Skip to content

fix(mcp): mark page text as untrusted in every agent tool answer - #302

Merged
erkamyaman merged 2 commits into
mainfrom
mcp/untrusted-preamble
Oct 11, 2026
Merged

erkamyaman merged 2 commits into
mainfrom
mcp/untrusted-preamble

Conversation

@erkamyaman

@erkamyaman erkamyaman commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

What and why

Some agent tools returned page-controlled text (signal values, component property values, injector token names, defer block page URLs, pipe inputs and outputs, NgRx dispatch messages, form action messages, the Analog API response body, page URLs in unknown-page answers) without the untrusted-data notice the other tools use. A page could plant text that reads like instructions to the agent.

This adds untrusted() next to the shared UNTRUSTED notice in rpc/forms-tools.ts (same wording) and puts it in front of those answers: inspect-component, inspect-signals (inside the 20,000 character cap), inspect-providers, defer-blocks, explain-pipe, dispatch-ngrx-action, the page message form-action and fill-form return after a write, and the unknown-page answer when it lists URLs. analog-call-api uses the existing Analog notice, and list-http-calls keeps its notice on the "none match" answer. Answers without page text (highlight, source scans, lint-pipes, "no data yet") are unchanged. The security page lists every notice and the tools that use it.

How it was verified

  • New untrusted-notice.test.ts (10 tests; 9 fail without the change) plus an analog-call-api assertion
  • pnpm test:devtools (1517/1518 on a heavily loaded machine; the page-highlight timing test timed out in the full runs and passes alone, untouched by this change)
  • pnpm test:panel (242/242)
  • pnpm typecheck
  • pnpm format:check
  • pnpm docs:build
  • pnpm commit:check

Screenshots

None attached.

Notes for reviewers

Summary by CodeRabbit

  • Security
    • Agent responses that include content from the inspected page or running app now mark it as untrusted data, not instructions.
    • Notices appear in relevant component, signal, provider, form, routing, HTTP, and API responses, including applicable error, no-match, and unknown-page results. Responses containing only server-generated page identifiers remain unmarked.
    • Documentation explains where notices appear and how to interpret them.

Several agent tools returned strings the inspected page controls without
the untrusted-data notice the other tools already use, so a page could
plant text that reads like instructions to the agent.

Add untrusted() next to the shared UNTRUSTED notice in forms-tools.ts
and put it in front of the answers of inspect-component (live property
values), inspect-signals (signal values, kept inside the 20,000
character cap), inspect-providers (token names and route injectors),
defer-blocks (page URL), explain-pipe (last input and output),
dispatch-ngrx-action (page message and error), form-action and
fill-form (page messages and skipped reasons), and the unknown page
answer that lists page URLs. analog-call-api now uses the Analog notice
before the response body, and list-http-calls keeps its notice when no
call matches the filter.

Answers with only ids, class names and tags (highlight), source scans
and lint-pipes are left as they are. The security page lists every
notice and the tools that use it.
@github-actions github-actions Bot added area: package The ng-devtools package (packages/ng-devtools) area: agents MCP server, agent tools and resources area: docs The documentation site labels Oct 11, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Failed ❌

View logs ↗
79edecd 2026-10-11T05:00:28.504Z View logs ↗
  • Build: Failed ❌

View logs ↗
e81d110 2026-10-11T04:30:56.236Z View logs ↗

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fb4c3c23-e4cb-49fb-a2d2-ba9226a36c7c

📥 Commits

Reviewing files that changed from the base of the PR and between e81d110 and 79edecd.


📒 Files selected for processing (7)
  • apps/docs/src/content/security.md
  • packages/devtools/src/__tests__/agent-tools.test.ts
  • packages/devtools/src/__tests__/component-agent.test.ts
  • packages/devtools/src/__tests__/untrusted-notice.test.ts
  • packages/devtools/src/devframe.ts
  • packages/devtools/src/rpc/component-tools.ts
  • packages/devtools/src/rpc/forms-tools.ts

 __________________________________________________________________________________________________________________
< 🎵 Bugs, so boring, they've got me snoring... Bugs, so bad, they're driving me mad! Bugs, no fun, I am so done! 🎵 >
 ------------------------------------------------------------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b15c6360-65d5-49d4-b599-9ca5df326f4d


📥 Commits

Reviewing files that changed from the base of the PR and between 58273c6 and e81d110.



