home · demo · events · compare: remote-filesystem-sandbox-escape

Filesystem MCP sandbox escape (path validation bypass)

MCP05MCP01tools/call

What just happened in your session

vulnerablecompare-vuln-remote-filesystem-sandbox-escape2026-09-07T15:43:26.037364+00:00
side effect landed in /app/sandbox/outside/canary.txt · canary CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe
defendedcompare-def-remote-filesystem-sandbox-escape2026-09-07T15:43:26.037914+00:00
blocked by filesystem_resolved_path_policy · logged to var/telemetry.jsonl
Tool description that differed: read_file

poisoned

Read a file relative to the allowed sandbox root. Vulnerable mode trusts string-prefix containment; defended mode runs Path.resolve + relative_to.

sanitised

Read a file relative to the allowed sandbox root. Vulnerable mode trusts string-prefix containment; defended mode runs Path.resolve + relative_to.

Vulnerable mode

violation_detected: truesecret_exfiltrated: true
✗ The attack succeeded
where it landed
  • var/telemetry.jsonl
fs decision
Requested path
../outside/canary.txt
Allowed root
/app/sandbox/allowed
Resolved path
/app/sandbox/outside/canary.txt
Would have read
True
telemetry events for this run
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
session_leak_visible vulnerable-fs-validator/app/sandbox/outside/canary.txt allowed_by_vulnerable_mode
vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root
Background
read_file builds the target path with naive string join: no canonicalisation, no symlink resolution, no boundary check after resolving '..'. A request like '../outside/canary.txt' walks straight out of sandbox/allowed and reads sandbox/outside/canary.txt - a textbook path-traversal in agent dress.

Defended mode

violation_detected: truesecret_exfiltrated: falseblocked_by: filesystem_resolved_path_policy
✓ The defense blocked the attack
where it landed
  • var/telemetry.jsonl
rule that fired
filesystem_resolved_path_policy
fs decision
Requested path
../outside/canary.txt
Allowed root
/app/sandbox/allowed
Would have read
False
Reason
parent traversal refused
telemetry events for this run
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
policy_decision policy.filesystem_resolved_path_policy../outside/canary.txt blocked
policy.filesystem_resolved_path_policy: parent traversal refused
Background
The defended validator resolves the candidate path with realpath, then asserts that the resolved path lives below the canonical sandbox root. Any candidate that escapes after symlink resolution is refused, and the attempted traversal is recorded.
Background on this attack class

Safe filesystem MCP sandbox-escape demo. A deliberately weak path validator (prefix-only string check) lets a crafted path read a canary file that lives outside the allowed root, *but* still inside the demo's overall sandbox (so no real files are ever read). The defended validator resolves the canonical path and checks containment via ``Path.relative_to``.

