{"record":{"id":"960337b204b367c7","repo":"docker/cli","slug":"invalid-security-opt-q","errorCode":null,"errorMessage":"invalid --security-opt: %q","messagePattern":"invalid --security-opt: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/container/opts.go","lineNumber":937,"sourceCode":"\nfunc parseLoggingOpts(loggingDriver string, loggingOpts []string) (map[string]string, error) {\n\tloggingOptsMap := opts.ConvertKVStringsToMap(loggingOpts)\n\tif loggingDriver == \"none\" && len(loggingOpts) > 0 {\n\t\treturn map[string]string{}, fmt.Errorf(\"invalid logging opts for driver %s\", loggingDriver)\n\t}\n\treturn loggingOptsMap, nil\n}\n\n// takes a local seccomp daemon, reads the file contents for sending to the daemon\nfunc parseSecurityOpts(securityOpts []string) ([]string, error) {\n\tfor key, opt := range securityOpts {\n\t\tk, v, ok := strings.Cut(opt, \"=\")\n\t\tif !ok && k != \"no-new-privileges\" {\n\t\t\tk, v, ok = strings.Cut(opt, \":\")\n\t\t}\n\t\tif (!ok || v == \"\") && k != \"no-new-privileges\" {\n\t\t\t// \"no-new-privileges\" is the only option that does not require a value.\n\t\t\treturn securityOpts, fmt.Errorf(\"invalid --security-opt: %q\", opt)\n\t\t}\n\t\tif k == \"seccomp\" {\n\t\t\tswitch v {\n\t\t\tcase seccompProfileDefault, seccompProfileUnconfined:\n\t\t\t\t// known special names for built-in profiles, nothing to do.\n\t\t\tdefault:\n\t\t\t\t// value may be a filename, in which case we send the profile's\n\t\t\t\t// content if it's valid JSON.\n\t\t\t\tf, err := os.ReadFile(v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn securityOpts, fmt.Errorf(\"opening seccomp profile (%s) failed: %w\", v, err)\n\t\t\t\t}\n\t\t\t\tvar b bytes.Buffer\n\t\t\t\tif err := json.Compact(&b, f); err != nil {\n\t\t\t\t\treturn securityOpts, fmt.Errorf(\"compacting json for seccomp profile (%s) failed: %w\", v, err)\n\t\t\t\t}\n\t\t\t\tsecurityOpts[key] = \"seccomp=\" + b.String()\n\t\t\t}","sourceCodeStart":919,"sourceCodeEnd":955,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/container/opts.go#L919-L955","documentation":"Thrown by parseSecurityOpts when a --security-opt value cannot be split into key=value (or key:value) and is not the single valueless option 'no-new-privileges'. The CLI requires every security option except 'no-new-privileges' to carry a value. This is a client-side validation performed before the request reaches the daemon.","triggerScenarios":"Calling `docker run --security-opt <bare-word>` where the token contains neither '=' nor ':', e.g. `--security-opt seccomp` or `--security-opt apparmor`. The function first tries Cut on '=', then on ':', and only 'no-new-privileges' is exempt from requiring a value.","commonSituations":"Forgetting the value when enabling seccomp/apparmor profiles; typoing a flag like `--security-opt no-new-privileges:true` (the colon-split makes k='no-new-privileges', v='true' which is accepted, but bare `--security-opt no-new` fails); copy-pasting partial examples from docs.","solutions":["Add a value via '=' or ':' separator: --security-opt seccomp=unconfined or --security-opt seccomp:unconfined","Use the exact bare keyword only for the valueless option: --security-opt no-new-privileges","For apparmor, use --security-opt apparmor=<profile-name>"],"exampleFix":"# before\ndocker run --security-opt seccomp\n# after\ndocker run --security-opt seccomp=unconfined","handlingStrategy":"validation","validationCode":"// Validate --security-opt tokens before passing to the run/create call.\nfunc validSecurityOpt(opt string) bool {\n    if opt == \"no-new-privileges\" {\n        return true\n    }\n    if _, _, ok := strings.Cut(opt, \"=\"); ok {\n        return true\n    }\n    if _, _, ok := strings.Cut(opt, \":\"); ok {\n        return true\n    }\n    return false\n}\n\nfor _, o := range securityOpts {\n    if !validSecurityOpt(o) {\n        return fmt.Errorf(\"refusing bad --security-opt %q\", o)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Allowlist known security option keys (seccomp, apparmor, systempaths, no-new-privileges) in your wrapper","Write a preflight linter that rejects valueless tokens other than no-new-privileges"],"tags":["docker","security-opt","seccomp","cli-validation"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}