Skip to content

Python: Model MCP and FastMCP server handler parameters as remote sources (#22702) - #22750

Open
Tito0015 wants to merge 2 commits into
github:mainfrom
Tito0015:feature/python-mcp-remote-sources
Open

Tito0015 wants to merge 2 commits into
github:mainfrom
Tito0015:feature/python-mcp-remote-sources

Conversation

@Tito0015

@Tito0015 Tito0015 commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #22702.

This PR adds QL framework modeling for Python MCP (Model Context Protocol) and fastmcp server handler parameters as RemoteFlowSources.

Why QL Modeling instead of Models-as-Data (YAML)

Existing open PR #22703 models MCP via Models-as-Data (MaD) YAML (ThreatModelSource of kind remote). However, several legacy Python security queries (such as py/nosql-injection, py/xml-bomb, and py/xxe) query RemoteFlowSource::Range directly and do not consume MaD sources. Additionally, MaD currently misses tool handlers wrapped behind stacked custom decorators.

Modeling via Mcp.qll extending RemoteFlowSource::Range resolves both gaps natively.

What is Modeled

  • @mcp.tool(), @mcp.prompt(), @mcp.resource() (called and bare forms) across FastMCP and MCPServer (MCP 2.x).
  • Standalone fastmcp @tool, @prompt, @resource, and fastmcp.tools.tool.
  • Function registration via add_tool(...).
  • def and async def functions, methods registered via @self.mcp.tool(), and stacked decorators (@other above @mcp.tool()).

Exclusions

  • Method receivers (self / cls).
  • Parameters type-annotated as Context (or Context | None / Optional[Context]).

Testing

  • Added unit tests under python/ql/test/library-tests/dataflow/remote-flow-sources/ covering sync/async, bare/called decorators, keyword-only args, stacked decorators, and negative exclusion cases.
  • All tests pass locally via codeql test run.

@Tito0015
Tito0015 requested review from a team as code owners October 4, 2026 05:43
Alex-Hofer added a commit to Alex-Hofer/mcp-vulnbench that referenced this pull request Oct 4, 2026


Both proposals for Python MCP sources on the 28 Python cases: the class detects 9, the rows 13, both 13. Records what each covers that the other does not, the method (derived image, checks) and the limits of the comparison.
@Tito0015
Tito0015 force-pushed the feature/python-mcp-remote-sources branch from 2771182 to ec38c23 Compare October 5, 2026 19:46
@Tito0015

Tito0015 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Hi @geoffw0 — hope you are well.

You reviewed and merged my earlier C++ MMIO PR (#22438); thank you again for that. When you have a moment, I would appreciate a look at this Python follow-up for #22702.

It models MCP / FastMCP server handler parameters as RemoteFlowSources in QL (Mcp.qll), mainly so queries that still take RemoteFlowSource directly (e.g. py/xxe, py/xml-bomb, py/nosql-injection) can see MCP tool/prompt/resource args, and so stacked custom decorators on handlers are covered via getADecorator() (similar to Flask routing).

There is already open MaD coverage in #22703; this PR is intentionally QL-only and complementary. Library tests are under python/ql/test/library-tests/dataflow/remote-flow-sources/ and pass locally with codeql test run.

No rush — happy to adjust based on team preference (QL vs MaD, scope, naming). Thanks for any pointers.

*/

private import python
private import semmle.python.dataflow.new.DataFlow
@geoffw0

geoffw0 commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Hi, this looks reasonable at a glance (though I was a little surprised to see QL-modelled sources rather than MaD models). In any case I've started the tests and am handing over to another member of the team.

@Tito0015
Tito0015 force-pushed the feature/python-mcp-remote-sources branch 3 times, most recently from f188c3f to c909145 Compare October 8, 2026 19:24
@Tito0015
Tito0015 force-pushed the feature/python-mcp-remote-sources branch from c909145 to 1ae3030 Compare October 13, 2026 04:14
@owen-mc

owen-mc commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

I was also surprised by the assertion that QL-modelling was needed. I think it's correct though. We should fix it - I think changing those queries (and any others) to use ActiveThreatModelSource instead of RemoteFlowSource would solve it. I've put up this PR to fix it: #22822.

@Tito0015

Copy link
Copy Markdown
Contributor Author

Thanks for the review and for driving this upstream architectural fix in #22822, @owen-mc — migrating those queries to ActiveThreatModelSource is definitely the right long-term move for the Python dataflow pipeline.

I would love to collaborate directly on #22822. I can help benchmark query recall across the affected legacy rules, run test suites against edge cases, or review changes alongside the team.

Once #22822 lands, I will rebase and align this PR (#22750):

  1. MaD Alignment: Shift standard MCP tool, prompt, and resource handler definitions into Models-as-Data (MaD) YAML (coordinating with Python: Add models for the MCP server SDKs (mcp, fastmcp) #22703) so they feed cleanly into ActiveThreatModelSource.
  2. Targeted QL Modeling: Keep the QL logic in Mcp.qll focused strictly on dynamic AST patterns that MaD cannot currently express—specifically stacked and custom wrapper decorators (getADecorator()), class/instance registrations (@self.mcp.tool(), add_tool), and strict parameter exclusions (e.g., Context types).

With @Alex-Hofer already referencing this work in mcp-vulnbench, there is clear momentum to establish robust, high-recall taint tracking for Agentic AI and MCP server interfaces. I’m very keen to help the CodeQL team establish standard security coverage across this emerging attack surface.

For background on my work in AST/CPG query lowering and static analysis compiler infrastructure:

Let me know the best way to coordinate on #22822—I'm happy to push validation runs or draft test cases against your branch whenever helpful!

@owen-mc

owen-mc commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Thanks for the offer, @Tito0015 , but it isn't needed. #22822 has now been merged.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: model MCP server handler parameters (mcp, fastmcp) as remote sources

4 participants