Skip to content

v0.2.0 — architecture consolidation and hardening

Latest

Choose a tag to compare

@elkaix elkaix released this 14 Aug 00:36
· 2 commits to main since this release
f002485

Architecture consolidation release. Every entry point now routes through a small set of owned seams instead of re-implementing routing, subprocess execution, PNG traversal, and HTTP transport in each module. The externally visible payoff is in the hardening below; the layer capabilities are unchanged from v0.1.0.

Security

  • Argument injection in external command templates is fixed. v0.1.0 built commands as shlex.split(template.format(**values)) — substituting first, then splitting — so a path containing spaces or quotes could inject additional argv elements into --inpaint-command and --detect-command. Templates are now tokenized first and values substituted per-token, so a value can never become more than one argument.
  • External processes are bounded and cannot outlive their deadline. One end-to-end timeout, bounded stdout/stderr tails with explicit truncation reporting, and POSIX process-group termination so a descendant cannot survive a timeout or hold the output pipes open after the leader exits.
  • Layer B HTTP follows same-origin redirects only, so credentials are never forwarded to another host. Endpoints carrying inline credentials, a query, a fragment, or control characters are rejected before any connection; responses are size-bounded with Content-Length and Content-Type validation; transport errors never embed the endpoint, headers, or response body.

Fixed

  • ZIP-based containers (DOCX, ODT) are detected when the sniff prefix truncates the archive's central directory — detection falls back to a metadata-only read of the on-disk archive instead of reporting unknown.
  • PNG structure is validated strictly on inspection: per-chunk CRC, IHDR first and single and 13 bytes, IDAT present and consecutive, and an empty terminal IEND.

Changed

These alter existing command-line behavior:

  • Symlinked input sources are rejected with an error instead of being silently skipped.
  • --visible-backend simple|external or --inpaint-command without a localization source now errors instead of silently doing nothing.
  • Explicit file arguments are no longer filtered out by the output root. Passing a file that lives under -o <dir> now exits 2 with an aliasing error rather than skipping that file. Directory sources are unaffected.
  • Invalid-source diagnostics are combined into a single line, and no matching input files is now prefixed invalid input selection:. Exit codes are unchanged at 2.

Internal

Five new shared modules — asset_kind, clean_asset, external_command, layer_b_http, png_chunks — with clean_file, inspect_file, and demo.py routing through them. Rewrite configuration moved to immutable RewritePlan objects. Test suite grew from 14 to 21 files; 326 tests pass on Python 3.10, 3.12, and 3.14.

Install

Python 3.10+, standard library only. Networks, models, GPUs, and system binaries (exiftool, c2patool, pypdf) sit behind opt-in adapters.

git clone https://github.com/PyModel/watermark-remover.git
cd watermark-remover
python skills/remove-ai-marks/scripts/clean_text.py --help

Honesty contract: deterministic cleaners report exactly what they removed. Rewrite, inpainting, and detector-evasion methods are labeled best-effort. Nothing here certifies that a vendor detector will fail.

Full changelog: v0.1.0...v0.2.0