fix(cli): let a real filesystem error be itself, not "no extension pin" - #221
Conversation
#220, from the review of #219. `clearPin` reached its stem fallback by catching ANY throw from `clearExtensionPin`, on the assumption that a throw meant "that wasn't a legal server name". It also catches the failures that matter: an EACCES on the identity directory came back as `no extension pin for @scope/name` — and since the stem lookup can never match a slash-form name, that is the message every scoped MCP would get for a permissions problem. It sends the reader looking for a file that is sitting right there. It now asks first whether the argument is a legal server name (`safeIdentityFileBase`, newly exported for it) and only falls back to the stem when it is not. Everything else propagates as itself. The test chmods the identity directory to 0500 and asserts the EACCES surfaces; against the previous implementation it fails with the exact misleading message above. Skipped when running as root, where the mode is advisory. Closes #220 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @chrischall's task in 48s —— View job Code Review: fix(cli): let a real filesystem error be itself, not "no extension pin"SummaryThis PR fixes a bug where Changes AnalysisLogic change (trust.ts:109-130):
Export (server/index.ts:72):
Test coverage (trust.test.ts:163-181):
Validation
TestingThe PR description reports: 1233 tests, three consecutive clean runs, tsc across all six workspaces. Existing tests for scoped/ambiguous stem cases (lines 122–161) remain passing and interact correctly with this fix. Verdict: pass No issues found. The fix correctly distinguishes between "not a valid server name" and "filesystem error," and the test validates the discriminator works as intended. |
|
✅ Auto-review verdict: pass — The fix correctly validates server names before filesystem operations, preventing real errors from being masked as "no extension pin" messages. Logic, exports, and test coverage are all sound. |
🤖 I have created a release *beep* *boop* --- ## [2.0.0](v1.11.0...v2.0.0) (2026-08-06) ### ⚠ BREAKING CHANGES * **protocol:** bind the ephemeral key into the ready signature ([#222](#222)) ### Features * **protocol:** add write_cookies, the one verb that can repair a rotated session ([#211](#211)) ([b2557c2](b2557c2)) * **protocol:** bind the ephemeral key into the ready signature ([#222](#222)) ([c13aeed](c13aeed)) * **server:** let a request name the tab that relays it ([#207](#207)) ([c5d3f4d](c5d3f4d)) * **server:** pin the extension's identity, and verify it on the peer path ([#213](#213)) ([0eeced7](0eeced7)) ### Bug Fixes * **cli:** let a real filesystem error be itself, not "no extension pin" ([#221](#221)) ([c87a864](c87a864)), closes [#220](#220) * **cli:** validate --via-tab before connecting, like the request URL ([#210](#210)) ([959fcc5](959fcc5)) * **extension:** reattach the write_cookies doc block, and name the writable cookies as writable ([#215](#215)) ([2730c4a](2730c4a)) * **extension:** use the guarded caps local for the cookie heading ([#217](#217)) ([f95c832](f95c832)) * **server:** release only our own extension claim, and stop guessing scoped names ([#219](#219)) ([3d90a64](3d90a64)), closes [#218](#218) * **server:** type no-tab rejections so they stop reading as version mismatches ([#205](#205)) ([dc30bd9](dc30bd9)) ### Refactor * **server:** drop the concatBytes imports the signature change orphaned ([#224](#224)) ([4985ba7](4985ba7)), closes [#223](#223) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The one nit from #220, on a fresh branch off main — #219 merged while I was writing the fix.
clearPinreached its stem fallback by catching any throw fromclearExtensionPin, on the assumption that a throw meant "that wasn't a legal server name". It also catches the failures that matter. An EACCES on the identity directory came back as:— and because the stem lookup can never match a slash-form name, that is the message every scoped MCP gets for a permissions problem. It sends the reader looking for a file that is sitting right there, at the moment they are already locked out by a pin.
It now asks first whether the argument is a legal server name (
safeIdentityFileBase, newly exported from@fetchproxy/serverfor it) and only falls back to the stem when it is not. Everything else propagates as itself.Testing
The new test chmods the identity directory to
0500and asserts the EACCES surfaces. I checked it discriminates rather than assuming: against the previous implementation it fails with exactly the misleading message above —Skipped when running as root, where the directory mode is advisory.
1233 tests, three consecutive clean runs,
tsc -bacross all six workspaces.Closes #220