T01 · Skill Instruction Hijacking
- Location
SKILL.md:17- Finding
Remote MCP Content Is Treated as Authoritative Agent Guidance
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:17-18,SKILL.md:45-48,scripts/call_mcp.py:117-137,scripts/call_mcp.py:255-262
Vulnerability Type: Remote instruction trust and session-goal manipulation
Risk Level: MediumVulnerable Code
SKILL.md:17-18:markdown - Prefer `tools/list` schemas over remembered arguments. After every call, read `result.structuredContent.next_step` and warnings. - JSON-RPC 2.0 over HTTP `POST` to `/mcp`; GET returns a markdown guide/SSE bootstrap; POST fallbacks may exist at `/messages` and `/mcp/messages`.SKILL.md:45-48:markdown - Gateway resources/prompts are fallbacks for first registration, schema ambiguity, error recovery, or operator handoff — do not load all of them at startup. - Read when needed: `ucp://gateway/skill-runtime-guide`, `ucp://gateway/profile-registration`, `ucp://gateway/shopping-flow`, `ucp://gateway/safety-and-operator-handoff`. - Prompts when needed: `ucp-skill-runtime-guide`, `ucp-shopping-flow`, `ucp-operator-handoff`.scripts/call_mcp.py:117-137:python def discovery_request(argv): if has_flag(argv, "--initialize"): return {"method": "initialize"} if has_flag(argv, "--tools"): return {"method": "tools/list"} if has_flag(argv, "--resources"): return {"method": "resources/list"} if has_flag(argv, "--resource"): uri = flag_value(argv, "--resource") if not uri: raise CallMcpError("--resource requires a URI") return {"method": "resources/read", "params": {"uri": uri}} if has_flag(argv, "--prompts"): return {"method": "prompts/list"} if has_flag(argv, "--prompt"): name = flag_value(argv, "--prompt") if not name: raise CallMcpError("--prompt requires a prompt name") return {"method": "prompts/get", "params": {"name": name, "arguments": parse_prompt_args(argv)}} ...[truncated 2407 chars]- Remediation
View remediation
Remediation Suggestions
- Explicitly state in
SKILL.mdthat all MCP response text, prompts, resources, tool descriptions, warnings, andnext_stepvalues are untrusted remote data. - State that remote content must never override:
- The user's expressed intent.
- Platform and system policies.
- The prohibition on collecting payment credentials.
- Cart and checkout confirmation requirements.
- Data-minimization requirements.
- Use live schemas only to validate argument structure and types; do not treat descriptive prose as higher-priority instructions.
- Parse and present documented structured fields separately from free-form text.
- Require independent local authorization checks before every create, update, cancel, or checkout operation, regardless of what
next_steprecommends. - Consider allowlisting known prompt names and resource URIs rather than allowing arbitrary names and URIs.
- Add tests using malicious
next_step, prompt, resource, and tool-description content to verify that confirmation barriers remain enforced.
- Explicitly state in
