{"record":{"id":"2bf2fb7a0ba97f05","repo":"hashicorp/nomad","slug":"invalid-character-in-cni-arg-value-q","errorCode":null,"errorMessage":"invalid ';' character in CNI arg value %q","messagePattern":"invalid ';' character in CNI arg value %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":7399,"sourceCode":"\t\tif net.CNI != nil {\n\t\t\tfor k, v := range net.CNI.Args {\n\t\t\t\tif cniArgKeys.Contains(k) {\n\t\t\t\t\terr := fmt.Errorf(\"duplicate CNI arg %q\", k)\n\t\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t\t} else {\n\t\t\t\t\tcniArgKeys.Insert(k)\n\t\t\t\t}\n\t\t\t\t// CNI_ARGS is a \";\"-separated string of \"key=val\", so a \";\"\n\t\t\t\t// in either key or val would confuse plugins (or libraries)\n\t\t\t\t// that parse that string.\n\t\t\t\t// Pre-validating this here protects job authors from submitting\n\t\t\t\t// a job that will most likely error later on the client anyway.\n\t\t\t\tif strings.Contains(k, \";\") {\n\t\t\t\t\terr := fmt.Errorf(\"invalid ';' character in CNI arg key %q\", k)\n\t\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t\t}\n\t\t\t\tif strings.Contains(v, \";\") {\n\t\t\t\t\terr := fmt.Errorf(\"invalid ';' character in CNI arg value %q\", v)\n\t\t\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate the hostname field to be a valid DNS name. If the parameter\n\t\t// looks like it includes an interpolation value, we skip this. It\n\t\t// would be nice to validate additional parameters, but this isn't the\n\t\t// right place.\n\t\tif net.Hostname != \"\" && !strings.Contains(net.Hostname, \"${\") {\n\t\t\tif _, ok := dns.IsDomainName(net.Hostname); !ok {\n\t\t\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Hostname is not a valid DNS name\"))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check for duplicate tasks or port labels, and no duplicated static ports\n\tfor _, task := range tg.Tasks {","sourceCodeStart":7381,"sourceCodeEnd":7417,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L7381-L7417","documentation":"Nomad rejects CNI arguments (cni_args) whose key or value contains a semicolon, because semicolons are the CNI_ARGS delimiter (key=value;key2=value2) and would allow argument injection/spoofing into the CNI plugin invocation. During group network validation, each arg is scanned with strings.Contains and appended to a multi-error.","triggerScenarios":"Defining a task group network block with cni_args where any key or value contains the ';' character, e.g. cni_args = [\"FOO=bar;baz\"], then submitting the job (job register/validate runs Validate).","commonSituations":"Copy-pasting CNI args from a Linux environment where semicolons are used as list separators; attempting to pass multiple CNI args in one string instead of separate list entries; template or env substitution injecting ';'.","solutions":["Remove the ';' from the CNI arg value, splitting into separate cni_args entries at the ';' delimiter.","Encode the ';' (e.g. percent-escape or URL-encode) if the CNI plugin supports it and Nomad's version permits escaping.","Validate the args locally with strings.Contains(v, \";\") before submitting the job spec."],"exampleFix":"// before\nnetwork { cni_args = [\"K=V1;V2\"] }\n// after\nnetwork { cni_args = [\"K=V1\", \"K2=V2\"] }","handlingStrategy":"validation","validationCode":"for i, arg := range cniArgs {\n  kv := strings.SplitN(arg, \"=\", 2)\n  if len(kv) != 2 { return fmt.Errorf(\"cni_args[%d] not key=value\", i) }\n  if strings.Contains(kv[0], \";\") || strings.Contains(kv[1], \";\") {\n    return fmt.Errorf(\"cni_args[%d] contains ';'\", i)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep cni_args entries as single key=value pairs without separators","Escape or split any ';' before building the job spec","Validate job specs with nomad job validate in CI"],"tags":["nomad","cni","validation","networking"],"backgroundTag":"invalid-config-value","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}