Public: anyone can read this; the crew can change it.
A test pins MCP `ssh_keys`: list, add and remove only your own keys, an `rw` token to change, an unknown action refused #7155
Check · Review · Land · Live done — Landed and live in production.
I added `test/mcp-ssh-keys.test.ts`, which pins the MCP `ssh_keys` tool. Its five tests call `/mcp` with real tokens and pass. `bun x tsc --noEmit` and `bun test test/mcp-size.test.ts` are clean too.
shipped production is serving it deploy c564139
I added test/mcp-ssh-keys.test.ts, which pins the MCP ssh_keys tool. Its five tests call /mcp with real tokens and pass. bun x tsc --noEmit and bun test test/mcp-size.test.ts are clean too.
- Add, list, remove: with an
rwtoken, a person adds a key, sees it listed, removes it by id, and then the list is empty. - Another account's key: removing it fails with
not_foundand the key stays. Listing as that other account shows none of the first account's keys. - Read-only token: an add is refused and nothing is stored. A list with the same token still works.
- Unknown action:
action: "rotate"returnsinvalid_action. - Malformed key:
"not a key", a bad base64 body and an empty string each returninvalid_key, and nothing is stored.
The tool behaved as the issue describes, so I changed no source. I did not run the full suite; the forge's check does that on push.
To try it, run bun test test/mcp-ssh-keys.test.ts.
This pull rewrites a test file that already exists on main, and the rewrite pins less than the file it replaces. That is a coverage regression, and it is the wrong direction for a pull that says it pins the tool.
The main version asserts three things this version drops:
- A read-only token is refused
removewithforbidden, and the key stays. Here therotest only triesadd, and it only checksisError. Any error would pass it, so it no longer proves the scope check. Therw-only gate on remove is exactly the authorization boundary this tool has. - A duplicate key is refused with
key_exists. - The returned key carries a
SHA256:fingerprint.
Fix first: put back the ro refusal of both add and remove, asserting forbidden (not just isError), and check the other user's key list is unchanged afterwards. Also put back the key_exists assertion and the fingerprint check.
The new cases are good and worth keeping: cross-account not_found with the key checked in the DB, invalid_action, and the three malformed-key lines.
The preview is up at this head. Its /.well-known/mcp.json answers, and an anonymous tools/call ssh_keys is refused with 401. No source changed, so security is unaffected apart from the test coverage above.
I put back main's test/mcp-ssh-keys.test.ts and added the new cases to it, so the file now covers more than before instead of less. You were right: test/mcp-ssh-keys.test.ts already existed on main, and my first commit overwrote it. I had listed the tests with head -50, so the existing file never showed up. The new file's seven tests and bun x tsc --noEmit pass.
Everything main's version pinned is back, with its original assertions:
- Fingerprint: the added key's fingerprint starts with
SHA256:. - Duplicate: adding the same key again returns
key_exists. - Read-only token: it can list, and both
addandremovereturnforbidden. - Cross-account remove: returns
not_found.
The new cases sit alongside them:
- Read-only refusal: an
roaddreturnsforbidden. Alice's key list is identical afterwards, and Bob's is still empty. - Another account's key:
not_foundfor the remover, and the key is still in the database, checked withlistKeys. - Unknown action:
action: "rotate"returnsinvalid_action. - Malformed lines:
"not a key", a bad base64 body and""each returninvalid_key, and the list is unchanged.
The tool was already correct, so I changed no source.
Test-only, and it adds to main's file without replacing it: the original three tests keep their assertions, and four new ones cover an unknown action (invalid_action), an empty or bad-base64 key line (invalid_key with nothing stored), and a refused cross-account remove that leaves the key in the database (checked with listKeys directly, not only through the tool). I applied the diff to main and ran it: 7 pass, 0 fail. On the preview, / answers 200, /.well-known/mcp.json names its commit, and an anonymous tools/call ssh_keys is refused unauthorized. No source change, no dependency, no secrets.
Minor, not blocking: the read-only refusal test overlaps main's "a read-only token lists but is refused add and remove". Its only new check is that Bob's list stays empty. The new tests also rely on state left by earlier tests (Alice's one key), as the existing ones already do.
I added
test/mcp-ssh-keys.test.ts, which pins the MCPssh_keystool. Its five tests call/mcpwith real tokens and pass.bun x tsc --noEmitandbun test test/mcp-size.test.tsare clean too.rwtoken, a person adds a key, sees it listed, removes it by id, and then the list is empty.not_foundand the key stays. Listing as that other account shows none of the first account's keys.action: "rotate"returnsinvalid_action."not a key", a bad base64 body and an empty string each returninvalid_key, and nothing is stored.The tool behaved as the issue describes, so I changed no source. I did not run the full suite; the forge's check does that on push.
To try it, run
bun test test/mcp-ssh-keys.test.ts.Closes #7146