Skip to content

feat(security): publish-side hardening — SHA256SUMS, tags, pinned actions#3

Merged
bhavink merged 1 commit into
mainfrom
feat/security-publish
May 5, 2026
Merged

feat(security): publish-side hardening — SHA256SUMS, tags, pinned actions#3
bhavink merged 1 commit into
mainfrom
feat/security-publish

Conversation

@bhavink
Copy link
Copy Markdown
Owner

@bhavink bhavink commented May 5, 2026

Summary

Publish-side security plumbing. Consume-side hardening (TF module hash verification with mock-based tests) follows in PR 4 — splitting because hash verification is cleanly testable only once SHA256SUMS is actually being published.

What changes

Workflow hardening

  • update.yml — pin actions/checkout and actions/setup-python by commit SHA with version comments. Verify SHA256SUMS in-place after generation. Tag every successful publication as v<YYYY.MM.DD>. Skip tag if it already exists (multiple same-day runs).
  • terraform.yml — pin actions/checkout and hashicorp/setup-terraform by commit SHA.

Integrity manifest

  • update_outputs.py generates docs/output/SHA256SUMS in GNU sha256sum format (<64-hex> <filename>).
  • Compatible with sha256sum -c SHA256SUMS (Linux) and shasum -a 256 -c (macOS).
  • Excludes SHA256SUMS from itself (no chicken-and-egg).
  • Output directory index now links the manifest and shows the verify command.

Threat model

  • SECURITY.md — explicit trust boundary (5 things you trust when consuming), highest-leverage defense (pin to tag/SHA, never main), defenses already in place, recommended consumption patterns by paranoia level (default → strict → vendored), manual integrity verification recipe, reproducible-build verification recipe, honestly named out-of-scope failure modes.

Tests

  • 6 new in test_update_outputs.py covering: file emitted, GNU format regex, recorded hashes match on-disk content, no self-reference, every txt file covered, index links it.
  • 39/39 Python tests passing (was 33/33).
  • 9/9 Terraform tests still passing.

Test plan

  • python -m pytest 39/39 passing
  • terraform test 9/9 passing (no regression)
  • Both workflow YAMLs parse cleanly
  • sha256sum -c SHA256SUMS against the locally-generated manifest succeeds for all 89 entries
  • CI runs terraform.yml (pinned SHAs) on this PR
  • First weekly run of update.yml post-merge generates SHA256SUMS + tags

Follow-up (PR 4)

TF module hash verification: optional verify_checksums input (default true) that fetches SHA256SUMS at plan time and compares against sha256(self.response_body) of each fetched feed via postcondition. Mock-based unit tests for the verification logic.

…ned actions, threat model

Publish-side security plumbing. Consume-side (TF module hash verification)
follows in a separate PR.

Workflow changes (.github/workflows/update.yml):
- Pin actions/checkout and actions/setup-python by commit SHA with version
  comments. Prevents transitive action supply-chain attacks.
- Verify SHA256SUMS in-place after generation (sha256sum -c) — catches
  local corruption before push.
- Tag every successful publication with v<YYYY.MM.DD>. Consumers pin a
  stable ?ref= instead of tracking main. Skip tag if it already exists
  (multiple runs same day).
- terraform.yml: pin actions/checkout + hashicorp/setup-terraform by SHA.

update_outputs.py:
- Generate docs/output/SHA256SUMS in GNU sha256sum format alongside the
  txt files. One line per .txt file: "<64-hex-digest>  <filename>".
- Compatible with `sha256sum -c SHA256SUMS` and `shasum -a 256 -c`.
- Excludes SHA256SUMS itself (no chicken-and-egg).
- Directory index now links SHA256SUMS and shows the verify command.

Tests (test_update_outputs.py): 6 new — file emitted, GNU format, hashes
match on-disk content, no self-reference, every txt file covered, index
links it. 12/12 passing (was 6/6).

SECURITY.md: explicit threat model. Trust boundary (5 things you trust
when consuming). Highest-leverage defense: pin to tag/SHA, never main.
Defenses already in place. Recommended consumption patterns by paranoia
level: default (tag pin), strict (SHA pin + hash verify), paranoid
(vendor into your own repo). Manual integrity verification recipe.
Reproducible-build verification recipe. Out-of-scope failure modes
(GitHub itself, upstream Databricks compromise, solo-maintainer account
takeover) named honestly.

Total tests: 39 Python (was 33) + 9 Terraform = 48/48 passing.
@bhavink bhavink merged commit 348f347 into main May 5, 2026
4 checks passed
@bhavink bhavink deleted the feat/security-publish branch May 5, 2026 15:55
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