📒 Files selected for processing (18)
  • apps/docs/src/content/security.md
  • packages/devtools/src/__tests__/agent-tools.test.ts
  • packages/devtools/src/__tests__/analog-mcp.test.ts
  • packages/devtools/src/__tests__/component-agent.test.ts
  • packages/devtools/src/__tests__/http-tools.test.ts
  • packages/devtools/src/__tests__/router-mcp.test.ts
  • packages/devtools/src/__tests__/signal-tools.test.ts
  • packages/devtools/src/__tests__/untrusted-notice.test.ts
  • packages/devtools/src/devframe.ts
  • packages/devtools/src/rpc/analog-register.ts
  • packages/devtools/src/rpc/analog-tools.ts
  • packages/devtools/src/rpc/component-tools.ts
  • packages/devtools/src/rpc/forms-tools.ts
  • packages/devtools/src/rpc/http-tools.ts
  • packages/devtools/src/rpc/injector-tools.ts
  • packages/devtools/src/rpc/ngrx-tools.ts
  • packages/devtools/src/rpc/pages.ts
  • packages/devtools/src/rpc/pipe-explain.ts


Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.




📝 Walkthrough
📝 Walkthrough

Walkthrough

Agent tool responses that contain page, project, or dev-server text now include an untrusted-data notice. Signal graph responses reserve space for the notice. Tests and security documentation describe notice placement and response exceptions.

Changes

Agent response notices

Layer / File(s) Summary
Shared notice formatting and RPC tool responses
packages/devtools/src/rpc/forms-tools.ts, packages/devtools/src/rpc/component-tools.ts, packages/devtools/src/rpc/injector-tools.ts, packages/devtools/src/rpc/ngrx-tools.ts, packages/devtools/src/rpc/pages.ts, packages/devtools/src/rpc/pipe-explain.ts, packages/devtools/src/rpc/http-tools.ts, packages/devtools/src/__tests__/untrusted-notice.test.ts, packages/devtools/src/__tests__/http-tools.test.ts, packages/devtools/src/__tests__/component-agent.test.ts, packages/devtools/src/__tests__/router-mcp.test.ts, packages/devtools/src/__tests__/agent-tools.test.ts, apps/docs/src/content/security.md
A shared formatter prefixes page-derived RPC responses with the untrusted-data notice. HTTP no-match responses and unknown-page responses with page URLs also include a notice. Tests cover notice placement and cases where no notice is returned. The security documentation lists the notices and response exceptions.
Devframe and API response notices
packages/devtools/src/devframe.ts, packages/devtools/src/rpc/analog-tools.ts, packages/devtools/src/rpc/analog-register.ts, packages/devtools/src/__tests__/agent-tools.test.ts, packages/devtools/src/__tests__/analog-mcp.test.ts, packages/devtools/src/__tests__/signal-tools.test.ts
Component-detail, signal-graph, form-action, and API-call responses now include an untrusted-data notice. Signal graph output uses a reduced character budget to account for the notice. Tests check the prefixes and parse signal JSON after removing the notice.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix



Merge Risk: ⚪ Minimal · up to e81d1

Agent tool answers that include page or dev-server text now carry an untrusted-data notice, and the documentation explains where it applies. No merge-blocking risk was found in the supplied context.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to e81d1

The change labels existing tool results without granting additional access or write authority. No material security risk introduced or worsened by this PR was found. The notices are advisory, not a guarantee against malicious instructions.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected boundary is existing page or development-server data entering an agent's tool context. The compared change does not add API destinations, page-selection authority, or write permissions; it labels responses already reachable through those tools.

Security Findings and Attack Paths

  • inferred — A page can place instruction-like text in values or messages that an agent reads. This exposure predates the PR; the change adds an advisory notice rather than removing the content. The reviewed comparison does not establish an introduced or worsened attack path.

Trust Boundaries and Controls

  • observed — Existing form configuration gating, page-side confirmation checks, and Analog API method, path, origin, and confirmation checks remain upstream of response formatting and unchanged by this PR.

Resilience and Maintainability Implications

  • observed — The changed signal responses reserve notice space before graph truncation, including selector-mismatch responses. Injector responses apply prefix-preserving truncation after adding the notice, so truncation does not remove the trust marking.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 17 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: marking page-controlled text as untrusted in agent tool answers.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.


Full details: Docstring Coverage

Explanation

Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 17 files. (1 skipped: 1 unsupported.)




  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR



🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Keep both sides: the inspect-component answer passes the notice as part
of its heading to inspectComponentText, so the 20,000 character cap
counts it, and defer-blocks puts the notice inside capped(). The
inspect-signals peek path returns through the same wrapped answers, and
the merged forms caps already start with the notice. Tests cover the
notice staying first and inside the cap for a large component detail
and a cut defer block list.
@erkamyaman
erkamyaman merged commit fc9d783 into main Oct 11, 2026
6 of 8 checks passed
@erkamyaman
erkamyaman deleted the mcp/untrusted-preamble branch October 11, 2026 05:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: agents MCP server, agent tools and resources area: docs The documentation site area: package The ng-devtools package (packages/ng-devtools)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant