You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(mcp): document redaction limitations and audit guidance
Add a "Limitations and gotchas" section calling out the things users
need to know before pointing an LLM at the MCP server:
- Audit your payloads BEFORE connecting any LLM — once it has seen a
secret, you can't unsend it. Two LLM-free audit paths: grep the
codebase for field names that store credentials/tokens/PII, and
inspect a normal Reactotron desktop session (the UI is intentionally
unredacted).
- Reactotron desktop UI is intentionally not redacted (it's for the
developer debugging their own app)
- Redaction is a blocklist — anything app-specific that doesn't match
a default rule passes through. Add via additionalRules.
- AsyncStorage values only redact when the storage key carries a
sensitive name; bare keys with bare values leak
- State path patterns only fire at known anchors (state resource and
request_state tool) and only support trailing wildcards
- Custom commands / display payloads use the generic deep walk only
- Data is unredacted at rest — anyone with desktop access can see it
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/mcp.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -102,6 +102,20 @@ This uses a **two-key model**: the server always applies its default rules unles
102
102
103
103
When multiple apps are connected, **each app's data is redacted with that app's own configuration**, even within a single MCP response that aggregates events from several apps (timeline, network, asyncstorage, etc.). One app's `additionalRules` won't redact another app's data, and one app's `removeRules` won't weaken redaction for any other app's data.
104
104
105
+
### Limitations and gotchas
106
+
107
+
> **Audit your app's payloads before pointing an LLM at the MCP server.** Redaction is defence in depth, not a guarantee. The default rules catch widely-used names and token formats, but anything app-specific (custom field names, homegrown token shapes, bare values without a recognisable shape) passes through unredacted. Do the audit *before* connecting any LLM — once an LLM has seen a secret, you can't unsend it. Two practical ways to audit: search your codebase for the field names you store credentials, tokens, or PII under, and inspect a normal Reactotron desktop session (the desktop UI is unredacted, so what you see there is roughly what an LLM would see minus the default-rule matches). Add anything sensitive to `additionalRules` (or to the desktop's settings modal) before the first LLM connection.
108
+
109
+
A few specific things worth knowing:
110
+
111
+
-**The Reactotron desktop UI is not redacted.** Redaction only happens at the MCP boundary. The desktop UI shows captured data verbatim — that's by design, since you're debugging your own app.
112
+
-**Redaction is a blocklist, not an allowlist.** Field names that aren't in `sensitiveKeys` and string values that don't match any `valuePatterns` regex pass through verbatim. A field literally called `mySpecialSecret` or a homegrown token format like `xz-…-…` is invisible to the default rules. Add them via the settings modal or `additionalRules`.
113
+
-**AsyncStorage values rely on the storage key carrying the sensitive name.**`AsyncStorage.setItem("auth:password", "hunter2")` redacts because the storage key contains `password`. `AsyncStorage.setItem("appData", "hunter2")` does *not* — neither the key nor the bare value match any default rule, so the value passes through verbatim. If your app stores secrets under non-descriptive storage keys, redaction won't help. Use the `ignore` option on the AsyncStorage plugin to skip those keys entirely.
114
+
-**State path patterns only fire at known anchors.** The `reactotron://state/current` resource and the `request_state` tool both pass the originating state path so absolute patterns (e.g. `auth.tokens.*`) match correctly. Other resources don't carry that anchor and can't apply path-based rules. If a sensitive subtree never matches by key name or value pattern, path patterns alone may not catch it.
115
+
-**State path patterns support trailing wildcard only.**`auth.tokens.*` works. `users.*.password` does not — you'd need to add `password` to `sensitiveKeys` (it already is by default) or list each path explicitly.
116
+
-**Custom commands and `display` payloads are walked generically.** If you emit free-form data via `Reactotron.display(...)` or a custom command, only key-name and value-pattern rules apply. Sensitive content in arbitrary shapes is on you.
117
+
-**Server defaults apply at the boundary, not at storage.** The relay server still receives the full payload over the WebSocket and stores it in the in-memory event buffer. Anyone with desktop access (or who can attach a debugger to the Reactotron process) can see the unredacted data. Redaction stops the data from reaching the MCP client; it does not encrypt anything at rest.
118
+
105
119
## Configuration
106
120
107
121
The MCP port defaults to **4567** and can be changed in Reactotron's settings (stored via electron-store as `mcpPort`).
0 commit comments