Skip to content

Unchecked type assertion in pkg/cli/project_command.go — panics on malformed GraphQL response (#aw_sg18a1) #34580

@github-actions

Description

@github-actions

Summary

In pkg/cli/project_command.go:159, the GraphQL response field project["id"] is dereferenced with an unchecked single-value type assertion (string), while the same project map's "url" and "number" fields are checked with two-value , ok assertions a few lines below (lines 167, 172). A malformed or partial GitHub GraphQL response — id: null, missing field, or an unexpected scalar type — therefore panics the CLI process instead of returning a clean error.

Location

  • pkg/cli/project_command.go:159if err := linkProjectToRepo(ctx, project["id"].(string), config.Repo, config.Verbose); err != nil {
  • Compare with sibling validated reads at:
    • pkg/cli/project_command.go:167projectURL, ok := project["url"].(string)
    • pkg/cli/project_command.go:172projectNumberFloat, ok := project["number"].(float64)

Severity

High for the affected code path (project-create CLI flow):

  • The panic crashes gh aw project create --repo <slug> with a runtime stack trace instead of "failed to get project ID from response".
  • createProject (line 289) does validate the GraphQL envelope (datacreateProjectV2projectV2) but does not validate individual scalar fields, so id/url/number reach the caller as raw any.
  • Trust boundary: the value originates from a remote GitHub API call. Defense-in-depth is warranted.

Suggested Fix

Apply the same defensive pattern already used for url / number, BEFORE the linkProjectToRepo call so the early-return path is consistent:

projectID, ok := project["id"].(string)
if !ok || projectID == "" {
    return errors.New("failed to get project ID from response")
}

if config.Repo != "" {
    fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Linking project to repository %s...", config.Repo)))
    if err := linkProjectToRepo(ctx, projectID, config.Repo, config.Verbose); err != nil {
        fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to link project to repository: %v", err)))
    } else {
        fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("✓ Project linked to repository"))
    }
}

Adjacent Risky Sites (lower priority — local-literal / sync-pool patterns are safe-by-convention; flagged for awareness, not action)

File:Line Pattern Risk
pkg/cli/jsonworkflow_to_markdown.go:448 return intervalType.(string) Lower — intervalType is parts["_interval"] populated internally; map is private. Add defensive , ok if refactored.
pkg/cli/jsonworkflow_to_markdown.go:455 intervalToFuzzySchedule(intervalType.(string)) Same as above — duplicate site.
pkg/workflow/safe_outputs_workflow_helpers.go:41 tool["inputSchema"].(map[string]any)["required"] = required Safe-by-construction (literal 4 lines above), but a local var would be more refactor-resistant.
pkg/workflow/mcp_scripts_generator.go:61 inputSchema["properties"].(map[string]any) Same as above — literal-map safe.
pkg/workflow/yaml.go:173, repository_features_validation.go:185/212, pkg/cli/workflows.go:357 sync.Map.Load / sync.Pool.Get casts Idiomatic Go — only one type ever stored. Documented pattern. No change recommended.
pkg/linters/*/...:N (12 sites) pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) go/analysis framework idiom — guaranteed by framework. No change recommended.

Validation

  • gh aw project create --repo <slug> exits with the new error message instead of a panic when GraphQL returns a malformed id.
  • Existing tests still pass.
  • Optional: add a TestCreateProject_MissingID table case using a stubbed GraphQL response.

Estimated Effort

Small — ~6-line change, single file, mirrors an established local pattern.


Generated by Sergo — The Serena Go Expert (Run 18)
Strategy: reverify-plus-unchecked-type-assertion-audit

Generated by 🤖 Sergo - Serena Go Expert · opus47 25.4M ·

  • expires on Jun 1, 2026, 5:24 AM UTC

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions