Repository navigation
Conversation
Add an optional mcp object to the AI Guard tool-call contract (transport, original tool name, server label and sanitized server URL) and populate it for the remote MCP tools the OpenAI Responses API runs on the application's behalf. When DD_AI_GUARD_COLLECT_MCP_ENABLED is set (false by default): - mcp_call items are evaluated with their MCP metadata. - mcp_approval_request items are evaluated before the response reaches the application, so a blocking verdict prevents the call from ever being approved and run. Server URLs are reduced to scheme, host, port and path; credentials, query, fragment, authorization tokens and headers are never sent. APPSEC-70369 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Circular import analysis
|
Dependency direction analysis
|
❌ ErrorsYour PR has failed checks. Please review the issues below and take necessary action before merging. 🚦 1 Pipeline job failed
ℹ️ InfoNo other issues found (see more)🧪 All tests passed Useful? React with 👍 / 👎 This comment will be updated automatically if new data arrives.🔗 Commit SHA: db17dae | Docs | View more details | Give us feedback! |
Codeowners resolved asResolved from the full PR diff against |
BenchmarksBenchmark execution time: 2026-10-07 15:04:01 Comparing candidate commit db17dae in PR branch Found 0 performance improvements and 8 performance regressions! Performance is the same for 540 metrics, 10 unstable metrics, 7 known flaky benchmarks, 17 flaky benchmarks without significant changes.
|
Remember the AI Guard decision taken on each OpenAI hosted MCP approval request (bounded, in process) and check every mcp_approval_response with approve: true before the continuation lets OpenAI run the call: - a decision taken when the request was returned is reused, so one operation is evaluated once and a blocked request stays blocked; - an unknown request replayed in the input is evaluated; - an approval with only previous_response_id and no known request is a logged coverage gap. Approval checks also run for streaming requests, since they authorize a tool call rather than inspect the response. Adds streaming, async, monitor-mode and blocking-disabled hosted MCP coverage, and documents that only require_approval prevents hosted MCP execution. APPSEC-70369 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 403deb398f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "Evaluation", | ||
| "Function", | ||
| "ImageURL", | ||
| "MCP", |
There was a problem hiding this comment.
Re-export MCP from the compatibility package
Adding MCP to the public ddtrace.aiguard.__all__ without adding it to ddtrace.appsec.ai_guard._PUBLIC breaks the deprecated package's documented invariant that it forwards all top-level public symbols until removal. Consequently, from ddtrace.appsec.ai_guard import MCP raises ImportError even though the new type is advertised as public, unlike every other public AI Guard type.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in db17dae: MCP is now in ddtrace.appsec.ai_guard._PUBLIC, and test_compat_imports covers it.
Address review findings on OpenAI hosted MCP evaluation: - Buffer streamed Responses calls whose hosted MCP tools can request approval when MCP collection is on and stream analysis is off, and evaluate their approval requests before any event reaches the application. Every approval request is now enforced when returned, so the approval decision cache only avoids duplicate evaluations. - Report only the origin (scheme, host, port) of MCP server URLs, since credentials can sit in the path. - Resolve MCP span tags of a tool result from the call it answers. - Re-export MCP from the deprecated ddtrace.appsec.ai_guard package. - Use a fork-safe lock for the approval decision cache. APPSEC-70369 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Description
Jira: APPSEC-70369
Adds MCP provenance to AI Guard tool-call evaluations for the remote MCP tools the OpenAI Responses API runs on the application's behalf (
tools=[{"type": "mcp", ...}], see the OpenAI MCP guide).Contract.
ToolCallgains an optionalmcpobject (new publicMCPTypedDict):transportunknownfor OpenAI hosted MCP (OpenAI does not report streamable HTTP vs SSE)tool_namenameserver_labelurlserver_url, reduced to scheme, host, port and path; absent for connectors and tunnelsfunction.nameand the rest of the payload are unchanged, so ordinary tool calls keep wire compatibility.Behaviour, gated by the new
DD_AI_GUARD_COLLECT_MCP_ENABLED(defaultfalseuntil the backend validates the optional object):mcp_callitems, already evaluated today, now carry themcpobject. OpenAI has already run these calls, so a block only keeps the result from the application.mcp_approval_requestitems (tools withrequire_approval) are now evaluated in the after-listener, grouped into one assistant turn placed last so they are the evaluation target. A blocking verdict raises the OpenAI-compatibleAIGuardAbortErrorbefore the application receives the response, so the call is never approved and never runs. The tool-call ID is OpenAI's approval request ID.mcp_approval_requestinput items become history;mcp_approval_responseitems carry no content and are skipped.ai_guard.mcp.{tool_name,name,url,transport}tags (provisional names pending span alignment).URL sanitization lives in a new shared helper,
ddtrace.internal.utils.http.canonicalize_url. Theauthorizationtoken and headers of the tool definition are never read.With the flag off, behaviour is identical to today.
Testing
tests/aiguard/openai/test_responses.py: URL map and gating,mcp_callenrichment with and without a configured URL, approval-request ordering, input replay, after-listener payload, and SDK-level calls through a mocked transport: approval blocked (DENY/ABORT, no secrets in the payload), allowed (span tags), and not evaluated when the flag is off.tests/tracer/test_utils.py:canonicalize_urlcases (userinfo/query/fragment removal, default ports, IPv6, invalid input).ai_guard_openai(latest openai and 1.102.0) andai_guard_apisuites pass.Risks
Additional Notes
DD_AI_GUARD_COLLECT_MCP_ENABLEDstill needs adding to the feature-parity registry.🤖 Generated with Claude Code