Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Can cleanup cause a JSON reviver to delete a property?

Yes in our fixture. The reviver deletes only the exact key secret. A marked sec + U+200B + ret survives before cleanup; after deletion the reviver omits that property.

Tested October 11, 2026 · v24.19.0 · 4 measured runs

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked secret key

Measured inputs and outputs

These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. We make no detector-score or statistical-watermark removal claim.

Before and after observations; full code points and strings are in the JSON download.
Fixture and modeInput string and code pointsOutput and cleaner statusObserved before / after
Marked secret key
direct string / keep / invisible true
"{\"sec​ret\":\"hidden\",\"name\":\"Ada\"}"
U+007B U+0022 U+0073 U+0065 U+0063 U+200B U+0072 U+0065 U+0074 U+0022 U+003A U+0022 U+0068 U+0069 U+0064 U+0064 U+0065 U+006E U+00 …
"{\"secret\":\"hidden\",\"name\":\"Ada\"}"
Removed 1 invisible character
{"visited":["sec​ret","name",""],"result":{"sec​ret":"hidden","name":"Ada"},"serialized":"{\"sec​ret\":\"hidden\",\"name\":\"Ada\"}"}
{"visited":["secret","name",""],"result":{"name":"Ada"},"serialized":"{\"name\":\"Ada\"}"}
Plain secret key
direct string / keep / invisible true
"{\"secret\":\"hidden\",\"name\":\"Ada\"}"
U+007B U+0022 U+0073 U+0065 U+0063 U+0072 U+0065 U+0074 U+0022 U+003A U+0022 U+0068 U+0069 U+0064 U+0064 U+0065 U+006E U+0022 U+00 …
"{\"secret\":\"hidden\",\"name\":\"Ada\"}"
No selected invisible characters found
{"visited":["secret","name",""],"result":{"name":"Ada"},"serialized":"{\"name\":\"Ada\"}"}
{"visited":["secret","name",""],"result":{"name":"Ada"},"serialized":"{\"name\":\"Ada\"}"}
Retained joiner
direct string / keep / invisible true
"{\"sec‍ret\":\"hidden\",\"name\":\"Ada\"}"
U+007B U+0022 U+0073 U+0065 U+0063 U+200D U+0072 U+0065 U+0074 U+0022 U+003A U+0022 U+0068 U+0069 U+0064 U+0064 U+0065 U+006E U+00 …
"{\"sec‍ret\":\"hidden\",\"name\":\"Ada\"}"
No selected invisible characters found
{"visited":["sec‍ret","name",""],"result":{"sec‍ret":"hidden","name":"Ada"},"serialized":"{\"sec‍ret\":\"hidden\",\"name\":\"Ada\"}"}
{"visited":["sec‍ret","name",""],"result":{"sec‍ret":"hidden","name":"Ada"},"serialized":"{\"sec‍ret\":\"hidden\",\"name\":\"Ada\"}"}
No matching field
direct string / keep / invisible true
"{\"name\":\"Ada\"}"
U+007B U+0022 U+006E U+0061 U+006D U+0065 U+0022 U+003A U+0022 U+0041 U+0064 U+0061 U+0022 U+007D
"{\"name\":\"Ada\"}"
No selected invisible characters found
{"visited":["name",""],"result":{"name":"Ada"},"serialized":"{\"name\":\"Ada\"}"}
{"visited":["name",""],"result":{"name":"Ada"},"serialized":"{\"name\":\"Ada\"}"}

A key edit activates the callback condition

The first JSON document has a marked secret key and a plain name key. Our reviver records each visited key and returns undefined only when the key is exactly secret. Before cleanup, the marked field remains in the parsed object. After cleanup joins its spelling, the reviver deletes that field and the serialized result contains name alone. The plain secret reference already loses the field at both stages. The retained U+200D key remains distinct and is kept. The name-only reference has no deletion trigger. The visited list includes the final empty-string root key, which helps expose the callback traversal rather than inferring it from output alone.

Parsing with a reviver adds an application rule

The reviver is our authored callback, not a built-in secret-field policy or behavior of the cleaner. JSON.parse invokes it on each exact document; the cleaner itself has no schema knowledge and does not call it. Our JSON collision guide measures duplicate names during parsing, whereas these fixtures have distinct names. The replacer-whitelist article controls serialization selection; this experiment removes a field during deserialization by returning undefined. No private value is present: hidden and Ada are synthetic labels. We test a small flat object, not nested reviver transformations, root replacement, prototype behavior or a real application’s filtering policy.

Review key-dependent transformations after edits

Retain the original document and the actual reviver used by the destination. If cleanup changes a key, compare the parsed object after that callback rather than validating syntax alone. Check which fields disappeared and whether those omissions reflect the intended schema. Do not rely on this demonstration as a privacy filter: the retained-joiner row shows how an exact-name rule can miss another spelling. The downloads reproduce one condition and four controls in the recorded runtime. They do not define a robust field-redaction policy, certify removal of confidential data or provide evidence about a statistical watermark. Targeted content edits still need a separate schema decision.

Reproduce this test

Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.

node reproduce.cjs

Reference and next check

ECMAScript JSON parsing and serialization provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.