Skip to content

fix(security): propagate OSSF Scorecard Tier-1 hardening to main#83

Closed
devonartis wants to merge 9 commits into
mainfrom
develop
Closed

fix(security): propagate OSSF Scorecard Tier-1 hardening to main#83
devonartis wants to merge 9 commits into
mainfrom
develop

Conversation

@devonartis
Copy link
Copy Markdown
Owner

Summary

Promotes PR #82 (Tier-1 Scorecard hardening) from develop to main so the public main ref is what scorecard.yml scans.

  • Token-Permissions 0→10 (codeql + release perms moved to job level)
  • Pinned-Dependencies 8→10 (Docker SHA pins, govulncheck pinned, pip removed)
  • Repo Python-free across .github/, tests/sec-l2b/, scripts/smoke/
  • Expected overall lift: 6.2 → ~7.3

Closes #81 (already closed by PR #82, listed here for traceability).

Test plan

  • All CI gates green on this PR (most reused from develop push)
  • After merge: gh workflow run scorecard.yml --ref main
  • 4-6 hr later: verify https://api.scorecard.dev/projects/github.com/devonartis/agentwrit reports Token-Permissions=10, Pinned-Dependencies=10, overall ≥ 7.0
  • First v* tag push triggers release.yml — cosign keyless signing verified with cosign verify devonartis/agentwrit:v<n>

devonartis and others added 9 commits May 13, 2026 19:53
12 stories (3 precondition, 8 acceptance, 1 deferred) covering
Token-Permissions + Pinned-Deps lift, Docker digest reproducibility,
Scorecard non-regression of currently-10 checks, and Python-removal
verification. Council-approved 2026-05-13 (3 reviewers, APPROVED_AFTER_REVISION).

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
Top-level write permissions hit OSSF Scorecard Token-Permissions
check (currently 0/10). Move security-events:write and actions:read
to the analyze job — the only consumer in this workflow. Top level
keeps contents:read only. CodeQL analyze action is on the recognized-
action list, so job-level security-events:write is not penalized.

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
Top-level packages:write and id-token:write hit OSSF Scorecard
Token-Permissions. The publish job is the only consumer of both.
cosign-installer is on the recognized-actions list, so job-level
id-token:write keeps keyless signing working without penalty.
Comments preserved — they explain why each permission exists.

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
golang:1.24-alpine and alpine:3.21 were unpinned tag references.
Tags are mutable — a supply-chain compromise of the upstream
publisher would silently land in our build. Pin both by sha256
digest. Dependabot's docker ecosystem (.github/dependabot.yml)
rotates digests weekly with PR review.

Tag names preserved on the preceding comment line (Dockerfile FROM
syntax rejects trailing inline comments after AS stage).

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
go install ...@latest is unpinned by Scorecard's definition — every
CI run resolves dynamically. Pin to the dereferenced commit SHA of
the latest release tag (v1.1.4 / d1f380186385b4f64e00313f31743df8e4b89a77).
Tag-derived SHA is the only safe form: gh api releases/latest
.target_commitish can return branch HEAD, not the tag commit.

Manual quarterly bump cadence — owner reviews when next release
is worth picking up. Existing gosec + CodeQL gates provide
secondary CVE coverage.

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
Project rule (.claude/rules/golang.md): all crypto is Go stdlib.
Two integration scripts were using inline python3 with the
cryptography package for challenge-response Ed25519 keygen+sign:
tests/sec-l2b/integration.sh (3 blocks) and scripts/smoke/core-
contract.sh (2 blocks). The latter is what the smoke-l25 CI gate
actually runs. Plan (.plans/2026-05-13-ossf-scorecard-tier1-plan.md)
covered only the first script — scope expanded after audit found
core-contract.sh still required python3+cryptography even after
integration.sh was converted.

Replace with tests/sec-l2b/edsign (~50 lines, crypto/ed25519
stdlib only). Both bash scripts build the helper once per run and
use it for keygen+sign; HTTP POST stays in curl, JSON body
construction in jq -nc. S6 oversized-body generator uses
head -c 1048576 /dev/zero | tr '\\0' 'x' instead of python.

Delete pip install step from ci.yml smoke-l25 job; add setup-go
since the job now runs `go build` for the helper. Update
core-contract.sh dep-check to require go instead of python3.

Repo is now Python-free across .github/, tests/sec-l2b/, and
scripts/smoke/. OSSF Scorecard Pinned-Dependencies finding for
the pip line disappears entirely (rather than being hash-pinned).

Acceptance verified locally against live broker:
- scripts/smoke/core-contract.sh: 10/10 PASS
- tests/sec-l2b/integration.sh:    9 PASS / 1 SKIP (HSTS-TLS) / 0 FAIL
HTTP wire behavior unchanged: same Ed25519 keypair generation,
same hex-decoded nonce signing, same JSON body shape, same POST
to /v1/register, same HTTP error handling via curl -w %{http_code}.

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
Closes #81

Co-authored-by: Claude <noreply@anthropic.com>
Go 1.24 gofmt enforces blank line + tab indent for indented code blocks
in doc comments. Format check failed on lines 7 and 11 of edsign/main.go.

Refs #81

Co-authored-by: Claude <noreply@anthropic.com>
fix(security): OSSF Scorecard Tier-1 hardening (token perms + pin deps)
@devonartis
Copy link
Copy Markdown
Owner Author

Closing per owner — wrong shape. Will use direct merge pattern instead.

@devonartis devonartis closed this May 14, 2026
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.

OSSF Scorecard Tier-1 hardening: token-permissions + pinned-dependencies

1 participant