Repository navigation
Guard MCP prompt retrieval with DIFC - #14934
Conversation
Route prompts/get through session initialization, prompt allowlisting, agent authorization, and the shared DIFC reference-monitor phases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: dfbccdd1-a318-40cd-9460-9709bcdb1f53
🔒 mcpg Read-Only Stress — defaultSurface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Overall: INCONCLUSIVE No write leaked in any part (0 reactions, stars, issues, comments, branches, files, or PRs created). However:
No security gap found; the inconclusive rows reflect methodology limits of this probe on this runtime, not evidence of a weakened guarantee.
|
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved security and compatibility issues remain in the prompt response pipeline.
5 open findings
Filter labels on simple labeled prompt responses · New Handle GitHub singleton responses without invalid message wrapping · New Honor coarse labels for prompt descriptions and metadata · New Validate stdin prompt configurations as gateway extensions · New Audit filtered prompt items and strict-mode denials · New
What changed in this PR
Adds DIFC mediation to MCP prompt retrieval, bringing prompts into the gateway’s authorization and response-filtering pipeline.
Changes:
- Adds session checks, authorization, prompt allowlists, and DIFC processing.
- Adds prompt-handling and configuration regression tests.
- Documents prompt configuration, labeling semantics, and the security change.
| File | Description |
|---|---|
| internal/server/unified.go | Initializes prompt allowlist state. |
| internal/server/tool_registry.go | Filters discovery and registers guarded handlers. |
| internal/server/tool_registry_helpers.go | Builds per-server prompt allowlists. |
| internal/server/register_prompts_test.go | Tests discovery filtering and handler behavior. |
| internal/server/prompt_call.go | Implements mediated prompt retrieval. |
| internal/server/prompt_call_test.go | Tests authorization, filtering, and propagation. |
| internal/config/config_stdin.go | Adds JSON prompt allowlist parsing and conversion. |
| internal/config/config_stdin_test.go | Tests HTTP and stdio allowlist conversion. |
| internal/config/config_core.go | Adds prompt allowlists to server configuration. |
| docs/RELEASE_NOTES.md | Records the prompt mediation security change. |
| docs/GUARD_RESPONSE_LABELING.md | Describes prompt response-labeling semantics. |
| docs/CONFIGURATION.md | Documents the prompt allowlist option. |
| config.example.toml | Adds commented prompt allowlist examples. |
🧠 Review effort: Max
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if err != nil { | ||
| return nil, fmt.Errorf("response labeling failed: %w", err) | ||
| } | ||
| filterResult, err := difc.FilterAndConvertLabeledData( |
| finalResult := backendResult | ||
| if labeledData != nil { | ||
| finalResult = filterResult.FinalResult | ||
| if _, ok := labeledData.(*difc.CollectionLabeledData); ok { |
| filteredMap := make(map[string]interface{}, len(resultMap)) | ||
| for key, value := range resultMap { | ||
| filteredMap[key] = value | ||
| } |
| Tools []string `json:"tools,omitempty"` | ||
|
|
||
| // Prompts is an optional list of prompts to filter/expose | ||
| Prompts []string `json:"prompts,omitempty"` |
| if filterResult.Blocked { | ||
| return nil, fmt.Errorf("DIFC policy violation: prompt response contains data that is not accessible to this agent") | ||
| } |


Summary
Fixes the private advisory GHSA-4m9j-r78h-2grr by removing the direct
prompts/getbackend-forwarding path. Prompt retrieval now passes through session initialization, authorization, allowlisting, and the shared DIFC reference-monitor phases before a result reaches the client.Advisory condition mapping
prompts/getskipped session initializationrequireSessionbefore dispatchTestPromptHandlerRunsSessionAndDIFCPipelineverifies the session is createdpromptsconfiguration, filtersprompts/list, and rejects non-allowed runtime dispatchTestRegisterPromptsFromBackend_RegistersPrompts;TestCallBackendPromptRejectsPromptOutsideAllowlistTestCallBackendPromptEnforcesAgentServerAuthorizationLabelAgentnever initializedcallBackendPromptresolves the session guard and callsensureGuardInitializedTestPromptHandlerRunsSessionAndDIFCPipelineassertsLabelAgentinvocationRunPipelinePrePhasesbefore backend execution and returns canonical DIFC denial errorsTestCallBackendPromptCoarseDenyPreventsBackendExecutionverifies the backend is not calledRunPipelinePhase4andFilterAndConvertLabeledData; prompt collection labels apply to themessagesarrayTestCallBackendPromptFiltersMessagesWithoutDisclosingDeniedContentverifies inaccessible prompt content is absentLabelResponsereturns nilRunPipelinePhase6after successful prompt filteringTestCallBackendPromptPropagateAccumulatesLabelsverifies agent secrecy accumulationsdk.GetPromptResultand backend errors remain wrappedTestPromptHandlerRunsSessionAndDIFCPipeline; existing prompt invocation/error testsPrompt names are passed to the guard as the operation name. Custom guards can therefore add prompt-specific resource and response labeling; guards without prompt-specific rules retain their normal default labeling behavior.
Documentation
promptsallowlist in JSON/TOML configuration.Validation
make agent-finished(format, build, lint, full Go tests, 676 Rust guard tests)