From 499926221774d5fb21cdd92ebad147aacefe6f22 Mon Sep 17 00:00:00 2001 From: Javier Rodriguez Date: Fri, 17 Jul 2026 13:31:11 +0200 Subject: [PATCH 1/2] feat(materials): record checkmarx engine types from SARIF via scan.types annotation Enrich the SARIF crafter so a Checkmarx One report emits the shared chainloop.material.scan.types annotation, mirroring the native CHECKMARX_JSON crafter. Engine types are read from the (engine) ruleId suffix ast-cli appends to every rule, gated on Checkmarx detection, and normalized onto the canonical scan-type vocabulary via the existing checkmarxEngineToScanType map. Unrecognized engines are dropped so recognition fails closed and never over-claims for other tools. Assisted-by: Claude Code Signed-off-by: Javier Rodriguez Chainloop-Trace-Sessions: a306a5c2-d7a3-4c8c-b021-584300a909fe --- pkg/attestation/crafter/materials/sarif.go | 107 +++++++++++++++++ .../crafter/materials/sarif_test.go | 75 ++++++++++++ .../testdata/checkmarx-extra-engines.sarif | 97 ++++++++++++++++ .../materials/testdata/checkmarx.sarif | 109 ++++++++++++++++++ 4 files changed, 388 insertions(+) create mode 100644 pkg/attestation/crafter/materials/testdata/checkmarx-extra-engines.sarif create mode 100644 pkg/attestation/crafter/materials/testdata/checkmarx.sarif diff --git a/pkg/attestation/crafter/materials/sarif.go b/pkg/attestation/crafter/materials/sarif.go index a8ebf0d5f..74849a3ad 100644 --- a/pkg/attestation/crafter/materials/sarif.go +++ b/pkg/attestation/crafter/materials/sarif.go @@ -18,6 +18,9 @@ package materials import ( "context" "fmt" + "maps" + "slices" + "strings" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" api "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/api/attestation/v1" @@ -26,6 +29,12 @@ import ( "github.com/rs/zerolog" ) +// checkmarxVendorTag is the lower-cased vendor marker Checkmarx One stamps on +// every SARIF rule (properties.tags == ["security","checkmarx",""]) and +// embeds in its driver name ("Checkmarx One"). Either signal identifies a +// Checkmarx SARIF export. +const checkmarxVendorTag = "checkmarx" + type SARIFCrafter struct { backend *casclient.CASBackend *crafterCommon @@ -84,4 +93,102 @@ func (i *SARIFCrafter) injectAnnotations(m *api.Attestation_Material, doc *sarif if driver.Version != nil && *driver.Version != "" { m.Annotations[AnnotationToolVersionKey] = *driver.Version } + + // Checkmarx One exports every engine (sast, sca, kics, containers, sscs) under + // a single driver, so the driver name alone cannot tell attestation-level + // policies which analyses actually ran. Record the distinct engine types on the + // shared scan.types annotation, mirroring the native CHECKMARX_JSON crafter, so + // those policies (e.g. *-scan-present) match uniformly across material kinds. + if scanTypes := i.checkmarxScanTypes(doc); scanTypes != "" { + m.Annotations[AnnotationScanTypesKey] = scanTypes + } +} + +// checkmarxScanTypes inspects a Checkmarx One SARIF report and returns its +// distinct scan types, normalized onto the canonical scan-type vocabulary and +// formatted for the AnnotationScanTypesKey annotation (sorted, comma-joined; e.g. +// "iac,sast,sca"). It returns "" for a non-Checkmarx report or one whose engines +// we cannot classify, so recognition fails closed and never over-claims for other +// tools. +// +// Checkmarx's SARIF export carries no dedicated engine field (the EngineID +// property only exists in its sonar export). It does append a "()" suffix +// to every rule id (e.g. "Reflected_XSS (sast)"), verified against ast-cli's +// findRuleID; that suffix is the engine signal we read here. The Checkmarx-only +// engine names (kics, sscs, containers) are why we gate on isCheckmarxSARIF: a +// generic SARIF must never be mapped onto this vocabulary. +func (i *SARIFCrafter) checkmarxScanTypes(doc *sarif.Report) string { + if !isCheckmarxSARIF(doc) { + return "" + } + + scanTypes := map[string]struct{}{} + for _, run := range doc.Runs { + if run == nil || run.Tool == nil || run.Tool.Driver == nil { + continue + } + for _, rule := range run.Tool.Driver.Rules { + if rule == nil || rule.ID == nil { + continue + } + engine := ruleIDEngineSuffix(*rule.ID) + if engine == "" { + continue + } + scanType, ok := checkmarxEngineToScanType[strings.ToLower(engine)] + if !ok { + // Fail closed: an engine we cannot classify is dropped so no + // vendor-specific value leaks into the annotation. + i.logger.Debug().Str("engine", engine).Msg("unrecognized Checkmarx engine type, omitting from scan.types annotation") + continue + } + scanTypes[scanType] = struct{}{} + } + } + + if len(scanTypes) == 0 { + return "" + } + return strings.Join(slices.Sorted(maps.Keys(scanTypes)), ",") +} + +// isCheckmarxSARIF reports whether doc looks like a Checkmarx One SARIF export. +// Checkmarx stamps its driver name ("Checkmarx One") and tags every rule with +// "checkmarx"; either signal is enough. +func isCheckmarxSARIF(doc *sarif.Report) bool { + for _, run := range doc.Runs { + if run == nil || run.Tool == nil || run.Tool.Driver == nil { + continue + } + driver := run.Tool.Driver + if driver.Name != nil && strings.Contains(strings.ToLower(*driver.Name), checkmarxVendorTag) { + return true + } + for _, rule := range driver.Rules { + if rule == nil || rule.Properties == nil { + continue + } + for _, tag := range rule.Properties.Tags { + if strings.ToLower(tag) == checkmarxVendorTag { + return true + } + } + } + } + return false +} + +// ruleIDEngineSuffix extracts the engine identifier from the trailing +// "()" that ast-cli appends to every SARIF rule id (e.g. +// "Reflected_XSS (sast)" -> "sast"). It returns "" when no such suffix is present. +func ruleIDEngineSuffix(id string) string { + id = strings.TrimSpace(id) + if !strings.HasSuffix(id, ")") { + return "" + } + open := strings.LastIndex(id, "(") + if open < 0 { + return "" + } + return strings.TrimSpace(id[open+1 : len(id)-1]) } diff --git a/pkg/attestation/crafter/materials/sarif_test.go b/pkg/attestation/crafter/materials/sarif_test.go index b0c602a95..58c69db62 100644 --- a/pkg/attestation/crafter/materials/sarif_test.go +++ b/pkg/attestation/crafter/materials/sarif_test.go @@ -131,6 +131,81 @@ func TestSARIFCraft(t *testing.T) { } } +func TestSARIFCraft_ScanTypes(t *testing.T) { + testCases := []struct { + name string + filePath string + // annotations lists annotation keys that must be set to the given value. + annotations map[string]string + // absentAnnotations lists annotation keys that must NOT be set. A + // non-Checkmarx SARIF (or one with only unrecognized engines) advertises no + // engine types, so scan.types must be omitted (fail closed) rather than set + // to an empty value. + absentAnnotations []string + }{ + { + // Checkmarx One SARIF bundling multiple engines under a single driver. + // Engine types are read from rules[].properties.tags / the "(engine)" + // ruleId suffix and normalized to the canonical vocabulary (kics -> iac), + // sorted and comma-joined. + name: "checkmarx multi-engine SARIF", + filePath: "./testdata/checkmarx.sarif", + annotations: map[string]string{ + "chainloop.material.scan.types": "iac,sast,sca", + }, + }, + { + // containers -> container and sscs -> supply-chain map to the canonical + // vocabulary; an unmapped engine ("future-engine") is dropped so no + // vendor-specific value leaks into the annotation. + name: "checkmarx SARIF with extra + unmapped engines", + filePath: "./testdata/checkmarx-extra-engines.sarif", + annotations: map[string]string{ + "chainloop.material.scan.types": "container,supply-chain", + }, + }, + { + // A non-Checkmarx SARIF (tfsec) must never get a scan.types annotation: + // the engine normalization is Checkmarx-specific, so recognition fails + // closed for other tools rather than over-claiming. + name: "non-checkmarx SARIF gets no scan.types", + filePath: "./testdata/report.sarif", + absentAnnotations: []string{"chainloop.material.scan.types"}, + }, + } + + l := zerolog.Nop() + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + uploader := mUploader.NewUploader(t) + uploader.On("Upload", context.TODO(), mock.Anything, mock.Anything, mock.Anything). + Return(&casclient.UpDownStatus{ + Digest: "deadbeef", + Filename: "report.sarif", + }, nil) + + schema := &contractAPI.CraftingSchema_Material{ + Name: "test", + Type: contractAPI.CraftingSchema_Material_SARIF, + } + backend := &casclient.CASBackend{Uploader: uploader} + crafter, err := materials.NewSARIFCrafter(schema, backend, &l) + require.NoError(t, err) + + got, err := crafter.Craft(context.TODO(), tc.filePath) + require.NoError(t, err) + + for k, v := range tc.annotations { + assert.Equal(t, v, got.Annotations[k], "annotation %q", k) + } + for _, k := range tc.absentAnnotations { + _, ok := got.Annotations[k] + assert.False(t, ok, "annotation %q must not be set", k) + } + }) + } +} + func TestSARIFCraft_SkipUpload(t *testing.T) { testCases := []struct { name string diff --git a/pkg/attestation/crafter/materials/testdata/checkmarx-extra-engines.sarif b/pkg/attestation/crafter/materials/testdata/checkmarx-extra-engines.sarif new file mode 100644 index 000000000..184ded9dc --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/checkmarx-extra-engines.sarif @@ -0,0 +1,97 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Checkmarx One", + "version": "1.0", + "informationUri": "https://checkmarx.com/resource/documents/en/34965-67042-checkmarx-one.html", + "rules": [ + { + "id": "openssl - CVE-2022-0001 (containers)", + "name": "openssl - CVE-2022-0001", + "helpUri": "https://checkmarx.com", + "help": { + "text": "", + "markdown": "" + }, + "fullDescription": { + "text": "Vulnerable package in container image" + }, + "properties": { + "security-severity": "9.0", + "name": "openssl - CVE-2022-0001", + "id": "openssl - CVE-2022-0001 (containers)", + "description": "Vulnerable package in container image", + "tags": ["security", "checkmarx", "containers"] + } + }, + { + "id": "Missing branch protection (sscs)", + "name": "Missing branch protection", + "helpUri": "https://checkmarx.com", + "help": { + "text": "", + "markdown": "" + }, + "fullDescription": { + "text": "Repository is missing branch protection" + }, + "properties": { + "security-severity": "6.0", + "name": "Missing branch protection", + "id": "Missing branch protection (sscs)", + "description": "Repository is missing branch protection", + "tags": ["security", "checkmarx", "sscs"] + } + }, + { + "id": "Some future finding (future-engine)", + "name": "Some future finding", + "helpUri": "https://checkmarx.com", + "help": { + "text": "", + "markdown": "" + }, + "fullDescription": { + "text": "Finding from an engine we do not classify yet" + }, + "properties": { + "security-severity": "5.0", + "name": "Some future finding", + "id": "Some future finding (future-engine)", + "description": "Finding from an engine we do not classify yet", + "tags": ["security", "checkmarx", "future-engine"] + } + } + ] + } + }, + "results": [ + { + "ruleId": "openssl - CVE-2022-0001 (containers)", + "level": "error", + "message": { + "text": "Vulnerable package openssl in image" + } + }, + { + "ruleId": "Missing branch protection (sscs)", + "level": "warning", + "message": { + "text": "Branch protection not enabled" + } + }, + { + "ruleId": "Some future finding (future-engine)", + "level": "note", + "message": { + "text": "Future engine finding" + } + } + ] + } + ] +} diff --git a/pkg/attestation/crafter/materials/testdata/checkmarx.sarif b/pkg/attestation/crafter/materials/testdata/checkmarx.sarif new file mode 100644 index 000000000..740aabef3 --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/checkmarx.sarif @@ -0,0 +1,109 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Checkmarx One", + "version": "1.0", + "informationUri": "https://checkmarx.com/resource/documents/en/34965-67042-checkmarx-one.html", + "rules": [ + { + "id": "Reflected_XSS (sast)", + "name": "ReflectedXss", + "helpUri": "https://checkmarx.com", + "help": { + "text": "", + "markdown": "" + }, + "fullDescription": { + "text": "Reflected XSS" + }, + "properties": { + "security-severity": "8.0", + "name": "Reflected_XSS", + "id": "Reflected_XSS (sast)", + "description": "Reflected XSS", + "tags": ["security", "checkmarx", "sast"] + } + }, + { + "id": "CVE-2021-1234 (sca)", + "name": "Cve20211234", + "helpUri": "https://checkmarx.com", + "help": { + "text": "", + "markdown": "" + }, + "fullDescription": { + "text": "Vulnerable dependency" + }, + "properties": { + "security-severity": "9.0", + "name": "CVE-2021-1234", + "id": "CVE-2021-1234 (sca)", + "description": "Vulnerable dependency", + "tags": ["security", "checkmarx", "sca"] + } + }, + { + "id": "Passwords And Secrets - Generic Password (kics)", + "name": "Passwords And Secrets - Generic Password", + "helpUri": "https://checkmarx.com", + "help": { + "text": "", + "markdown": "" + }, + "fullDescription": { + "text": "Generic password in IaC file" + }, + "properties": { + "security-severity": "7.0", + "name": "Passwords And Secrets - Generic Password", + "id": "Passwords And Secrets - Generic Password (kics)", + "description": "Generic password in IaC file", + "tags": ["security", "checkmarx", "kics"] + } + } + ] + } + }, + "results": [ + { + "ruleId": "Reflected_XSS (sast)", + "level": "error", + "message": { + "text": "Reflected XSS in handler.go" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "handler.go" + }, + "region": { + "startLine": 42 + } + } + } + ] + }, + { + "ruleId": "CVE-2021-1234 (sca)", + "level": "error", + "message": { + "text": "Vulnerable dependency detected" + } + }, + { + "ruleId": "Passwords And Secrets - Generic Password (kics)", + "level": "warning", + "message": { + "text": "Generic password found in main.tf" + } + } + ] + } + ] +} From b0f522c1bd6ec412b454929edcd8e4889815020e Mon Sep 17 00:00:00 2001 From: Javier Rodriguez Date: Fri, 17 Jul 2026 14:29:01 +0200 Subject: [PATCH 2/2] fix(materials): make SARIF scan.types findings-based and per-run Address review feedback on the Checkmarx SARIF scan.types extraction: - Read the engine from each finding's ruleId instead of the driver's rule catalog, so a report carrying rule metadata without matching findings no longer overstates scan.types. This keeps the annotation findings-based, consistent with the native CHECKMARX_JSON crafter. - Detect and extract per run rather than gating on the whole document, so a multi-run SARIF that mixes a Checkmarx run with another tool's run no longer attributes the other tool's suffixed rule ids to Checkmarx. Assisted-by: Claude Code Signed-off-by: Javier Rodriguez Chainloop-Trace-Sessions: a306a5c2-d7a3-4c8c-b021-584300a909fe --- pkg/attestation/crafter/materials/sarif.go | 74 +++++++++---------- .../crafter/materials/sarif_test.go | 22 ++++++ .../testdata/checkmarx-multi-run.sarif | 59 +++++++++++++++ .../checkmarx-rules-without-findings.sarif | 66 +++++++++++++++++ 4 files changed, 184 insertions(+), 37 deletions(-) create mode 100644 pkg/attestation/crafter/materials/testdata/checkmarx-multi-run.sarif create mode 100644 pkg/attestation/crafter/materials/testdata/checkmarx-rules-without-findings.sarif diff --git a/pkg/attestation/crafter/materials/sarif.go b/pkg/attestation/crafter/materials/sarif.go index 74849a3ad..5dce15ab6 100644 --- a/pkg/attestation/crafter/materials/sarif.go +++ b/pkg/attestation/crafter/materials/sarif.go @@ -104,34 +104,36 @@ func (i *SARIFCrafter) injectAnnotations(m *api.Attestation_Material, doc *sarif } } -// checkmarxScanTypes inspects a Checkmarx One SARIF report and returns its -// distinct scan types, normalized onto the canonical scan-type vocabulary and -// formatted for the AnnotationScanTypesKey annotation (sorted, comma-joined; e.g. -// "iac,sast,sca"). It returns "" for a non-Checkmarx report or one whose engines -// we cannot classify, so recognition fails closed and never over-claims for other -// tools. +// checkmarxScanTypes inspects a SARIF report and returns the distinct scan types +// produced by its Checkmarx runs, normalized onto the canonical scan-type +// vocabulary and formatted for the AnnotationScanTypesKey annotation (sorted, +// comma-joined; e.g. "iac,sast,sca"). It returns "" when no Checkmarx run is +// present or none of its engines can be classified, so recognition fails closed +// and never over-claims for other tools. // +// Detection and extraction are both per run: a SARIF document may bundle several +// runs (e.g. an aggregated report mixing tools), and only a Checkmarx run's +// "()" suffixes use the vocabulary we normalize. Gating extraction on the +// individual run keeps another tool's rule ids from being attributed to Checkmarx. +// +// The engine is read from each finding's ruleId, not the driver's rule catalog: // Checkmarx's SARIF export carries no dedicated engine field (the EngineID -// property only exists in its sonar export). It does append a "()" suffix -// to every rule id (e.g. "Reflected_XSS (sast)"), verified against ast-cli's -// findRuleID; that suffix is the engine signal we read here. The Checkmarx-only -// engine names (kics, sscs, containers) are why we gate on isCheckmarxSARIF: a -// generic SARIF must never be mapped onto this vocabulary. +// property only exists in its sonar export), but ast-cli appends a "()" +// suffix to every result ruleId (e.g. "Reflected_XSS (sast)"), verified against +// ast-cli's findRuleID. Reading findings rather than tool.driver.rules (a catalog +// that need not correspond to findings) keeps the annotation findings-based, +// consistent with the native CHECKMARX_JSON crafter. func (i *SARIFCrafter) checkmarxScanTypes(doc *sarif.Report) string { - if !isCheckmarxSARIF(doc) { - return "" - } - scanTypes := map[string]struct{}{} for _, run := range doc.Runs { - if run == nil || run.Tool == nil || run.Tool.Driver == nil { + if !isCheckmarxRun(run) { continue } - for _, rule := range run.Tool.Driver.Rules { - if rule == nil || rule.ID == nil { + for _, result := range run.Results { + if result == nil || result.RuleID == nil { continue } - engine := ruleIDEngineSuffix(*rule.ID) + engine := ruleIDEngineSuffix(*result.RuleID) if engine == "" { continue } @@ -152,26 +154,24 @@ func (i *SARIFCrafter) checkmarxScanTypes(doc *sarif.Report) string { return strings.Join(slices.Sorted(maps.Keys(scanTypes)), ",") } -// isCheckmarxSARIF reports whether doc looks like a Checkmarx One SARIF export. -// Checkmarx stamps its driver name ("Checkmarx One") and tags every rule with -// "checkmarx"; either signal is enough. -func isCheckmarxSARIF(doc *sarif.Report) bool { - for _, run := range doc.Runs { - if run == nil || run.Tool == nil || run.Tool.Driver == nil { +// isCheckmarxRun reports whether a single SARIF run looks like a Checkmarx One +// export. Checkmarx stamps its driver name ("Checkmarx One") and tags every rule +// with "checkmarx"; either signal is enough. +func isCheckmarxRun(run *sarif.Run) bool { + if run == nil || run.Tool == nil || run.Tool.Driver == nil { + return false + } + driver := run.Tool.Driver + if driver.Name != nil && strings.Contains(strings.ToLower(*driver.Name), checkmarxVendorTag) { + return true + } + for _, rule := range driver.Rules { + if rule == nil || rule.Properties == nil { continue } - driver := run.Tool.Driver - if driver.Name != nil && strings.Contains(strings.ToLower(*driver.Name), checkmarxVendorTag) { - return true - } - for _, rule := range driver.Rules { - if rule == nil || rule.Properties == nil { - continue - } - for _, tag := range rule.Properties.Tags { - if strings.ToLower(tag) == checkmarxVendorTag { - return true - } + for _, tag := range rule.Properties.Tags { + if strings.ToLower(tag) == checkmarxVendorTag { + return true } } } diff --git a/pkg/attestation/crafter/materials/sarif_test.go b/pkg/attestation/crafter/materials/sarif_test.go index 58c69db62..bf84131da 100644 --- a/pkg/attestation/crafter/materials/sarif_test.go +++ b/pkg/attestation/crafter/materials/sarif_test.go @@ -164,6 +164,28 @@ func TestSARIFCraft_ScanTypes(t *testing.T) { "chainloop.material.scan.types": "container,supply-chain", }, }, + { + // Scan types are findings-based: the driver rule catalog lists sast, sca + // and kics rules, but only a sast finding is present, so scan.types must + // reflect just the engines that actually produced results (matching the + // native CHECKMARX_JSON crafter). + name: "checkmarx SARIF with rules but no findings for some engines", + filePath: "./testdata/checkmarx-rules-without-findings.sarif", + annotations: map[string]string{ + "chainloop.material.scan.types": "sast", + }, + }, + { + // A multi-run SARIF mixing a Checkmarx run (sast) with another tool's run + // whose rule ids reuse the "(engine)" suffix (sca) must only attribute the + // Checkmarx run's engines: detection and extraction are per run, so the + // other tool's findings never contaminate the annotation. + name: "multi-run SARIF only attributes checkmarx run engines", + filePath: "./testdata/checkmarx-multi-run.sarif", + annotations: map[string]string{ + "chainloop.material.scan.types": "sast", + }, + }, { // A non-Checkmarx SARIF (tfsec) must never get a scan.types annotation: // the engine normalization is Checkmarx-specific, so recognition fails diff --git a/pkg/attestation/crafter/materials/testdata/checkmarx-multi-run.sarif b/pkg/attestation/crafter/materials/testdata/checkmarx-multi-run.sarif new file mode 100644 index 000000000..303aad8d8 --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/checkmarx-multi-run.sarif @@ -0,0 +1,59 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Checkmarx One", + "version": "1.0", + "informationUri": "https://checkmarx.com/resource/documents/en/34965-67042-checkmarx-one.html", + "rules": [ + { + "id": "Reflected_XSS (sast)", + "name": "ReflectedXss", + "helpUri": "https://checkmarx.com", + "help": { "text": "", "markdown": "" }, + "fullDescription": { "text": "Reflected XSS" }, + "properties": { + "security-severity": "8.0", + "name": "Reflected_XSS", + "id": "Reflected_XSS (sast)", + "description": "Reflected XSS", + "tags": ["security", "checkmarx", "sast"] + } + } + ] + } + }, + "results": [ + { + "ruleId": "Reflected_XSS (sast)", + "level": "error", + "message": { "text": "Reflected XSS in handler.go" } + } + ] + }, + { + "tool": { + "driver": { + "name": "some-other-tool", + "informationUri": "https://example.com", + "rules": [ + { + "id": "Vulnerable dependency (sca)", + "shortDescription": { "text": "Vulnerable dependency" } + } + ] + } + }, + "results": [ + { + "ruleId": "Vulnerable dependency (sca)", + "level": "error", + "message": { "text": "Vulnerable dependency from a non-Checkmarx tool" } + } + ] + } + ] +} diff --git a/pkg/attestation/crafter/materials/testdata/checkmarx-rules-without-findings.sarif b/pkg/attestation/crafter/materials/testdata/checkmarx-rules-without-findings.sarif new file mode 100644 index 000000000..d9d97d9b5 --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/checkmarx-rules-without-findings.sarif @@ -0,0 +1,66 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Checkmarx One", + "version": "1.0", + "informationUri": "https://checkmarx.com/resource/documents/en/34965-67042-checkmarx-one.html", + "rules": [ + { + "id": "Reflected_XSS (sast)", + "name": "ReflectedXss", + "helpUri": "https://checkmarx.com", + "help": { "text": "", "markdown": "" }, + "fullDescription": { "text": "Reflected XSS" }, + "properties": { + "security-severity": "8.0", + "name": "Reflected_XSS", + "id": "Reflected_XSS (sast)", + "description": "Reflected XSS", + "tags": ["security", "checkmarx", "sast"] + } + }, + { + "id": "CVE-2021-1234 (sca)", + "name": "Cve20211234", + "helpUri": "https://checkmarx.com", + "help": { "text": "", "markdown": "" }, + "fullDescription": { "text": "Vulnerable dependency" }, + "properties": { + "security-severity": "9.0", + "name": "CVE-2021-1234", + "id": "CVE-2021-1234 (sca)", + "description": "Vulnerable dependency", + "tags": ["security", "checkmarx", "sca"] + } + }, + { + "id": "Passwords And Secrets - Generic Password (kics)", + "name": "Passwords And Secrets - Generic Password", + "helpUri": "https://checkmarx.com", + "help": { "text": "", "markdown": "" }, + "fullDescription": { "text": "Generic password in IaC file" }, + "properties": { + "security-severity": "7.0", + "name": "Passwords And Secrets - Generic Password", + "id": "Passwords And Secrets - Generic Password (kics)", + "description": "Generic password in IaC file", + "tags": ["security", "checkmarx", "kics"] + } + } + ] + } + }, + "results": [ + { + "ruleId": "Reflected_XSS (sast)", + "level": "error", + "message": { "text": "Reflected XSS in handler.go" } + } + ] + } + ] +}