Skip to content

Commit cd19eaa

Browse files
committed
docs: update migration guide and resources doc for matcher changes
- migration.md: path-safety checks now raise ResourceSecurityError rather than silently falling through; null bytes are rejected by default; templates may have at most one multi-segment variable - resources.md: add reject_null_bytes to the settings table; note that ResourceSecurity is a heuristic and safe_join remains the containment boundary
1 parent 0eeafe7 commit cd19eaa

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

docs/migration.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -548,14 +548,17 @@ await client.read_resource(str(my_any_url))
548548
### Resource templates: matching behavior changes
549549

550550
Resource template matching has been rewritten with RFC 6570 support.
551-
Four behaviors have changed:
551+
Several behaviors have changed:
552552

553553
**Path-safety checks applied by default.** Extracted parameter values
554-
containing `..` as a path component or looking like an absolute path
555-
(`/etc/passwd`, `C:\Windows`) now cause the template to not match.
556-
This is checked on the decoded value, so `..%2Fetc` and `%2E%2E` are
557-
caught too. Note that `..` is only flagged as a standalone path
558-
component, so values like `v1.0..v2.0` or `HEAD~3..HEAD` are unaffected.
554+
containing `..` as a path component, a null byte, or looking like an
555+
absolute path (`/etc/passwd`, `C:\Windows`) now raise
556+
`ResourceSecurityError` and halt template iteration — a strict
557+
template's rejection no longer falls through to a later permissive
558+
template. This is checked on the decoded value, so `..%2Fetc`,
559+
`%2E%2E`, and `%00` are caught too. Note that `..` is only flagged as
560+
a standalone path component, so values like `v1.0..v2.0` or
561+
`HEAD~3..HEAD` are unaffected.
559562

560563
If a parameter legitimately needs to receive absolute paths or
561564
traversal sequences, exempt it:
@@ -570,10 +573,17 @@ from mcp.server.mcpserver import ResourceSecurity
570573
def inspect_file(target: str) -> str: ...
571574
```
572575

573-
**Template literals are regex-escaped.** Previously a `.` in your
576+
**Template literals match exactly.** Previously a `.` in your
574577
template matched any character; now it matches only a literal dot.
575578
`data://v1.0/{id}` no longer matches `data://v1X0/42`.
576579

580+
**At most one multi-segment variable.** Templates may contain a single
581+
`{+var}`, `{#var}`, or explode-modified variable (`{/var*}`, etc.).
582+
Two such variables make matching inherently ambiguous and now raise
583+
`InvalidUriTemplate` at decoration time. This is unlikely to affect
584+
existing templates since the previous Level 1 matcher did not support
585+
these operators at all.
586+
577587
**Query parameters match leniently.** A template like
578588
`search://{q}{?limit}` now matches `search://foo` (with `limit` absent
579589
from the extracted params so your function default applies). Previously

docs/server/resources.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,12 @@ The configurable checks:
224224
|-------------------------|---------|-------------------------------------|
225225
| `reject_path_traversal` | `True` | Rejects `..` sequences that escape the starting directory |
226226
| `reject_absolute_paths` | `True` | Rejects `/foo`, `C:\foo`, UNC paths |
227+
| `reject_null_bytes` | `True` | Rejects values containing `\x00` |
227228
| `exempt_params` | empty | Parameter names to skip checks for |
228229

230+
These checks are a heuristic pre-filter; for filesystem access,
231+
`safe_join` remains the containment boundary.
232+
229233
## Errors
230234

231235
If your handler can't fulfil the request, raise an exception. The SDK

0 commit comments

Comments
 (0)