Skip to content

Block upgrades that change the signer identity - #6132

Open
samuv wants to merge 1 commit into
skills-sig/12-sync-reverifyfrom
skills-sig/13-upgrade-guard
Open

Block upgrades that change the signer identity#6132
samuv wants to merge 1 commit into
skills-sig/12-sync-reverifyfrom
skills-sig/13-upgrade-guard

Conversation

@samuv

@samuv samuv commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Note

Stack 2 of RFC THV-0080 (tracking issue #5899) — part of stack #6128: #6091#6121#6129#6131 ← this.

Summary

An upgrade re-resolves a mutable source — exactly the moment a compromised or transferred publisher could slip a differently-signed artifact into the pinned trust chain. This PR closes that gap:

  • Plan-time signer probe: when a lock entry records a signer identity, planUpgrade verifies the candidate artifact (chain-of-trust only, no install — preview stays install-free) and compares the observed identity against the recorded one. OCI candidates verify directly; git candidates are re-resolved at the pinned commit for their signature material.
  • signer-change-blocked status: a differing identity — or an unsigned candidate against a signed entry — blocks the plan with no pinned reference, mirroring ref-change-blocked exactly: preview reports it, --fail-on-changes counts it as a change (exit 2), and a plain upgrade exits with the policy-rejection code (exit 4) pointing at the escape hatch. The blocked outcome carries new_signer_identity so the user sees who signed the candidate.
  • --allow-signer-change (CLI, client, API): the explicit override verifies the candidate chain-of-trust-only and re-records the new identity in the lock entry — a deliberate, diff-visible trust rotation rather than a silent one. This is also the recovery path the install-time signer-mismatch error now points at.
  • Entries without recorded provenance (unsigned/legacy) are unaffected — no probe, no behavior change.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Test improvements
  • CI/CD or build system changes

Test plan

  • Unit tests pass locally
  • Linting passes (task lint-fix, 0 issues)
  • New unit tests: signer-change blocked with the new identity reported and the lock untouched; unsigned candidate blocked against a signed entry; --allow-signer-change upgrades and re-records the new identity; preview parity (same block reported, nothing installed or rewritten); exit-code matrix rows (policy rejection, preview-informational, fail-on-changes interaction).
  • task docs regenerated (new flag + API field).

Does this introduce a user-facing change?

Yes, behind the experimental gate: thv skill upgrade refuses to move a skill to an artifact signed by a different identity (or unsigned) unless --allow-signer-change is passed.

Generated with Claude Code

@samuv samuv changed the title wip signer-change guard Block upgrades that change the signer identity Jul 29, 2026
@github-actions github-actions Bot added size/XS Extra small PR: < 100 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Jul 29, 2026
@samuv
samuv force-pushed the skills-sig/13-upgrade-guard branch from 591c621 to f1a9a83 Compare July 29, 2026 08:01
@samuv
samuv marked this pull request as ready for review July 29, 2026 08:02
@github-actions github-actions Bot added size/M Medium PR: 300-599 lines changed and removed size/XS Extra small PR: < 100 lines changed size/M Medium PR: 300-599 lines changed labels Jul 29, 2026
@samuv samuv self-assigned this Jul 29, 2026
An upgrade re-resolves a mutable source, which is exactly when a
compromised or transferred publisher would slip a differently-signed
artifact into the pinned trust chain (RFC THV-0080). Upgrade planning
now probes the candidate's signer identity — chain-of-trust
verification only, no install — and blocks the upgrade with a
dedicated signer-change-blocked status when it differs from the
identity the lock file records, or when the candidate is unsigned.
Blocked plans carry no pinned reference, exactly like ref changes:
preview reports them, fail-on-changes counts them as changes, and a
plain upgrade exits with the policy-rejection code pointing at
--allow-signer-change.

The explicit override verifies the candidate chain-of-trust-only and
re-records the newly observed identity in the lock entry, so the
change is deliberate and diff-visible rather than a silent rotation.
Entries without recorded provenance are unaffected.

Part of #5899.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@samuv
samuv force-pushed the skills-sig/13-upgrade-guard branch from f1a9a83 to 8cb954f Compare July 29, 2026 08:09
@github-actions github-actions Bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Jul 29, 2026
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 54.71698% with 24 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (skills-sig/12-sync-reverify@3a2f05e). Learn more about missing BASE report.

Files with missing lines Patch % Lines
pkg/skills/skillsvc/upgrade.go 57.14% 11 Missing and 4 partials ⚠️
pkg/skills/client/client.go 0.00% 7 Missing ⚠️
pkg/skills/skillsvc/verify.go 50.00% 2 Missing ⚠️
Additional details and impacted files
@@                      Coverage Diff                       @@
##             skills-sig/12-sync-reverify    #6132   +/-   ##
==============================================================
  Coverage                               ?   72.47%           
==============================================================
  Files                                  ?      740           
  Lines                                  ?    76358           
  Branches                               ?        0           
==============================================================
  Hits                                   ?    55344           
  Misses                                 ?    17083           
  Partials                               ?     3931           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Medium PR: 300-599 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant