Skip to content

feat: add HMAC-SHA256 report authenticity envelopes (Phase 20 JSON slice) - #10

Open
mattpartida wants to merge 1 commit into
mainfrom
feat/20260824-report-envelope
Open

mattpartida wants to merge 1 commit into
mainfrom
feat/20260824-report-envelope

Conversation

@mattpartida

Copy link
Copy Markdown
Owner

Summary

Implements the roadmap's Phase 20 (first slice): an optional, non-executable integrity envelope for exported JSON reports so downstream consumers can detect accidental or malicious report mutation between scan time and review time.

Scanner (skills/agent-security/scripts/config_risk_summary.py):

  • New --envelope-secret-file <path> flag adds an additive report_envelope object to JSON output: algorithm (hmac-sha256), payload_sha256, signature, and sorted covered_fields.
  • Without the flag, output is byte-identical to before — fully backwards compatible.
  • Envelope signs the full summary minus the envelope itself (never self-signed); canonical serialization is sorted-keys/tight-separators/UTF-8.
  • Secret files are UTF-8 text with at most one trailing newline stripped (CI secret-file convention). Unreadable, non-UTF-8, or empty/blank secrets fail closed as structured invalid_envelope_secret error findings (ok: false, strict exit 1) instead of silently unsigned output.
  • Signing requires --format json (default); combining with markdown/SARIF is a usage error (exit 2) rather than silently unsigned output.

New verifier (skills/agent-security/scripts/verify_report_envelope.py):

  • Standard-library only, reads report on stdin, secret via mutually exclusive --secret-file <path> / --secret-env <VAR>.
  • Exit 0 = intact, 1 = verification failure (JSON verdict with machine-readable codes: missing_envelope, unsupported_algorithm, malformed_envelope, payload_digest_mismatch, signature_mismatch, invalid_secret, invalid_report), 2 = usage error.
  • Constant-time signature comparison (hmac.compare_digest).

Docs: new docs/report-envelopes.md (envelope fields, verifier usage, exit-code table, secret generation/storage/rotation, integrity-not-encryption scoping); README quick start + key-files list; SKILL.md helper scripts + example commands; docs/ci-integration.md signed-artifact workflow section; CHANGELOG; roadmap Phase 20 marked Shipped (JSON report slice) with explicit remaining follow-ups (SARIF/Markdown coverage, kid multi-secret rotation support).

Test Plan

  • TDD: tests/test_phase20_report_envelopes.py written first (17 tests, all red before implementation)
  • Default output has no report_envelope; existing JSON fields unchanged
  • Envelope present + well-formed with secret file; deterministic across runs; trailing-newline tolerance
  • Empty/unreadable secret -> structured error finding, ok: false, strict exit 1; no envelope emitted
  • --format markdown + envelope flag -> usage error exit 2 with clear stderr
  • Verifier accepts intact reports via file and env secret sources
  • Verifier rejects tampered findings, forged signature, wrong secret, missing envelope, unsupported algorithm, empty/missing secret — each with the distinct expected error code
  • Verifier requires exactly one secret source (both/none -> exit 2)
  • Docs/README/CHANGELOG/roadmap/SKILL sync assertions
  • python -m compileall -q skills tests scripts — OK
  • python -m pytest -q — 146 passed (129 baseline + 17 new)
  • ruff check . — All checks passed
  • ./package-skills.sh + python3 scripts/package_skills.py --check — artifacts current and reproducible (new verifier script is packaged into agent-security.skill)
  • git diff --check — clean

Follow-ups deliberately deferred: SARIF/Markdown envelope coverage and key-identifier (kid) rotation support — recorded in the roadmap as remaining Phase 20 scope.

…ice)

- Add --envelope-secret-file to config_risk_summary.py: optional additive
  report_envelope (algorithm, payload_sha256, signature, covered_fields)
  over the JSON report payload; output unchanged without the flag
- Fail closed on unreadable/empty secrets with structured
  invalid_envelope_secret error findings; require --format json
- Add dependency-light verify_report_envelope.py verifier with
  --secret-file/--secret-env (mutually exclusive), constant-time compare,
  exit codes 0/1/2, and machine-readable failure codes
- Add docs/report-envelopes.md plus README, SKILL.md, ci-integration,
  changelog, and roadmap sync
- Add tests/test_phase20_report_envelopes.py (17 tests: compatibility,
  determinism, tamper detection, secret handling, docs sync)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant