# How dcg's SARIF Output Works for CI Integration

> Integrate dcg's SARIF output into your CI pipelines for automated security reporting. Learn how dcg converts scan findings into structured JSON for GitHub Actions, GitLab CI, and Azure DevOps.

- Repository: [Jeff Emanuel/destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard)
- Tags: deep-dive
- Published: 2026-07-14

---

**The dcg (destructive_command_guard) CLI generates SARIF 2.1.0-compliant JSON through [`src/sarif.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/sarif.rs), converting scan findings into structured results that CI platforms like GitHub Actions, GitLab CI, and Azure DevOps can ingest natively for security reporting.**

The `dcg` tool analyzes shell scripts and configuration files for potentially destructive commands. When integrated into continuous integration pipelines, it outputs findings using the Static Analysis Results Interchange Format (SARIF), enabling automated security scanning with rich metadata about detected risks. The implementation follows the official SARIF 2.1.0 schema to ensure compatibility across modern DevOps platforms.

## Understanding the SARIF 2.1.0 Implementation

The SARIF module ([`src/sarif.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/sarif.rs)) implements a complete serialization layer that transforms the internal `ScanReport` structure into a standards-compliant JSON document. This conversion happens through `SarifReport::from_scan_report`, which constructs the hierarchical object model required by the specification.

### Tool Metadata and Run Configuration

The generated report begins with schema-level metadata including the `$schema` URI (`SARIF_SCHEMA`) and version identifier (`SARIF_VERSION`). The implementation creates a single `SarifRun` object containing:

- **Tool metadata** (`SarifTool` → `SarifToolComponent`) populated with the dcg name, version, and a link back to the repository via `DCG_INFO_URI`【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L26-L38】
- **Invocation details** that record the working directory and mark the execution as successful【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L40-L52】

### Rule Aggregation and Descriptor Mapping

Before emitting results, the code aggregates unique rule definitions to avoid duplication. While iterating over `ScanFinding`s, it builds a deduplicated map of `SarifReportingDescriptor` objects. Each descriptor includes:

- A human-readable name generated via `humanize_rule_id`
- Short description text
- A help URL pointing to the rule's markdown documentation in the repository
- Default severity and enablement settings【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L90-L107】

### Converting Findings to SARIF Results

The `finding_to_result` function maps each finding to a `SarifResult` object, excluding only those with an `Allow` decision. The conversion process:

1. **Severity mapping**: Translates internal decisions to SARIF levels—`Deny` becomes `Error`, `Warn` becomes `Warning`, and `Allow` becomes `Note` (implemented in `From<ScanSeverity>`)【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L47-L57】【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L64-L68】
2. **Location embedding**: Creates a `SarifLocation` containing the file URI, precise line/column coordinates, and a snippet of the extracted command【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L82-L99】
3. **Suggestion handling**: Adds a `SarifFix` with textual description when remediation advice is available【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L102-L108】
4. **Metadata preservation**: Stores extractor ID, command text, and decision data in a `SarifPropertyBag` for downstream tooling【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L77-L81】

## Filtering and Severity Mapping

The implementation filters findings to maintain focus on actionable issues. Only findings with `Deny` or `Warn` decisions are emitted to the final SARIF document; `Allow` results are intentionally omitted to reduce noise in CI reports【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L23-L25】.

This severity mapping ensures that:
- **Blocking issues** (`Deny`) appear as errors in CI dashboards
- **Advisory issues** (`Warn`) surface as warnings
- **Permitted patterns** (`Allow`) do not clutter the security report

## CLI Integration and Output Generation

When executing `dcg scan --output sarif`, the CLI invokes the serialization pipeline documented in [`src/main.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/main.rs). The `scan` subcommand processes the `--output` flag to determine the format, calling `SarifReport::from_scan_report` and serializing the structure using `serde_json::to_string_pretty`【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/main.rs#L1155-L1159】.

The resulting JSON writes to stdout or a specified file:

```rust
// Simplified from the scan command implementation
let report = scanner.run(&paths)?;
let sarif = crate::sarif::SarifReport::from_scan_report(&report);
let json = serde_json::to_string_pretty(&sarif)?;
println!("{}", json);

```

For file output, redirect the stream or use the appropriate shell redirection:

```bash
dcg scan . --output sarif > security-report.sarif

```

## CI/CD Platform Integration

Because the output conforms to the SARIF 2.1.0 specification, major CI platforms can consume the results without custom parsers.

### GitHub Actions

GitHub's `upload-sarif` action ingests the JSON directly into the Code scanning dashboard. The workflow step requires only the file path:

```yaml
- name: Run destructive command scan
  run: dcg scan . --output sarif > dcg-results.sarif

- name: Upload SARIF to GitHub
  uses: github/codeql-action/upload-sarif@v2
  with:
    sarif_file: dcg-results.sarif

```

### GitLab CI

GitLab's `codequality` report type accepts SARIF format, displaying findings in merge request pipelines:

```yaml
security_scan:
  script:
    - dcg scan . --output sarif > gl-code-quality-report.json
  artifacts:
    reports:
      codequality: gl-code-quality-report.json

```

### Azure DevOps

Azure DevOps automatically parses SARIF files in the Security tab when published as build artifacts. Use the Publish Build Artifacts task to make the report available to the built-in security analysis tools.

## Summary

- **SARIF 2.1.0 compliance**: The [`src/sarif.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/sarif.rs) module implements the full specification with schema validation, tool metadata, and run invocations
- **Structured conversion**: `SarifReport::from_scan_report` transforms internal `ScanReport` objects into standardized JSON with preserved location data and fix suggestions
- **Severity translation**: Internal decisions map directly to SARIF levels—`Deny` → `Error`, `Warn` → `Warning`—while `Allow` findings are filtered from output
- **Universal CI support**: Native integration with GitHub Actions, GitLab CI, and Azure DevOps through standard SARIF ingestion APIs
- **Rich metadata**: Each result includes command snippets, file locations, rule documentation URLs, and property bags for extensibility

## Frequently Asked Questions

### How does dcg handle false positives in SARIF output?

Findings marked with an `Allow` decision are filtered out during the SARIF generation process in [`src/sarif.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/sarif.rs)【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L23-L25】. This ensures that explicitly permitted patterns do not appear in CI security dashboards, keeping the report focused on actionable violations.

### Can I customize the severity levels in the SARIF output?

The severity levels are determined by the rule's decision type (`Deny`, `Warn`, or `Allow`) and mapped to SARIF levels through the `From<ScanSeverity>` implementation【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L47-L57】. While the CLI does not expose direct severity customization flags, you can modify rule configurations to change whether a pattern triggers a `Deny` or `Warn` decision, which indirectly affects the SARIF level.

### What information is included in the SARIF property bag?

The `SarifPropertyBag` contains additional metadata for each finding, including the extractor ID that identified the command, the full command text, and the specific decision rendered【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/sarif.rs#L77-L81】. This data enables downstream tools to perform custom filtering or correlation without parsing the formatted message strings.

### Does dcg support SARIF output for all scan commands?

The SARIF output is specifically implemented for the `scan` subcommand via the `--output sarif` flag, as documented in [`src/main.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/main.rs)【/cache/repos/github.com/Dicklesworthstone/destructive_command_guard/main/src/main.rs#L1155-L1159】. When invoked, the CLI routes the `ScanReport` through the `sarif` module serializer, producing JSON that can be consumed by any SARIF-compatible platform.