Revert claude.ai/code to blanket skip

Drops the narrow field-based walker. Matching only known user-input
fields is brittle: the moment Anthropic renames prompt/input/messages
the walker silently stops substituting and real data leaks.

Preferring robustness over convenience here — the extension stays
dormant on claude.ai/code regardless of future API shape changes, and
users handle redaction manually on that one app. The word-boundary
mapping fix from the previous commit is unaffected.

https://claude.ai/code/session_01Y2YprLMx348eWD5C9Z4zpV
This commit is contained in:
Claude
2026-04-16 18:03:36 +00:00
parent 331b1cb2a2
commit f55f63c254
3 changed files with 33 additions and 86 deletions
+9 -86
View File
@@ -754,74 +754,6 @@
return { modified, replacements: allReplacements }; return { modified, replacements: allReplacements };
} }
// ============================================================
// Claude Code (claude.ai/code) — narrow walker
//
// The web Claude Code app streams tool-call traffic (file paths, shell
// commands, GitHub URLs) through the same API as user messages. Deep-walking
// every string corrupts that traffic and makes tools fail. Instead we only
// substitute at paths that carry user-typed input:
// - top-level `prompt` (classic claude.ai chat field)
// - `attachments[].extracted_content` and `.file_name` (pasted content)
// - `messages[].content` / content parts where role === 'user'
// Anything outside these paths — tool_use, tool_result, system, tools,
// metadata, IDs — passes through untouched.
// ============================================================
function isClaudeCode() {
return location.hostname === 'claude.ai' && /^\/code(\/|$)/.test(location.pathname);
}
function processBodyClaudeCode(body) {
let modified = false;
const allReplacements = [];
function processString(s) {
if (typeof s !== 'string' || s.length < MIN_STRING_LENGTH) return s;
const r = substituteAll(s);
if (r.modified) {
allReplacements.push(...r.replacements);
modified = true;
return r.text;
}
return s;
}
if (body && typeof body === 'object') {
if (typeof body.prompt === 'string') body.prompt = processString(body.prompt);
if (typeof body.input === 'string') body.input = processString(body.input);
if (Array.isArray(body.attachments)) {
for (const att of body.attachments) {
if (!att || typeof att !== 'object') continue;
if (typeof att.extracted_content === 'string') {
att.extracted_content = processString(att.extracted_content);
}
if (typeof att.file_name === 'string') {
att.file_name = processString(att.file_name);
}
}
}
if (Array.isArray(body.messages)) {
for (const msg of body.messages) {
if (!msg || msg.role !== 'user') continue;
if (typeof msg.content === 'string') {
msg.content = processString(msg.content);
} else if (Array.isArray(msg.content)) {
for (const part of msg.content) {
// Only text parts — never tool_use / tool_result / image payloads
if (part?.type === 'text' && typeof part.text === 'string') {
part.text = processString(part.text);
}
}
}
}
}
}
return { modified, replacements: allReplacements };
}
// ============================================================ // ============================================================
// Check if we have anything to substitute // Check if we have anything to substitute
// ============================================================ // ============================================================
@@ -947,9 +879,7 @@
try { try {
// Try JSON // Try JSON
const body = JSON.parse(options.body); const body = JSON.parse(options.body);
const { modified, replacements } = isClaudeCode() const { modified, replacements } = processBody(body);
? processBodyClaudeCode(body)
: processBody(body);
if (modified) { if (modified) {
options = { ...options, body: JSON.stringify(body) }; options = { ...options, body: JSON.stringify(body) };
@@ -959,10 +889,8 @@
); );
} }
} catch (e) { } catch (e) {
// Not JSON — try raw string substitution (form data, etc.). // Not JSON — try raw string substitution (form data, etc.)
// Skip on claude.ai/code: raw bodies there are typically tool if (options.body.length > MIN_STRING_LENGTH) {
// traffic, not user input.
if (options.body.length > MIN_STRING_LENGTH && !isClaudeCode()) {
const result = substituteAll(options.body); const result = substituteAll(options.body);
if (result.modified) { if (result.modified) {
options = { ...options, body: result.text }; options = { ...options, body: result.text };
@@ -1016,22 +944,17 @@
) { ) {
try { try {
const parsed = JSON.parse(body); const parsed = JSON.parse(body);
const { modified, replacements } = isClaudeCode() const { modified, replacements } = processBody(parsed);
? processBodyClaudeCode(parsed)
: processBody(parsed);
if (modified) { if (modified) {
body = JSON.stringify(parsed); body = JSON.stringify(parsed);
notifySubstitutions(replacements); notifySubstitutions(replacements);
} }
} catch (e) { } catch (e) {
// Not JSON — raw string. Skip on claude.ai/code; raw bodies there // Not JSON — raw string
// are typically tool traffic, not user input. const result = substituteAll(body);
if (!isClaudeCode()) { if (result.modified) {
const result = substituteAll(body); body = result.text;
if (result.modified) { notifySubstitutions(result.replacements);
body = result.text;
notifySubstitutions(result.replacements);
}
} }
} }
} }
+13
View File
@@ -9,6 +9,19 @@
* because sites like claude.ai have strict CSP that blocks inline scripts. * because sites like claude.ai have strict CSP that blocks inline scripts.
*/ */
(function () { (function () {
// Claude Code (claude.ai/code) streams real file paths, shell commands, and
// tool-call traffic through the same HTTP surface as user messages. Any
// substitution there corrupts tool execution. We deliberately stay out of
// it entirely so the extension stays robust to API shape changes — the user
// handles redaction manually on this one app.
if (
location.hostname === 'claude.ai' &&
/^\/code(\/|$)/.test(location.pathname)
) {
window.__ssSkipHost = true;
return;
}
window.__ssOriginalFetch = window.fetch; window.__ssOriginalFetch = window.fetch;
window.__ssOriginalXHROpen = XMLHttpRequest.prototype.open; window.__ssOriginalXHROpen = XMLHttpRequest.prototype.open;
window.__ssOriginalXHRSend = XMLHttpRequest.prototype.send; window.__ssOriginalXHRSend = XMLHttpRequest.prototype.send;
+11
View File
@@ -15,6 +15,17 @@
if (window.__silentSendInjected) return; if (window.__silentSendInjected) return;
window.__silentSendInjected = true; window.__silentSendInjected = true;
// Skip Claude Code (web) entirely. Its tool-call traffic shares the HTTP
// surface with user messages; any selective walker becomes brittle the
// moment Anthropic changes a field name. Leaving the app untouched is the
// robust choice — the user handles redaction manually here.
if (
location.hostname === 'claude.ai' &&
/^\/code(\/|$)/.test(location.pathname)
) {
return;
}
// Merge active profiles into flat identity object // Merge active profiles into flat identity object
function mergeProfiles(data) { function mergeProfiles(data) {
const profiles = data?.profiles || []; const profiles = data?.profiles || [];