feat(prompts): per-prompt rug-pull baseline MVP (spec 100) - #1010
Merged
Conversation
Implements the core of spec 100 (merged in #1009): the tool-quarantine (Spec 032) analogue for aggregated upstream prompts. A trusted server that passes admission with a benign prompt and later mutates its advertised metadata is now caught and the changed prompt is WITHHELD from prompts/list until approved — closing the last F2 gap from the PR #973 review. Scope (metadata only): the baseline hashes advertised LIST metadata (name + description + arguments); get-time prompts/get message content is inherently not baselineable here (spec Non-Goals) and stays defended by the existing F2 sanitisation + F12 caps. - storage: parallel PromptApprovalRecord + prompt_approvals bucket + CRUD (+ Manager wrappers), mirroring the tool ops 1:1 — NOT a ToolApprovalRecord overload (the server:tool / server:prompt key spaces would collide). - engine (internal/server/prompt_quarantine.go): calculatePromptApprovalHash (sha256(name|desc|normalizeJSON(args)), excludes Meta/Title), checkPromptApprovals with the pending/changed/approved state machine + baseline-pass + QuarantineEnabled kill-switch + TrustMode/AutoApproveToolChanges reuse, a fail-closed enforcePromptInvariant transition spine, filterBlockedPrompts, and the ApprovePrompt/ApproveAllPrompts mutators (which re-baseline + RefreshPrompts()). - hook: checkPromptApprovals + filterBlockedPrompts run in RefreshPrompts after the TPA scan-and-drop, before registration. Withholding IS the block — a prompt never passed to SetPrompts is absent from prompts/list and fails prompts/get natively, so there is no runtime get-time gate. Tests: hash stability/change, fail-closed invariant, first-seen→pending, approve→registered, rug-pull change→withheld→revert→re-approved, trust=auto auto-approve, ApproveAllPrompts, and a full-RefreshPrompts withholding integration test. Existing aggregation tests set quarantine off (they verify aggregation, not the baseline). Deferred to a follow-up: the quarantine_security MCP ops (inspect_prompts/approve_prompt/approve_all_prompts), REST twins, and the Vue review banner — the approve API (ApprovePrompt/ApproveAllPrompts) is ready to wire. Adding the MCP tool-schema op requires regenerating the 3 frozen tool-surface goldens, done deliberately in that PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7J8Yv5zr4tMQZaY3ot3Za
Deploying mcpproxy-docs with
|
| Latest commit: |
4e55ef9
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://2bc3d56f.mcpproxy-docs.pages.dev |
| Branch Preview URL: | https://feat-prompt-rugpull-mvp.mcpproxy-docs.pages.dev |
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
📦 Build ArtifactsWorkflow Run: View Run Available Artifacts
How to DownloadOption 1: GitHub Web UI (easiest)
Option 2: GitHub CLI gh run download 32262266585 --repo smart-mcp-proxy/mcpproxy-go
|
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.
Implements the MVP of spec 100 (merged in #1009) — the tool-quarantine (Spec 032) analogue for aggregated upstream prompts, closing the last F2 gap from the PR #973 review. A trusted server that passes admission with a benign prompt and later mutates its advertised metadata is now caught, and the changed prompt is withheld from
prompts/listuntil approved.The one constraint (metadata only)
The baseline hashes advertised LIST metadata (name + description + arguments). Get-time
prompts/getmessage content has no list-time artifact to hash against and is inherently not baselineable here (spec Non-Goals); that path stays defended by the existing F2 sanitisation and F12 size cap. This is stated loudly in the spec and the code so it's never mistaken for content protection.What's here
PromptApprovalRecord+prompt_approvalsbucket + CRUD (+ Manager wrappers), mirroring the tool ops 1:1 (not aToolApprovalRecordoverload — theserver:tool/server:promptkey spaces would collide).internal/server/prompt_quarantine.go) —calculatePromptApprovalHash(sha256(name|desc|normalizeJSON(args)), excludesMeta/Title),checkPromptApprovalswith the pending/changed/approved state machine + baseline-pass +QuarantineEnabledkill-switch +TrustMode/AutoApproveToolChangesreuse, a fail-closedenforcePromptInvarianttransition spine,filterBlockedPrompts, and theApprovePrompt/ApproveAllPromptsmutators.RefreshPromptsafter the TPA scan-and-drop, before registration. Withholding is the block: a prompt never passed toSetPromptsis absent fromprompts/listand failsprompts/getnatively, so there's no runtime get-time gate (the big simplification over tools).Tests
Hash stability/change, fail-closed invariant, first-seen→pending, approve→registered, rug-pull change→withheld→revert→re-approved, trust=auto auto-approve,
ApproveAllPrompts, and a full-RefreshPromptswithholding integration test.Deferred (immediate follow-up)
The
quarantine_securityMCP ops (inspect_prompts/approve_prompt/approve_all_prompts), REST twins, and the Vue review banner. The approve API (ApprovePrompt/ApproveAllPrompts) is ready to wire — I held the MCP tool-schema op out of this PR because it requires regenerating the 3 frozen tool-surface goldens, which is cleaner to do deliberately in that PR. Until then a held prompt is recoverable by approving programmatically or setting the server totrust: auto.The
enforceInvariantport is the security-critical fail-closed spine and is the part most worth a careful review.🤖 Generated with Claude Code