{"record":{"id":"43aa6c76f6f806a8","repo":"golang/go","slug":"invalid-pkg-config-package-name-s","errorCode":null,"errorMessage":"invalid pkg-config package name: %s","messagePattern":"invalid pkg-config package name: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/work/exec.go","lineNumber":2072,"sourceCode":"func (b *Builder) getPkgConfigFlags(a *Action, p *load.Package) (cflags, ldflags []string, err error) {\n\tsh := b.Shell(a)\n\tif pcargs := p.CgoPkgConfig; len(pcargs) > 0 {\n\t\t// pkg-config permits arguments to appear anywhere in\n\t\t// the command line. Move them all to the front, before --.\n\t\tvar pcflags []string\n\t\tvar pkgs []string\n\t\tfor _, pcarg := range pcargs {\n\t\t\tif pcarg == \"--\" {\n\t\t\t\t// We're going to add our own \"--\" argument.\n\t\t\t} else if strings.HasPrefix(pcarg, \"--\") {\n\t\t\t\tpcflags = append(pcflags, pcarg)\n\t\t\t} else {\n\t\t\t\tpkgs = append(pkgs, pcarg)\n\t\t\t}\n\t\t}\n\t\tfor _, pkg := range pkgs {\n\t\t\tif !load.SafeArg(pkg) {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"invalid pkg-config package name: %s\", pkg)\n\t\t\t}\n\t\t}\n\n\t\tif err := checkPkgConfigFlags(\"\", \"pkg-config\", pcflags); err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tvar out []byte\n\t\tout, err = sh.runOut(p.Dir, nil, b.PkgconfigCmd(), \"--cflags\", pcflags, \"--\", pkgs)\n\t\tif err != nil {\n\t\t\tdesc := b.PkgconfigCmd() + \" --cflags \" + strings.Join(pcflags, \" \") + \" -- \" + strings.Join(pkgs, \" \")\n\t\t\treturn nil, nil, sh.reportCmd(desc, \"\", out, err)\n\t\t}\n\t\tif len(out) > 0 {\n\t\t\tcflags, err = splitPkgConfigOutput(bytes.TrimSpace(out))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}","sourceCodeStart":2054,"sourceCodeEnd":2090,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/work/exec.go#L2054-L2090","documentation":"Before invoking pkg-config, the go command validates each package-name argument with load.SafeArg, which rejects names whose first byte is not alphanumeric, '.', '_', '/', or a multibyte rune. If a name fails, the build aborts before pkg-config runs. This stops malformed or hostile package names (e.g. those starting with '-', '$', '*', '~', '(') from being passed to the shell or pkg-config.","triggerScenarios":"Fires in the cgo flags setup while iterating the pkgs slice (non-flag arguments after --) when load.SafeArg(pkg) returns false for a name from a // #cgo pkg-config: directive.","commonSituations":"A .go file with `// #cgo pkg-config: -foo`, `// #cgo pkg-config: $VAR`, or any name whose first character is a shell metacharacter or dash.","solutions":["Check every // #cgo pkg-config: directive in your Go source for invalid leading characters","Use only standard pkg-config package names (start with a letter, digit, '.', '_', or '/')","Verify the package exists: `pkg-config --exists <name>`"],"exampleFix":"// before (in .go source)\n// #cgo pkg-config: -lmylib\n// after\n// #cgo pkg-config: mylib","handlingStrategy":"validation","validationCode":"// Validate a cgo pkg-config name like load.SafeArg does\nfunc safePkgConfigName(name string) bool {\n    if name == \"\" { return false }\n    c := name[0]\n    return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' ||\n        'a' <= c && c <= 'z' || c == '.' || c == '_' ||\n        c == '/' || c >= 0x80\n}\nif !safePkgConfigName(pcName) {\n    return fmt.Errorf(\"unsafe pkg-config name: %s\", pcName)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start every // #cgo pkg-config: name with a letter, digit, '.', '_', or '/'","Never put flags (leading '-') or shell vars (leading '$') in the pkg-config directive","Verify with `pkg-config --exists <name>` before building"],"tags":["go-toolchain","cgo","pkg-config","security","validation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}