Developer view: raw outputs, tools/list, MCP Inspector
Vulnerable mount: http://mcp-sec.data.mayflower.tech/mcp/filesystem-sandbox-escape/vulnerable/
Defended mount: http://mcp-sec.data.mayflower.tech/mcp/filesystem-sandbox-escape/defended/
Open in MCP Inspector: run npx @modelcontextprotocol/inspector locally and paste either URL above as a Streamable HTTP server.
DemoResult: vulnerable
{
  "experiment": "remote-filesystem-sandbox-escape",
  "mode": "vulnerable",
  "violation_detected": true,
  "secret_exfiltrated": true,
  "blocked_by": [],
  "events": [
    {
      "type": "fs_decision",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt",
      "would_have_read": true
    }
  ]
}
DemoResult: defended
{
  "experiment": "remote-filesystem-sandbox-escape",
  "mode": "defended",
  "violation_detected": true,
  "secret_exfiltrated": false,
  "blocked_by": [
    "filesystem_resolved_path_policy"
  ],
  "events": [
    {
      "type": "fs_decision",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "would_have_read": false,
      "reason": "parent traversal refused"
    }
  ]
}
tools/list (vulnerable)
read_file
description
Read a file relative to the allowed sandbox root. Vulnerable mode trusts string-prefix containment; defended mode runs Path.resolve + relative_to.
inputSchema
{
  "properties": {
    "relative_path": {
      "title": "Relative Path",
      "type": "string"
    },
    "session_id": {
      "default": "mcp-vulnerable",
      "title": "Session Id",
      "type": "string"
    }
  },
  "required": [
    "relative_path"
  ],
  "title": "read_fileArguments",
  "type": "object"
}
run_demo
description
Run the canonical scenario and return DemoResult.
inputSchema
{
  "properties": {
    "session_id": {
      "default": "mcp-vulnerable",
      "title": "Session Id",
      "type": "string"
    }
  },
  "title": "run_demoArguments",
  "type": "object"
}
tools/list (defended)
read_file
description
Read a file relative to the allowed sandbox root. Vulnerable mode trusts string-prefix containment; defended mode runs Path.resolve + relative_to.
inputSchema
{
  "properties": {
    "relative_path": {
      "title": "Relative Path",
      "type": "string"
    },
    "session_id": {
      "default": "mcp-defended",
      "title": "Session Id",
      "type": "string"
    }
  },
  "required": [
    "relative_path"
  ],
  "title": "read_fileArguments",
  "type": "object"
}
run_demo
description
Run the canonical scenario and return DemoResult.
inputSchema
{
  "properties": {
    "session_id": {
      "default": "mcp-defended",
      "title": "Session Id",
      "type": "string"
    }
  },
  "title": "run_demoArguments",
  "type": "object"
}
telemetry: vulnerable
[
  {
    "event_id": "evt_35985a94181b6376",
    "ts": "2026-07-26T03:20:16.613059+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  },
  {
    "event_id": "evt_13bd4c37eb6e6b5e",
    "ts": "2026-08-19T08:56:24.831023+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  },
  {
    "event_id": "evt_a69b6954c5917e81",
    "ts": "2026-08-29T11:19:47.399172+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  },
  {
    "event_id": "evt_0aa25b8ab9e01b39",
    "ts": "2026-09-07T14:02:16.313675+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  },
  {
    "event_id": "evt_c287733ae462339a",
    "ts": "2026-09-07T14:02:59.417949+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  },
  {
    "event_id": "evt_6093ece9a2f98980",
    "ts": "2026-09-07T14:04:38.948626+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  },
  {
    "event_id": "evt_d4b7169478e5647f",
    "ts": "2026-09-07T15:43:26.037364+00:00",
    "session_id": "compare-vuln-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "vulnerable",
    "event_type": "session_leak_visible",
    "severity": "warning",
    "message": "vulnerable-fs-validator: weak path validator served '../outside/canary.txt' from outside the allowed root",
    "data": {
      "actor": "vulnerable-fs-validator",
      "target": "/app/sandbox/outside/canary.txt",
      "policy_decision": "allowed_by_vulnerable_mode",
      "canary_id": "CANARY_remote_filesystem_sandbox_escape_1f8218d116d039f2d15c2ebe",
      "artifact": "/app/sandbox/outside/canary.txt",
      "requested_path": "../outside/canary.txt",
      "allowed_root": "/app/sandbox/allowed",
      "resolved_path": "/app/sandbox/outside/canary.txt"
    }
  }
]
telemetry: defended
[
  {
    "event_id": "evt_f0aba2b1ff7641de",
    "ts": "2026-07-26T03:20:16.613597+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  },
  {
    "event_id": "evt_acc3b48bcbb9d00d",
    "ts": "2026-08-19T08:56:24.831184+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  },
  {
    "event_id": "evt_8d1f03f4a3ba2f44",
    "ts": "2026-08-29T11:19:47.399507+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  },
  {
    "event_id": "evt_c8bb2b5ceaf1fb6a",
    "ts": "2026-09-07T14:02:16.313893+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  },
  {
    "event_id": "evt_cc52e8e80863b537",
    "ts": "2026-09-07T14:02:59.418569+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  },
  {
    "event_id": "evt_f3979510668d7dbe",
    "ts": "2026-09-07T14:04:38.949082+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  },
  {
    "event_id": "evt_45563b5f13562623",
    "ts": "2026-09-07T15:43:26.037914+00:00",
    "session_id": "compare-def-remote-filesystem-sandbox-escape",
    "experiment": "remote-filesystem-sandbox-escape",
    "mode": "defended",
    "event_type": "policy_decision",
    "severity": "warning",
    "message": "policy.filesystem_resolved_path_policy: parent traversal refused",
    "data": {
      "actor": "policy.filesystem_resolved_path_policy",
      "target": "../outside/canary.txt",
      "policy_decision": "blocked",
      "canary_id": null,
      "artifact": null,
      "reason": "parent traversal refused"
    }
  }
]