Guides

Audit & Reporting

How SCAL-P audits your dependencies and generates Markdown, JSON, and SARIF 2.1.0 reports.

Every operation in SCAL-P is audited. Whether you're installing, verifying, or running CI, events are logged and reports can be generated.

How audit works

After packages are installed, SCAL-P creates a separate lockfile (.scalp/lockfile.json) that stores SHA-512 hashes of installed package directories — not tarball hashes from the registry.

.scalp/lockfile.json
├── lockVersion: 2
├── generatedAt: "2026-05-22T12:00:00Z"
└── packages:
    ├── "lodash@4.17.21":
    │   ├── resolved: "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
    │   ├── integrity: "sha512-a1b2c3d4e5f6..."
    │   └── verifiedAt: "2026-05-22T12:00:05Z"
    └── "express@4.18.2":
        ├── resolved: "https://registry.npmjs.org/express/-/express-4.18.2.tgz"
        ├── integrity: "sha512-x7y9y6i..."
        └── verifiedAt: "2026-05-22T12:00:06Z"

When you run scalp audit, it re-hashes every package directory and compares against the lockfile. Any mismatch means something changed on disk.

This detects post-install tampering, modified files, added files, and removed files. If a compromised script modified a package after install, scalp audit catches it.

scalp audit

scalp audit

If everything matches:

audit ok

If tampering is detected:

! policy violations detected
policy violations detected:
- lodash@4.17.21 (hash_mismatch: hash_check)

Flags

FlagDescription
--pmPackage manager override (auto-detected)
--policyPolicy path (default .scalp/policy.json)
--ciForce enforcement to block
--reportGenerate a report file (.md or .sarif)
--artifactPath to a binary artifact to verify alongside packages
--checksumChecksums file for binary verification

Audit + report

scalp audit --report audit-report.md

This generates a full Markdown report. Use --report - to write to stdout:

scalp audit --report -

Audit + binary verify

scalp audit \
  --artifact scalp_linux_amd64.tar.gz \
  --checksum checksums.txt \
  --report audit-report.md

This runs the package audit and binary verification in a single command, producing one unified report.

Report sections (Markdown)

The Markdown report includes:

SectionContents
HeaderTool version, policy status (loaded/missing), package manager, pass/fail
SummaryTotal packages, verified/mismatched/missing counts, trust violations, CVEs
Hash VerificationPer-package status table
Trust ScoresPer-package breakdown (hash, maturity, downloads, CVEs) with verdict
CVEsVulnerability table from npm audit
Binary VerificationArtifact hash comparison
PolicyFull policy JSON in a code block
ViolationsAll violations with rule and reason
Audit EventsRaw NDJSON event log

Example output:

# Audit Report

**Tool:** scalp 0.2.0 (a1b2c3d)
**Date:** 2026-05-22T12:00:00Z
**Policy:** .scalp/policy.json ✓ loaded
**Package Manager:** npm
**Status:** ✅ PASSED

## Summary

| Metric           | Value |
| ---------------- | ----- |
| Total packages   | 142   |
| ✓ Verified       | 142   |
| ✗ Mismatched     | 0     |
| ✗ Missing        | 0     |
| Trust violations | 0     |
| CVEs             | 0     |

JSON report (CI)

The CI JSON report is a machine-readable format designed for pipeline consumption:

{
  "version": "0.2",
  "passed": true,
  "violations": [],
  "audit": {
    "verified": 142,
    "mismatched": 0,
    "missing": 0
  }
}

On failure:

{
  "version": "0.2",
  "passed": false,
  "violations": [
    {
      "package": "lodash@4.17.21",
      "reason": "trust_score: 17/50 (hash:0, maturity:15, dl:10, cves:7)",
      "rule": "min_score:50"
    }
  ],
  "audit": {
    "verified": 141,
    "mismatched": 1,
    "missing": 0
  }
}

SARIF 2.1.0 reports

SCAL-P generates SARIF (Static Analysis Results Interchange Format) reports compatible with GitHub Code Scanning:

scalp ci --sarif .scalp/report.sarif

Each policy violation becomes a SARIF result:

SARIF fieldMaps from
ruleIdNormalized rule name (require_hash, min_score, allowlist)
levelerror for most rules, warning for max_depth
message.textViolation reason
locations[].physicalLocation.artifactLocation.uriPath to package in node_modules/

The results array is always present — even when empty — to satisfy GitHub's upload-sarif action requirement.

GitHub Code Scanning integration

The easiest way is using the SCAL-P GitHub Action:

- name: Run SCAL-P CI
  uses: scal-p-labs/scalp-action@0b29e6acb5c358a7c6b6d470c6ab8cb6e86fc217
  with:
    version: latest
    sarif: .scalp/report.sarif
  continue-on-error: true

- name: Upload SARIF to GitHub
  if: success() || failure()
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: .scalp/report.sarif

Or using the CLI directly if you have scalp installed in your runner:

scalp ci --sarif .scalp/report.sarif

Audit log

.scalp/audit.log is an append-only NDJSON file. Every event (install, audit, verify, stage verify) produces one line:

{"ts":"2026-05-22T12:00:00Z","event":"hash_check","pkg":"lodash@4.17.21","status":"verified","hash_match":true}
{"ts":"2026-05-22T12:00:01Z","event":"binary_verify","pkg":"scalp_linux_amd64.tar.gz","status":"mismatch","hash_match":false}
{"ts":"2026-05-22T12:00:02Z","event":"policy_violation","pkg":"evil@1.0.0","status":"blocked","rule":"denylist","reason":"pattern:*-free"}

Grep-friendly, Splunk-friendly, ELK-friendly.

On this page