fix(cli): install skill content from a pinned release, not a branch - #93
Draft
MajorLift wants to merge 2 commits into
Draft
fix(cli): install skill content from a pinned release, not a branch#93MajorLift wants to merge 2 commits into
MajorLift wants to merge 2 commits into
Conversation
Skills are auto-loaded instructions distributed to engineers' agents across the org, alongside executable payloads written into agent-trusted paths. The repo's security posture does not describe that channel anywhere. Describes three channels — instruction, execution, delivery — with the state of each verified against the tree: `copy_bundle_dirs` ships `scripts` and `adapters` (7 payloads today), `tools/sync` pulls from a tracked branch rather than a reviewed ref, and `tools/bootstrap` is documented as `curl | bash` from `main` with no checksum. The package is lockfile-pinned; the content it installs is not, and that distinction is the crux. States the existing controls with equal care, since the risk is easy to overstate: auto-update is opt-in behind `SKILLS_AUTO_UPDATE`, this package declares no `postinstall` of its own, `--ff-only` breaks rather than silently applying a rewritten history, and CLI distribution is already review-gated. Descriptive, not a proposal — the five open decisions are listed for the security team to rule on rather than settled here. Also flags that SECURITY.md describes the repo as prompt templates with no runtime code, which does not account for the published CLI or the shipped executables. Raised during ADR 0057 review (MetaMask/decisions#162).
A lockfile entry pins the `@metamask/skills` CLI. It never pinned the skill revision that reaches disk: the cache cloned and reset to `main`, so an install pinned in a lockfile still picked up whatever had merged since, and the documented `curl … | bash` bootstrap did the same for cloud agents. The CLI now derives the content ref from its own package version, so one lockfile entry pins both halves. `tools/bootstrap` resolves the newest release tag over `git ls-remote` instead of defaulting to `main`. Both fail closed. A missing tag means this package version has no published content, and widening to a branch at that point would reinstate the channel being removed — so the CLI warns and declines, and bootstrap exits non-zero naming the override. `SKILLS_REF` still overrides, for development against `main` and for holding a consumer on a specific release. It is now a deliberate opt-in to a mutable ref rather than the default, and taking it warns. Engineer-owned checkouts reached through `METAMASK_SKILLS_DIR` are untouched; that is their working copy, not a delivery channel.
MajorLift
marked this pull request as draft
July 30, 2026 19:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
Draft — not intended for merge until the security review completes.
This changes the delivery channel for every consumer. The threat-model work is a separate stream in progress with the security team; this PR is the proposed fix, parked here for that review to land against. Do not merge on CI green alone.
The gap
A lockfile entry pins the
@metamask/skillsCLI. It never pinned the skill content that reaches disk:ensurePublicSkillsCachecloned--branch mainandreset --hard origin/main, so a lockfile-pinned install still picked up anything merged since.tools/bootstrap— the documentedcurl … | bashfor cloud agents — defaultedSKILLS_REFtomain, with no pin and no checksum.Skill bodies are auto-loaded instructions and the bundle carries executable payloads, so "which revision landed" is a question the install should be able to answer.
The fix
CLI — content ref derives from the package's own version, so one lockfile entry pins both halves:
Bootstrap — resolves the newest release tag via
git ls-remote --tagsinstead of defaulting tomain.Both fail closed. A missing tag means this package version has no published content; widening to a branch there would reinstate the channel being removed. The CLI warns and declines; bootstrap exits non-zero naming the override.
SKILLS_REFstill overrides — for development againstmain, and for holding a consumer on a specific release. It is now a deliberate opt-in to a mutable ref rather than the default, and taking it warns.Scope
Engineer-owned checkouts reached through
METAMASK_SKILLS_DIRare untouched — that is a working copy, not a delivery channel.tools/synccontinues togit pull --ff-onlythere.Test plan
yarn test— 14 pass / 0 failv0.2.0from package version0.2.0; tag existsgit ls-remote --tagsresolvesv0.2.0as newest against the live remotebash -n tools/bootstrapmainfails CIOpen, for that review
scripts/andadapters/should ship at all, and under what review — untouched here.mainmatch the channel's reach. Not asserted either way in this PR: the protection endpoint returns 404 to a non-admin token, which does not distinguish "no rule" from "no permission to read it".