{"record":{"id":"952eccf1984fc1fa","repo":"golang/go","slug":"invalid-flag-in-s-s-s-see-https-go-dev-s-in","errorCode":null,"errorMessage":"invalid flag in %s: %s %s (see https://go.dev/s/invalidflag)","messagePattern":"invalid flag in (.+?): (.+?) (.+?) \\(see https://go\\.dev/s/invalidflag\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/work/security.go","lineNumber":460,"sourceCode":"\t\t\t\t\tstrings.HasPrefix(arg, \"-Wl,\") &&\n\t\t\t\t\tstrings.HasPrefix(list[i+1], \"-Wl,\") &&\n\t\t\t\t\tload.SafeArg(list[i+1][4:]) &&\n\t\t\t\t\t!strings.Contains(list[i+1][4:], \",\") {\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue Args\n\t\t\t\t}\n\n\t\t\t\t// Permit -I= /path, -I $SYSROOT.\n\t\t\t\tif i+1 < len(list) && arg == \"-I\" {\n\t\t\t\t\tif (strings.HasPrefix(list[i+1], \"=\") || strings.HasPrefix(list[i+1], \"$SYSROOT\")) &&\n\t\t\t\t\t\tload.SafeArg(list[i+1][1:]) {\n\t\t\t\t\t\ti++\n\t\t\t\t\t\tcontinue Args\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif i+1 < len(list) {\n\t\t\t\t\treturn fmt.Errorf(\"invalid flag in %s: %s %s (see https://go.dev/s/invalidflag)\", source, arg, list[i+1])\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"invalid flag in %s: %s without argument (see https://go.dev/s/invalidflag)\", source, arg)\n\t\t\t}\n\t\t}\n\tBad:\n\t\treturn fmt.Errorf(\"invalid flag in %s: %s (see https://go.dev/s/invalidflag)\", source, arg)\n\t}\n\treturn nil\n}\n","sourceCodeStart":442,"sourceCodeEnd":470,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/work/security.go#L442-L470","documentation":"Thrown by checkFlags (the `Bad`-adjacent block) when a flag that takes an argument (e.g. `-I`) is followed by a value that does not satisfy validation. The flag's next token is captured and reported as `invalid flag in <source>: <flag> <value>`, pointing at the source (a #cgo line or env var).","triggerScenarios":"A #cgo CFLAGS line or CGO_CFLAGS entry like `-I -L` or `-I @file` where the argument is itself disallowed (e.g. unsafe per load.SafeArg, or matches an invalid pattern). checkFlags detects i+1 is in range and returns this two-token form.","commonSituations":"A vendored C library's #cgo line passes `-I` with a path containing shell metacharacters; CGO_CFLAGS crafted with a value flagged by SafeArg (absolute traversal, NUL bytes); copy-pasting gcc invocation snippets into #cgo verbatim.","solutions":["Inspect the flagged flag/value pair reported in the error and fix the offending token.","Ensure `-I`/`-L` paths are relative, well-formed, and pass load.SafeArg.","Run `go build -x` to see the exact flag list before validation.","Use CGO_CFLAGS_ALLOW (a valid regexp) only as a last-resort override."],"exampleFix":"// before\n// #cgo CFLAGS: -I ../../..\n\n// after\n// #cgo CFLAGS: -I ./include","handlingStrategy":"validation","validationCode":"// Pre-check cgo flag/arg pairs for suspicious values\nflags := strings.Fields(os.Getenv(\"CGO_CFLAGS\"))\nfor i := 0; i+1 < len(flags); i++ {\n    if flags[i] == \"-I\" || flags[i] == \"-L\" {\n        if !load.SafeArg(flags[i+1]) { // mirror go's own check\n            log.Fatalf(\"suspicious %s argument: %s\", flags[i], flags[i+1])\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep -I/-L paths relative and clean.","Avoid shell metacharacters in include/library paths.","Review vendored #cgo CFLAGS on update."],"tags":["go-toolchain","cgo","flags","security","validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}