Summary
Semgrep alerts #628 and #627 (created 2026-06-16, open 20 days) flag unescaped fmt.Sprintf injections into GraphQL mutation strings in pkg/cli/project_command.go.
File: pkg/cli/project_command.go
Rule: workflow-graphql-id-unescaped (CWE-89 — GraphQL injection)
Severity: Warning (Semgrep)
Affected locations
| Alert |
Function |
Line |
Injected value |
| #628 |
linkProjectToRepo() |
368 |
projectId and repositoryId from prior API responses |
| #627 |
createProject() |
295 |
ownerId from getOwnerNodeId() — inconsistently unescaped vs title (which uses escapeGraphQLString) |
Tier & Risk Scoring
| Dimension |
Score |
Notes |
| Exposure amplification |
2 |
Affects CLI project management commands; requires authenticated caller |
| Patchability |
1 |
Trivial — wrap with escapeGraphQLString() or use parameterized variables |
| Detectability |
3 |
Would surface as GraphQL parse error or unexpected behavior |
| Operational fragility |
2 |
Scoped to project CLI commands |
| Ownership confidence |
3 |
No assignee for 20 days |
| Aggregate |
11 |
Tier B — Open With Conditions |
SLA: High — fix within 7 days.
Root Cause
In createProject() (line 295), ownerId is injected raw into the mutation string via fmt.Sprintf, while the title argument on the same call uses escapeGraphQLString(title). This is an inconsistency that creates a defense-in-depth gap: if the GitHub API ever returns a node ID with special characters (e.g., in a future API change), it could cause a GraphQL injection.
In linkProjectToRepo() (line 368), both projectId and repositoryId are injected without escaping.
While GitHub API node IDs are currently opaque base64-like strings with low direct attacker control, the inconsistent escaping violates the principle of defense-in-depth.
Recommended Fix
Option A — Apply escapeGraphQLString() to all node ID arguments:
// createProject() — line 295
mutation = fmt.Sprintf(`...`, escapeGraphQLString(ownerId), escapeGraphQLString(title))
// linkProjectToRepo() — line 368
mutation = fmt.Sprintf(`...`, escapeGraphQLString(projectId), escapeGraphQLString(repositoryId))
Option B (preferred) — Use parameterized GraphQL variables via -f flags:
args := []string{"api", "graphql", "-f", fmt.Sprintf("ownerId=%s", ownerId), "-f", fmt.Sprintf("title=%s", title), "--raw-field", "query=" + staticMutation}
This eliminates string interpolation entirely.
Governance Context
Identified by the UK AI Open Code Risk & Resilience Governance weekly scan (2026-07-06). See discussion report for full tier classification and remediation queue.
References: CodeQL alert #628 · Semgrep alert #627 · §28806888795
Generated by UK AI Operational Resilience · 119.2 AIC · ⌖ 6.39 AIC · ⊞ 5.2K · ◷
Summary
Semgrep alerts #628 and #627 (created 2026-06-16, open 20 days) flag unescaped
fmt.Sprintfinjections into GraphQL mutation strings inpkg/cli/project_command.go.File:
pkg/cli/project_command.goRule:
workflow-graphql-id-unescaped(CWE-89 — GraphQL injection)Severity: Warning (Semgrep)
Affected locations
linkProjectToRepo()projectIdandrepositoryIdfrom prior API responsescreateProject()ownerIdfromgetOwnerNodeId()— inconsistently unescaped vstitle(which usesescapeGraphQLString)Tier & Risk Scoring
escapeGraphQLString()or use parameterized variablesSLA: High — fix within 7 days.
Root Cause
In
createProject()(line 295),ownerIdis injected raw into the mutation string viafmt.Sprintf, while thetitleargument on the same call usesescapeGraphQLString(title). This is an inconsistency that creates a defense-in-depth gap: if the GitHub API ever returns a node ID with special characters (e.g., in a future API change), it could cause a GraphQL injection.In
linkProjectToRepo()(line 368), bothprojectIdandrepositoryIdare injected without escaping.While GitHub API node IDs are currently opaque base64-like strings with low direct attacker control, the inconsistent escaping violates the principle of defense-in-depth.
Recommended Fix
Option A — Apply
escapeGraphQLString()to all node ID arguments:Option B (preferred) — Use parameterized GraphQL variables via
-fflags:This eliminates string interpolation entirely.
Governance Context
Identified by the UK AI Open Code Risk & Resilience Governance weekly scan (2026-07-06). See discussion report for full tier classification and remediation queue.
References: CodeQL alert #628 · Semgrep alert #627 · §28806888795