Is your feature request related to a problem? Please describe.
Plumber currently outputs results in JSON, CycloneDX SBOM, PBOM, and terminal format. However, there is no way to surface Plumber findings in GitLab's Security Dashboard or the merge request security widget, which are the standard places where security teams review findings.
GitLab's security scanning ecosystem relies on a specific JSON report format (gl-sast-report.json), and there is an ongoing effort to support SARIF (Static Analysis Results Interchange Format) as a direct upload format. SARIF is already the standard output format for CodeQL, Semgrep, and most modern static analysis tools. Without SARIF support:
- Plumber findings are invisible to security teams who rely on the GitLab Security Dashboard
- Compliance results cannot be tracked alongside SAST/DAST/Secret Detection findings in a unified view
- There is no standard way to feed Plumber results into third-party security aggregation platforms (DefectDojo, Mobb, etc.)
Describe the solution you'd like
Add two new, independent flags to plumber analyze that produce additional output files alongside the existing --output behavior. The existing --output flag remains unchanged; these are additive:
--sarif <path>: writes a SARIF v2.1.0 compliant file to the given path
--glsast <path>: writes a GitLab SAST report (gl-sast-report.json schema) to the given path
These flags are not mutually exclusive. You can use none, one, or both in the same run, and they stack with --output:
# Existing behavior unchanged
plumber analyze --output results.json
# Add SARIF output alongside JSON
plumber analyze --output results.json --sarif plumber-results.sarif
# Add GitLab SAST report alongside JSON
plumber analyze --output results.json --glsast gl-sast-report.json
# All three at once
plumber analyze --output results.json --sarif plumber-results.sarif --glsast gl-sast-report.json
# SARIF only (no JSON)
plumber analyze --sarif plumber-results.sarif
GitLab CI integration
plumber-compliance:
stage: test
script:
- plumber analyze --glsast gl-sast-report.json --sarif plumber-results.sarif
artifacts:
reports:
sast: gl-sast-report.json
paths:
- plumber-results.sarif
SARIF mapping
Each Plumber control maps to a SARIF reportingDescriptor (rule), and each finding maps to a SARIF result:
| Plumber Concept |
SARIF Equivalent |
Control (e.g., containerImageMustNotUseForbiddenTags) |
reportingDescriptor in tool.driver.rules |
| Finding/Issue |
result in results array |
| Compliance score |
result.properties.complianceScore (custom property) |
| Job name / location |
result.locations[].physicalLocation |
| Severity |
result.level (error, warning, note) |
Implementation Hints
These are just ideas. Feel free to change the implementation.
- SARIF library: Use an existing Go SARIF library like
github.com/owenrumney/go-sarif it handles the full SARIF v2.1.0 schema and is well-maintained.
- New files: Create
output/sarif.go and output/gitlab_sast.go (or under control/ depending on architecture preference).
- CLI flags: Add
--sarif and --glsast as StringVar flags in cmd/analyze.go, each accepting a file path. When the flag value is non-empty, write the corresponding output after RunAnalysis() completes independently of --output.
- SARIF logic (
output/sarif.go):
- After
RunAnalysis() produces the AnalysisResult, convert it to SARIF format
- Each enabled control becomes a
reportingDescriptor with id, name, shortDescription, and helpUri (linking to Plumber docs)
- Each issue/finding within a control becomes a
result with ruleId, message, level, and locations
- Location points to the
.gitlab-ci.yml file with line number if available (from the merged CI config)
- Add Plumber-specific properties in
result.properties (compliance score, control category, etc.)
- GitLab SAST logic (
output/gitlab_sast.go):
Files Touched
output/sarif.go (new, SARIF conversion logic)
output/gitlab_sast.go (new, GitLab SAST format conversion)
cmd/analyze.go (add --sarif and --glsast string flags, call output writers when set)
go.mod / go.sum (add go-sarif dependency)
- Documentation update for the new output flags
Why It's Valuable
SARIF is the de facto standard for static analysis tool output. Supporting it unlocks three critical capabilities: (1) visibility in GitLab's Security Dashboard where security teams already work, (2) integration with third-party security platforms like DefectDojo, Mobb, and ASPM tools, and (3) standardized output that makes Plumber's results comparable with other security scanners. GitLab is actively exploring direct SARIF upload support, which would make this a future-proof investment. In the meantime, the --glsast flag provides immediate value by placing Plumber findings alongside SAST/DAST results in the merge request widget, with zero changes to how --output currently works.
Is your feature request related to a problem? Please describe.
Plumber currently outputs results in JSON, CycloneDX SBOM, PBOM, and terminal format. However, there is no way to surface Plumber findings in GitLab's Security Dashboard or the merge request security widget, which are the standard places where security teams review findings.
GitLab's security scanning ecosystem relies on a specific JSON report format (
gl-sast-report.json), and there is an ongoing effort to support SARIF (Static Analysis Results Interchange Format) as a direct upload format. SARIF is already the standard output format for CodeQL, Semgrep, and most modern static analysis tools. Without SARIF support:Describe the solution you'd like
Add two new, independent flags to
plumber analyzethat produce additional output files alongside the existing--outputbehavior. The existing--outputflag remains unchanged; these are additive:--sarif <path>: writes a SARIF v2.1.0 compliant file to the given path--glsast <path>: writes a GitLab SAST report (gl-sast-report.jsonschema) to the given pathThese flags are not mutually exclusive. You can use none, one, or both in the same run, and they stack with
--output:GitLab CI integration
SARIF mapping
Each Plumber control maps to a SARIF
reportingDescriptor(rule), and each finding maps to a SARIFresult:containerImageMustNotUseForbiddenTags)reportingDescriptorintool.driver.rulesresultinresultsarrayresult.properties.complianceScore(custom property)result.locations[].physicalLocationresult.level(error,warning,note)Implementation Hints
These are just ideas. Feel free to change the implementation.
github.com/owenrumney/go-sarifit handles the full SARIF v2.1.0 schema and is well-maintained.output/sarif.goandoutput/gitlab_sast.go(or undercontrol/depending on architecture preference).--sarifand--glsastasStringVarflags incmd/analyze.go, each accepting a file path. When the flag value is non-empty, write the corresponding output afterRunAnalysis()completes independently of--output.output/sarif.go):RunAnalysis()produces theAnalysisResult, convert it to SARIF formatreportingDescriptorwithid,name,shortDescription, andhelpUri(linking to Plumber docs)resultwithruleId,message,level, andlocations.gitlab-ci.ymlfile with line number if available (from the merged CI config)result.properties(compliance score, control category, etc.)output/gitlab_sast.go):gl-sast-report.jsonformat that GitLab natively ingestsgitlab-org/security-products/security-report-schemasid,category,scanner,location,identifiers,severity)Files Touched
output/sarif.go(new, SARIF conversion logic)output/gitlab_sast.go(new, GitLab SAST format conversion)cmd/analyze.go(add--sarifand--glsaststring flags, call output writers when set)go.mod/go.sum(addgo-sarifdependency)Why It's Valuable
SARIF is the de facto standard for static analysis tool output. Supporting it unlocks three critical capabilities: (1) visibility in GitLab's Security Dashboard where security teams already work, (2) integration with third-party security platforms like DefectDojo, Mobb, and ASPM tools, and (3) standardized output that makes Plumber's results comparable with other security scanners. GitLab is actively exploring direct SARIF upload support, which would make this a future-proof investment. In the meantime, the
--glsastflag provides immediate value by placing Plumber findings alongside SAST/DAST results in the merge request widget, with zero changes to how--outputcurrently works.