Skip to content

fix(ci): pin actions to SHAs, add beta provenance, verify publisher binary - #364

Draft
SavioBS629 wants to merge 2 commits into
browserstack:mainfrom
SavioBS629:fix/pmaa-106-supply-chain
Draft

fix(ci): pin actions to SHAs, add beta provenance, verify publisher binary#364
SavioBS629 wants to merge 2 commits into
browserstack:mainfrom
SavioBS629:fix/pmaa-106-supply-chain

Conversation

@SavioBS629

@SavioBS629 SavioBS629 commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Addresses the PMAA-106 security retest (2026-07-31), which reopened the ticket with three required actions.

1. Beta publish provenance — fixed

  • beta-release.yml: npm publish now runs with --provenance; added id-token: write to workflow permissions (required for OIDC provenance signing, mirrors npm-publish.yml).

2. Action SHA pinning — fixed (8/8 references across all 4 workflows)

Every uses: reference now points to a full commit SHA (resolved from the GitHub API) with the version as a trailing comment:

Workflow Pins
beta-release.yml checkout v4.4.0, setup-node v4.4.0
mcp-ci.yml checkout v4.4.0, setup-node v4.4.0 (was v3 — deprecated node16 runtime)
npm-publish.yml checkout v2.8.0, setup-node v3.9.1, create-release v1.1.4 (majors kept as-is)
mcp-registry-publish.yml checkout v5.1.0, setup-node v5.0.0

A compromised mutable tag can no longer inject code into any workflow.

3. npm 2FA / automation-token control — needs org-level confirmation (not fixable in repo)

Requires someone with npm org access to confirm NPM_TOKEN is a granular automation token scoped to @browserstack/mcp-server with publish-only rights and that maintainer 2FA is enforced, then document it on the Jira ticket.

Bonus: mcp-publisher binary verification (original INF-006, CVSS 7.4)

  • mcp-registry-publish.yml: the mcp-publisher tarball is now downloaded to disk and verified against a pinned SHA-256 before extraction/execution. GitHub release assets are mutable, so URL version pinning alone doesn't protect the OIDC credential this job holds. Hash sourced from upstream registry_1.3.3_checksums.txt and independently verified by downloading and hashing the asset. Tamper case tested locally (modified archive → check fails, exit 1, job stops before the binary runs).

Testing

  • All 4 workflow files pass YAML validation
  • Checksum step's exact command sequence executed locally: genuine file passes and extracts a valid linux/amd64 ELF binary; tampered file fails closed
  • Action SHAs resolved live from repos/<owner>/<repo>/git/matching-refs/tags

🤖 Generated with Claude Code

…inary

Addresses PMAA-106 security retest (2026-07-31):
- Pin all GitHub Action references to full commit SHAs across all 4 workflows
- Add --provenance to beta-release.yml npm publish (with id-token: write)
- Verify mcp-publisher download against pinned SHA-256 before execution (INF-006)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@SavioBS629 SavioBS629 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review (automated) — 2 inline finding(s). Full report in the PR comment below. Verdict: Passed.

Comment thread .github/workflows/npm-publish.yml Outdated
Comment thread .github/workflows/npm-publish.yml Outdated
@SavioBS629

Copy link
Copy Markdown
Collaborator Author

Claude Code PR Review

PR: #364Head: f15e263Reviewers: stack:code-review

Summary

Hardens the CI/CD supply chain per the PMAA-106 security retest: pins all GitHub Action references across the 4 workflows to full commit SHAs, adds --provenance (+ id-token: write) to the beta npm publish, and verifies the mcp-publisher binary download against a pinned SHA-256 before execution.

Review Table

Priority Category Check Status Notes
High Security No hardcoded secrets or credentials Pass Pinned values are public commit SHAs and a public artifact checksum, not secrets; tokens remain in secrets.*
High Security Authentication/authorization checks present Pass OIDC id-token: write added only where provenance signing needs it; contents stays read in beta-release
High Security Input validation and sanitization Pass Publisher tarball now checksum-verified before extraction; curl -fsSL fails closed on HTTP errors
High Security No IDOR — resource ownership validated N/A Workflow-only change
High Security No SQL injection (parameterized queries) N/A Workflow-only change
High Correctness Logic is correct, handles edge cases Pass All 7 SHA pins independently verified against upstream tag refs; checksum matches official registry_1.3.3_checksums.txt; provenance prerequisites (npm ≥ 9.5 via Node 22, registry-url) satisfied
High Correctness Error handling is explicit, no swallowed exceptions Pass Checksum mismatch aborts the step (bash -e) before the binary is extracted or executed
High Correctness No race conditions or concurrency issues N/A No concurrent behavior changed
Medium Testing New code has corresponding tests N/A Workflow YAML; checksum step's command sequence executed locally (genuine file passes, tampered file fails closed)
Medium Testing Error paths and edge cases tested Pass Tamper case verified: modified archive → sha256 check FAILED, exit 1
Medium Testing Existing tests still pass (no regressions) N/A No src/test changes
Medium Performance No N+1 queries or unbounded data fetching N/A
Medium Performance Long-running tasks use background jobs N/A
Medium Quality Follows existing codebase patterns Pass SHA-pin + version-comment style consistent across all 4 workflows
Medium Quality Changes are focused (single concern) Pass Single concern: PMAA-106 supply-chain remediation
Low Quality Meaningful names, no dead code Pass Version + checksum extracted to named env vars with provenance comment
Low Quality Comments explain why, not what Pass Checksum source documented (registry_1.3.3_checksums.txt)
Low Quality No unnecessary dependencies added Pass No new dependencies; third-party binary now integrity-checked

Findings

  • File: .github/workflows/npm-publish.yml:15 (also line 20)

  • Severity: Medium

  • Reviewer: stack:code-review

  • Issue: The release workflow is pinned to end-of-life action majors — actions/checkout@v2.8.0 and actions/setup-node@v3.9.1 (Node 16-runtime lines that receive no further security patches), while the same PR upgrades mcp-ci.yml to v4.4.0. The release workflow is the most security-sensitive one in the repo.

  • Suggestion: Reuse the already-verified v4.4.0 SHAs from beta-release.yml (actions/checkout@11d5960a…, actions/setup-node@49933ea5…). Behavior-compatible (fetch-depth: 0, node-version, registry-url all supported identically). Note: keeping existing majors in this workflow was a deliberate minimal-diff decision by the author; flagged for a follow-up.

  • File: .github/workflows/npm-publish.yml:108

  • Severity: Low

  • Reviewer: stack:code-review

  • Issue: actions/create-release is archived (unmaintained since 2021). The SHA pin removes tag-hijack risk, but a dead dependency remains in the release path.

  • Suggestion: Replace with the preinstalled gh CLI (gh release create "$VERSION" --title "$VERSION" --notes "$BODY") in a follow-up; also allows passing PR-derived release notes via env vars instead of ${{ }} interpolation.

Informational (no action needed): the mcp-ci.yml v3→v4.4.0 pin is a two-major runtime bump (safe on ubuntu-latest); the pinned publisher checksum is coupled to linux_amd64 — if the runner label ever moves to arm64, update the URL/checksum pair together.


Verdict: PASS — all SHA pins and the binary checksum independently verified against upstream; remaining items are non-blocking follow-ups.

…ved create-release

Review follow-ups on PR browserstack#364:
- checkout v2.8.0 -> v4.4.0, setup-node v3.9.1 -> v4.4.0 (same verified SHAs
  used elsewhere in this PR; v2/v3 lines are EOL and unpatched)
- replace archived actions/create-release with gh release create, passing
  PR-derived notes via env vars instead of expression interpolation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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