{"record":{"id":"eed1e00fe1810458","repo":"hashicorp/packer","slug":"specversion-is-required","errorCode":null,"errorMessage":"specVersion is required","messagePattern":"specVersion is required","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"provisioner/hcp-sbom/validate.go","lineNumber":44,"sourceCode":"\treturn e.Err\n}\n\n// ValidateCycloneDX is a validation for CycloneDX in JSON format.\nfunc validateCycloneDX(content []byte) error {\n\tdecoder := cyclonedx.NewBOMDecoder(bytes.NewBuffer(content), cyclonedx.BOMFileFormatJSON)\n\tbom := new(cyclonedx.BOM)\n\tif err := decoder.Decode(bom); err != nil {\n\t\treturn fmt.Errorf(\"error parsing CycloneDX SBOM: %w\", err)\n\t}\n\n\tif !strings.EqualFold(bom.BOMFormat, \"CycloneDX\") {\n\t\treturn &ValidationError{\n\t\t\tErr: fmt.Errorf(\"invalid bomFormat: %q, expected CycloneDX\", bom.BOMFormat),\n\t\t}\n\t}\n\tif bom.SpecVersion.String() == \"\" {\n\t\treturn &ValidationError{\n\t\t\tErr: fmt.Errorf(\"specVersion is required\"),\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// validateSPDX is a validation for SPDX in JSON format.\nfunc validateSPDX(content []byte) error {\n\tdoc, err := spdxjson.Read(bytes.NewBuffer(content))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error parsing SPDX JSON file: %w\", err)\n\t}\n\n\tif doc.SPDXVersion == \"\" {\n\t\treturn &ValidationError{\n\t\t\tErr: fmt.Errorf(\"missing SPDXVersion\"),\n\t\t}\n\t}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/provisioner/hcp-sbom/validate.go#L26-L62","documentation":"validateCycloneDX requires a non-empty bom.SpecVersion after successful decode; this ValidationError is thrown when the CycloneDX document lacks a specVersion (or it is empty). A CycloneDX SBOM without a spec version cannot be mapped to a concrete schema version, so it is rejected.","triggerScenarios":"Content has bomFormat \"CycloneDX\" and decodes, but the specVersion field is missing or empty in the JSON, so bom.SpecVersion.String() returns \"\"; reached via validateSBOM when the SPDX probe failed first.","commonSituations":"Hand-crafted or hand-trimmed CycloneDX JSON that dropped \"specVersion\"; a broken generator producing partial documents; aggressive post-processing that stripped fields from the SBOM.","solutions":["Add a valid \"specVersion\" (e.g. \"1.5\", \"1.4\") to the top-level CycloneDX JSON object.","Re-generate the SBOM with the upstream tool rather than hand-editing.","Validate with cyclonedx-cli validate to confirm the document conforms to the declared spec version.","If generation is scripted, check no jq/transform step removes specVersion."],"exampleFix":"// before\n{ \"bomFormat\": \"CycloneDX\", \"components\": [] }\n// after\n{ \"bomFormat\": \"CycloneDX\", \"specVersion\": \"1.5\", \"components\": [] }","handlingStrategy":"validation","validationCode":"var probe struct {\n\tBOMFormat   string `json:\"bomFormat\"`\n\tSpecVersion string `json:\"specVersion\"`\n}\nif err := json.Unmarshal(content, &probe); err != nil {\n\treturn err\n}\nif probe.SpecVersion == \"\" {\n\treturn fmt.Errorf(\"specVersion missing from CycloneDX SBOM\")\n}","typeGuard":"func hasSpecVersion(b any) bool {\n\tm, ok := b.(map[string]any)\n\tif !ok { return false }\n\tsv, _ := m[\"specVersion\"].(string)\n\treturn sv != \"\"\n}","tryCatchPattern":"var vErr *hcp_sbom.ValidationError\nif err := processSBOM(); err != nil {\n\tif errors.As(err, &vErr) && strings.Contains(vErr.Error(), \"specVersion is required\") {\n\t\t// regenerate the SBOM; do not hand-patch specVersion\n\t}\n}","preventionTips":["Never strip top-level fields (specVersion, bomFormat) when post-processing SBOM JSON.","Pin a CycloneDX spec version (1.4/1.5) in your generator configuration.","Add a schema-validation CI step (cyclonedx-cli validate) before Packer runs.","Regenerate rather than hand-edit SBOM documents."],"tags":["sbom","cyclonedx","validation","schema"],"backgroundTag":"invalid-sbom-format","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}