{"slug": "ai-watermark-removers-can-t-verify-themselves-i-built-the-tool-that-can", "title": "AI Watermark removers can't verify themselves I built the tool that can", "summary": "Developer Neeeophytee released a seven-skill agent pack, 'ai-watermarks-reality-check,' that audits AI provenance evidence such as C2PA metadata and text watermarks without removing them, reporting statuses like PRESENT, VALID, and ABSENT. The pack, compatible with Claude Code, Codex, Gemini CLI, and MCP clients, addresses gaps in Anthropic's newly launched Claude watermarking, which lacks a public detector and detailed specification, and notes that common publishing actions can strip metadata. It requires Node.js 22.20+ for installation and Python 3.9+ for the skills.", "body_md": "Seven portable agent skills for checking what AI provenance evidence exists, whether it verifies, what a publishing pipeline destroys, and what must still be disclosed.\n\nThe pack deliberately does **not** remove watermarks or Content Credentials. It makes provenance observable without pretending that one signal can prove authorship.\n\nAnthropic says newly launched Claude models are gaining imperceptible text watermarks and supported image files can carry signed C2PA metadata. Its public detector and detailed text-watermark specification are not yet available. Meanwhile, common publishing actions such as resizing, screenshots, conversion, and social uploads can remove file metadata.\n\nThis pack gives teams a reproducible workflow:\n\n```\ninspect → verify → transform-test → privacy-audit → disclosure-check\n```\n\nThe signed original reports `PRESENT`\n\n, `VALID`\n\n, and `PRESERVED_VALID`\n\n. The downloaded and post-tool copies report `ABSENT`\n\n, `NOT_VERIFIED`\n\n, and `LOST_OR_UNAVAILABLE`\n\n. This comparison covers the C2PA provenance layer. It does not test proprietary pixel watermarks or keyed text watermarks.\n\n[Watch the 34-second landscape demo](/Neeeophytee/ai-watermarks-reality-check/blob/main/media/watermark-two-sides-34s-1080p.mp4) or [open the vertical social cut](/Neeeophytee/ai-watermarks-reality-check/blob/main/media/watermark-two-sides-vertical.mp4).\n\nThe skills work with [Claude Code](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview), [Codex](https://learn.chatgpt.com/docs/build-skills), [Gemini CLI](https://codelabs.developers.google.com/gemini-cli/how-to-create-agent-skills-for-gemini-cli), and other Agent Skills-compatible tools.\n\nUse them to audit supported evidence in files and text from Claude, ChatGPT, Gemini, open models, image generators, or any other source. Coverage follows the evidence type rather than a vendor name. C2PA, metadata, disclosure records, pipeline survival, and hidden Unicode channels can be inspected wherever they appear.\n\nThere is no universal detector for every proprietary or secret-key watermark. When an official detector, configuration, or key is unavailable, the result remains `UNVERIFIABLE`\n\n, `UNSUPPORTED`\n\n, or `UNKNOWN`\n\n.\n\n| Skill | Use it to |\n|---|---|\n`audit-provenance` |\nStart here. Answer the five questions for one asset in one pass |\n`inspect-content-provenance` |\nLocate C2PA structure and hidden text channels without overclaiming |\n`verify-content-credentials` |\nValidate a C2PA manifest and report integrity separately from signer trust |\n`map-provenance-survival` |\nBatch edited copies and create a shareable C2PA survival report |\n`audit-metadata-privacy` |\nInventory GPS, author, device, software, and date metadata without changing the source |\n`check-ai-transparency` |\nCheck whether evidence and human-readable disclosure are ready for review |\n`detect-text-watermark` |\nRun every available text-provenance detector and report what cannot be checked |\n\n```\nnpx skills add Neeeophytee/ai-watermarks-reality-check\n```\n\nThe current `skills`\n\ninstaller requires Node.js 22.20 or newer. The installed\nskills themselves require only Python 3.9 or newer.\n\nOr copy one directory from `skills/`\n\ninto your agent's skill directory. Each skill folder is self-contained: the shared parsing core is vendored into every `scripts/`\n\ndirectory, so a single folder works on its own.\n\nFor MCP-compatible clients, all seven analyzers can also be exposed as local stdio tools:\n\n```\n{\n  \"mcpServers\": {\n    \"provenance\": {\n      \"command\": \"python3\",\n      \"args\": [\"/absolute/path/to/mcp/server.py\"]\n    }\n  }\n}\n```\n\nNo hosted service is required. The MCP client starts `python3 mcp/server.py`\n\non the user's machine and exchanges JSON-RPC messages with it through standard input and output. The server dispatches calls to the same read-only analyzers, reads local files, and returns structured results. Cryptographic verification uses the user's local `c2patool`\n\ninstallation. Remote-manifest access stays disabled unless the caller explicitly enables it.\n\nThe server supports two protocol eras. It implements the current stateless revision\n`2026-07-28`\n\nand still answers the legacy `initialize`\n\nhandshake used by\n`2025-11-25`\n\nand earlier clients.\n\n| Behaviour | Support |\n|---|---|\n`server/discover` (mandatory in 2026-07-28) |\nImplemented |\nPer-request `_meta[\"io.modelcontextprotocol/protocolVersion\"]` |\nHonoured |\n`UnsupportedProtocolVersionError` (`-32022` ) with `supported` /`requested` |\nReturned |\nLegacy `initialize` negotiation |\nRetained |\n\nEvery script uses the Python standard library and requires Python 3.9 or newer. Cryptographic C2PA verification additionally requires the official `c2patool`\n\n**0.20.0 or newer**.\n\nStart with the front door, which answers all five questions in one pass:\n\n```\npython3 skills/audit-provenance/scripts/audit_provenance.py image.png \\\n  --c2patool /path/to/c2patool \\\n  --trust-anchors /path/to/policy.pem\n```\n\nThe individual analyzers remain directly available:\n\n```\npython3 skills/inspect-content-provenance/scripts/inspect_file.py image.png\n\npython3 skills/verify-content-credentials/scripts/verify_c2pa.py image.png\n\npython3 skills/map-provenance-survival/scripts/map_survival.py \\\n  --original original.png \\\n  --derivatives-dir transformed-copies/ \\\n  --derivative social-download:platform-roundtrip=downloaded.jpg \\\n  --c2patool /path/to/c2patool \\\n  --report survival-report.html\n\npython3 skills/audit-metadata-privacy/scripts/audit_metadata.py image.png\n\npython3 skills/check-ai-transparency/scripts/check_transparency.py \\\n  examples/transparency-record.json\n\npython3 skills/detect-text-watermark/scripts/detect_text_watermark.py draft.md\n```\n\nScripts emit JSON to stdout and diagnostics to stderr. Remote-manifest fetching is disabled by default and requires `--allow-network`\n\n. A missing verifier, an unsupported verifier version, an inaccessible remote manifest, or an unpublished detector produces an explicit unknown state rather than a pass.\n\nSurvival reports refuse to overwrite an existing file. They show only filenames\nby default, while the machine-readable JSON retains the full reproducibility\nrecord. Use `--include-paths`\n\nonly when the report will stay private. A generated\nreport never claims that a proprietary watermark detector ran.\n\nSee the [generated example](/Neeeophytee/ai-watermarks-reality-check/blob/main/examples/provenance-survival-example.md) and the\n[community benchmark template](/Neeeophytee/ai-watermarks-reality-check/blob/main/examples/platform-benchmark-template.md) before\npublishing a result.\n\nThe provenance survival skill can now audit a directory of edited or downloaded copies in one run and create a self-contained Markdown or HTML report. This is useful for testing a CMS, editor, CDN, social network, or watermark-removal workflow without changing any of the files being measured.\n\n`--derivatives-dir`\n\nrecursively adds visible, non-symlink files with stable labels.`--report survival-report.html`\n\ncreates a portable, script-free report.- Local paths and the original command are redacted from reports by default.\n- The JSON result remains on stdout and continues to validate against the published schema.\n- Every report states its boundary: this workflow measures C2PA survival, not proprietary pixel or keyed text watermarks.\n\n| Dimension | States | Meaning |\n|---|---|---|\n| Manifest presence | `PRESENT` , `POSSIBLE` , `ABSENT` , `UNKNOWN` |\nWhether a C2PA manifest is observed |\n| Integrity | `VALID` , `INVALID` , `NOT_VERIFIED` , `UNKNOWN` |\nWhether a conforming verifier validated the claim |\n| Signer trust | `TRUSTED` , `UNTRUSTED` , `NOT_CHECKED` , `UNKNOWN` |\nWhether the signing chain reaches the selected trust list |\n| Text watermark | `UNVERIFIABLE` |\nAnthropic has not published its detector as of 2026-08-13 |\n\n`POSSIBLE`\n\nmeans a structural carrier, sidecar, or format-appropriate malformed\nhint was located; inspect the marker confidence before acting. Only\n`STRUCTURAL`\n\nmeans the location and carrier form match the specification.\n`PRESENT`\n\nis only ever returned by a conforming verifier. `ABSENT`\n\nis emitted\nonly for a completed bounded scan of a supported container or an explicit live\nverifier \"no claim\" result. `VALID`\n\nnever automatically means `TRUSTED`\n\n.\nAbsence of a mark never proves that content was human-made.\n\nA literal mention of \"C2PA\" in readable text is recorded in `c2pa_mentions`\n\nand is never evidence.\n\nDetection is structural, at the locations the C2PA 2.4 specification defines.\n\n| Container | Carrier | `ABSENT` possible? |\n|---|---|---|\n| PNG | `caBX` chunk |\nyes |\n| JPEG | APP11 JUMBF segment | yes |\n| WebP | RIFF `C2PA` chunk |\nyes |\n| TIFF/DNG | private tag `0xCD41` , type 7, in the last main IFD |\nyes |\n| GIF | `C2PA_GIF` application extension |\nyes |\n| HTML | head `<script type=\"application/c2pa\">` containing Base64; `<link rel=\"c2pa-manifest\">` |\nyes |\n| Text | A.8 variation-selector wrapper; A.9 block in host comments or front matter | yes |\nAssociated File `/AFRelationship /C2PA_Manifest` |\nno |\n|\n| BMFF (MP4/HEIC/AVIF) | `uuid` box with the C2PA UUID, or `jumb` |\nno |\n| OOXML / ODF / ZIP | packaged manifest entry | no |\n| Any | detached `.c2pa` sidecar |\nnot format-specific |\n\n**Fail closed.** The right-hand column is the important one. For formats marked\n**no**, this build inspects the carriers listed but cannot walk the container\nexhaustively because of compressed PDF object streams and fragmented BMFF.\nFinding nothing therefore yields `UNKNOWN`\n\nwith a stated reason, never `ABSENT`\n\n.\n\n| Confidence | Meaning |\n|---|---|\n`STRUCTURAL` |\nFound at a spec-defined location |\n`MODERATE` |\nA format-appropriate key or XML namespace reference |\n`SIDECAR` |\nA detached `.c2pa` manifest beside the asset |\n\nA bounded read can never produce a conclusive clean result. `detect-text-watermark`\n\nstreams the whole file where practical and always reports:\n\n| Field | Meaning |\n|---|---|\n`file_sha256` |\nSHA-256 over every byte on disk, always |\n`scanned_sha256` |\nSHA-256 over the region actually analysed |\n`file_bytes` / `scanned_bytes` |\nsizes of each |\n`scan_complete` |\nwhether the two coincide |\n\nIf `scan_complete`\n\nis false, the status is `INCONCLUSIVE`\n\nwith a reason and exit\n`2`\n\n, even when nothing suspicious was seen in the part that was read. A prefix\nhash is never presented as the file hash.\n\nEvery entrypoint uses the same convention, so an orchestrating agent can apply one rule:\n\n| Code | Meaning |\n|---|---|\n`0` |\nConclusive and good: verified valid, no required gaps, no risk found |\n`1` |\nConclusive and bad: invalid, required gaps, HIGH privacy risk, provenance lost, covert channel found |\n`2` |\nInconclusive: unknown state, missing or unsupported verifier, unsupported container |\n\nMachine-readable JSON Schemas for all seven tools live in [ schemas/](/Neeeophytee/ai-watermarks-reality-check/blob/main/schemas). Every branch of every tool returns the same top-level field set, and CI validates real outputs against these schemas. The schemas also encode the evidence invariants: a document claiming\n\n`integrity: VALID`\n\nwith `manifest_presence: ABSENT`\n\nfails validation.`detect-text-watermark`\n\nruns a detector registry and reports honestly per adapter:\n\n| Adapter | Runs? | State when it cannot run |\n|---|---|---|\n`anthropic-official` |\nnever | `UNVERIFIABLE` : no public detector or specification exists |\n`synthid-text` |\nnever in this build | `NOT_CONFIGURED` without keys, `UNSUPPORTED` with them |\n`kgw-research` |\nnever in this build | `NOT_CONFIGURED` without a key, `UNSUPPORTED` with one |\n`unicode-covert-channel` |\nyes |\nnot applicable |\n`c2pa-text-manifest` |\nyes |\nnot applicable |\n\nThe state vocabulary distinguishes five situations, so a caller can never mistake \"did not look\" for \"looked and found nothing\":\n\n| State | Meaning |\n|---|---|\n`DETECTED` |\nThe detector ran and found the signal |\n`NOT_DETECTED` |\nThe detector ran and did not find it |\n`NOT_CONFIGURED` |\nRequired keys or config were not supplied; nothing was analysed |\n`UNSUPPORTED` |\nConfigured, but this build ships no scorer; nothing was analysed |\n`UNVERIFIABLE` |\nThe scheme cannot be checked by a third party at all |\n`FAILED` |\nThe detector errored |\n\n**Only DETECTED and NOT_DETECTED mean a detector ran**, and only those\ncontribute to the top-level status.\n\n`SynthID`\n\nand `KGW`\n\naccept configuration but\nthis build performs **no scoring** for either; they are unavailable integrations, not silent passes.\n\nKeyed model-level watermarks bias token sampling with a secret key; detection requires that key. A third party cannot check them, and this pack says so rather than guessing.\n\nA standards-compliant C2PA text manifest (2.4 §A.8) is itself a run of variation\nselectors after a ZWNBSP. It is recognised as provenance and **excluded** from\ncovert-channel findings rather than reported as suspicious.\n\nThe covert-channel scan finds Unicode tag characters (ASCII smuggling), bidi overrides, variation selectors, zero-width characters, exotic spaces, and mixed-script homoglyphs. These are **text-integrity and prompt-injection signals**, not watermark evidence: they identify no model or vendor.\n\n**Deliberate non-goal:** statistical or stylometric AI-text classifiers are not implemented and will not be added. Their false-positive rates make them unsafe for accusing a person of AI authorship.\n\n- No watermark removal, evasion, or provenance stripping.\n- No source files are modified.\n- No authorship verdicts.\n- No legal-compliance claims.\n- No statistical AI-text detection.\n- Reports avoid printing sensitive metadata values by default.\n\nSee [SOURCES.md](/Neeeophytee/ai-watermarks-reality-check/blob/main/SOURCES.md). Product behavior is volatile; the source review date is recorded there.\n\n[GNU Affero General Public License v3.0](/Neeeophytee/ai-watermarks-reality-check/blob/main/LICENSE) (`AGPL-3.0-only`\n\n)", "url": "https://wpnews.pro/news/ai-watermark-removers-can-t-verify-themselves-i-built-the-tool-that-can", "canonical_source": "https://github.com/Neeeophytee/ai-watermarks-reality-check", "published_at": "2026-08-14 14:32:37+00:00", "updated_at": "2026-08-14 14:43:39.886768+00:00", "lang": "en", "topics": ["ai-tools", "ai-ethics", "ai-policy", "developer-tools"], "entities": ["Neeeophytee", "Anthropic", "Claude", "C2PA", "Claude Code", "Codex", "Gemini CLI", "MCP"], "alternates": {"html": "https://wpnews.pro/news/ai-watermark-removers-can-t-verify-themselves-i-built-the-tool-that-can", "markdown": "https://wpnews.pro/news/ai-watermark-removers-can-t-verify-themselves-i-built-the-tool-that-can.md", "text": "https://wpnews.pro/news/ai-watermark-removers-can-t-verify-themselves-i-built-the-tool-that-can.txt", "jsonld": "https://wpnews.pro/news/ai-watermark-removers-can-t-verify-themselves-i-built-the-tool-that-can.jsonld"}}