███╗ ██╗██╗ ██╗██╗ ██╗ ███╗ ███╗ █████╗ ██████╗ ██╗ ██╗
████╗ ██║██║ ██║██║ ██║ ████╗ ████║██╔══██╗██╔══██╗██║ ██╔╝
██╔██╗ ██║██║ ██║██║ ██║ ██╔████╔██║███████║██████╔╝█████╔╝
██║╚██╗██║██║ ██║██║ ██║ ██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗
██║ ╚████║╚██████╔╝███████╗███████╗██║ ╚═╝ ██║██║ ██║██║ ██║██║ ██╗
╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
LOCAL-FIRST · ZERO NETWORK · INVISIBLE UNICODE DETECTION · METADATA SCRUBBING · C2PA REMOVAL · RE-PARSE VERIFICATION
VGT NullMark 1.0.0-beta.2 is a functional beta. It has not received an independent cryptographic or security audit.
NullMark reports only deterministic, explicitly implemented, auditable rules. It never converts an unknown vendor state into a false verified clean claim. Statistical watermarks (e.g. SynthID) are explicitly declared as not-verifiable-without-vendor-detector.
Found a vulnerability or have an improvement? Open an issue or contact us.
NullMark is a hardened, local-first desktop application for detection, analysis and deterministic sanitization of invisible Unicode watermarks, tracker payloads, sensitive metadata and active provenance manifests (C2PA) from texts, images and documents.
Conventional privacy tools:
Cloud-based processing → your data leaves the device
Single-pass sanitization → no verification of result
No C2PA awareness → AI provenance manifests survive
No re-parse step → residual markers go undetected
False "100% clean" claims → statistical watermarks ignored
VGT NullMark:
100% local processing → zero network access, zero telemetry
3 sanitization modes → Safe · Strict · Maximum
9 file formats → PNG, JPEG, WebP, PDF, SVG, DOCX, XLSX, PPTX, ODT
C2PA manifest removal → caBX, APP11, RIFF, ZIP manifests
Re-parse verification → every result independently re-analyzed before export
Honest scope declaration → statistical signals declared, never falsely confirmed
Rust core, no unsafe code → #![forbid(unsafe_code)]
4 whitelisted IPC commands → no shell, no fs plugin, no HTTP plugin
graph TD
A[Unvertrauenswürdige Eingabedaten] --> B[React 19 WebView Sandbox]
B -->|Typed IPC / Bounded Base64| C[Tauri 2 IPC Boundary]
C -->|Max 4 Whitelisted Commands| D[Rust Sanitizer Engine]
D --> E[Format-spezifische Parser & Scrubbing]
E --> F[In-Memory Re-Parse & Verifikation]
F -->|Nur bei 0 Restbefunden| G[Export-Freigabe]
┌─────────────────────────────────────────────────────────┐
│ REACT 19 / TYPESCRIPT UI │
│ Text Workspace · Document Workspace · Split Diff │
│ DE / EN · Risk Color Coding · Codepoint Inspector │
├─────────────────────────────────────────────────────────┤
│ TAURI 2 IPC BOUNDARY │
│ 4 commands only · Bounded Base64 · No file paths │
│ withGlobalTauri: false · freezePrototype: true │
├─────────────────────────────────────────────────────────┤
│ RUST SANITIZER ENGINE │
│ #![forbid(unsafe_code)] · Edition 2021 │
│ │
│ ┌──────────┬──────────┬──────────┬────────────────┐ │
│ │ Unicode │ Binary │ PDF │ Office / ODT │ │
│ │ Engine │ Parser │ Engine │ ZIP Engine │ │
│ │ 3 modes │PNG/JPEG │ lopdf │ DOCX/XLSX │ │
│ │ │WebP/SVG │ │ PPTX/ODT │ │
│ └──────────┴──────────┴──────────┴────────────────┘ │
│ │
│ IN-MEMORY RE-PARSE & VERIFY │
│ Export blocked until 0 residual findings │
└─────────────────────────────────────────────────────────┘
analyze_text(text: String)
sanitize_text(text: String, mode: String)
analyze_binary(payload_base64: String)
sanitize_binary(payload_base64: String)
No native file paths cross the IPC boundary. Only bounded bytes.
| Plugin | Status |
|---|---|
plugin-fs (Filesystem) |
❌ Disabled |
plugin-shell (Shell execution) |
❌ Disabled |
plugin-http (HTTP networking) |
❌ Disabled |
plugin-opener / plugin-process |
❌ Disabled |
| Control | Status |
|---|---|
#![forbid(unsafe_code)] in Rust core |
✅ |
withGlobalTauri: false |
✅ |
freezePrototype: true |
✅ |
No dangerouslySetInnerHTML |
✅ |
No eval() / new Function() |
✅ |
Strict CSP — default-src 'none' |
✅ |
| No remote scripts, fonts, CDNs | ✅ |
| No runtime command execution in network-facing services | ✅ |
| SHA-256 input/output fingerprints | ✅ |
| Automatic post-sanitization re-parse | ✅ |
Source security gate (npm run security:check) |
✅ |
CSP:
default-src 'none'; connect-src ipc: http://ipc.localhost;
font-src 'self'; img-src 'self' data:; style-src 'self';
script-src 'self'; object-src 'none'; frame-src 'none'
Run the security gate at any time:
npm run security:checkNullMark processes 9 file formats with native magic-byte signature verification.
| Category | Format | Metadata Removed | C2PA |
|---|---|---|---|
| Text | TXT, MD, CSV, JSON, XML, YAML, HTML | Unicode payloads (plaintext extraction) | — |
| Raster Images | PNG | tEXt, zTXt, iTXt, eXIf, tIME chunks — strict CRC32 validation |
caBX chunks |
| Raster Images | JPEG | EXIF (0xE1), XMP, IPTC/Photoshop (0xED), App segments, Comments — entropy scan after SOS, EOI validation |
APP11 (0xEB) fragment chains |
| Raster Images | WebP | EXIF, XMP RIFF chunks — VP8X flag bitmask scrubbing, RIFF size correction |
C2PA RIFF chunk |
| Documents | /Info dict, /Metadata XMP (doc + page), annotation identity fields (/T, /M, /CreationDate, /NM), /JavaScript, /Launch, /OpenAction, /AA |
AFRelationship /C2PA_Manifest filespecs |
|
| Vector | SVG | <metadata>, XML comments, <script>, event attributes (onclick etc.), external URIs — Doctype discarded (XXE protection) |
c2pa:manifest |
| Office | DOCX | docProps/core.xml, custom.xml, app.xml, w:author, w:date, w:initials — Unicode scrubbing in word/document.xml |
META-INF/content_credential.c2pa |
| Office | XLSX | docProps/, xl/comments*.xml, xl/persons/person*.xml — Unicode scrubbing in xl/sharedStrings.xml |
META-INF/content_credential.c2pa |
| Office | PPTX | docProps/, ppt/commentAuthors.xml, ppt/authors.xml — Unicode scrubbing in all ppt/slides/slide*.xml |
META-INF/content_credential.c2pa |
| OpenDocument | ODT | meta.xml, manifest.rdf — canonical mimetype as uncompressed entry 0 verified |
META-INF/content_credential.c2pa |
Input Codepoints
│
├─► Safe → Zero-width spaces, BOM, Tag chars, Soft hyphens
│ (context-sensitive chars reported but kept)
│
├─► Strict → + Bidi controls/overrides/isolates, ZWJ/ZWNJ,
│ Invisible math operators, Unusual spaces → ASCII space
│
└─► Maximum → + Private-use area (PUA), Curly quotes → straight,
Dash variants → hyphen, Ellipsis → ...,
Fullwidth ASCII → standard ASCII
| Codepoint | Name | Mode | Safe | Strict | Max |
|---|---|---|---|---|---|
U+200B |
Zero Width Space | Zero-width / High | 🗑️ | 🗑️ | 🗑️ |
U+FEFF |
BOM / Zero Width No-Break | Zero-width / High | 🗑️ | 🗑️ | 🗑️ |
U+2060 |
Word Joiner | Zero-width / Medium | 🗑️ | 🗑️ | 🗑️ |
U+00AD |
Soft Hyphen | Invisible format / Medium | 🗑️ | 🗑️ | 🗑️ |
U+E0000..E007F |
Unicode Tag Characters | Tag / High | 🗑️ | 🗑️ | 🗑️ |
U+200C, U+200D |
ZWNJ / ZWJ | Zero-width / Medium | ✅ Keep | 🗑️ | 🗑️ |
U+202A..202E |
Bidi Embeddings / Overrides | Bidi / High | ✅ Keep | 🗑️ | 🗑️ |
U+2061..2064 |
Invisible Math Operators | Invisible / Medium | ✅ Keep | 🗑️ | 🗑️ |
U+00A0, U+2000..200A |
Non-Standard Spaces | Suspicious / Info | ✅ Keep | 🔄 → |
🔄 → |
U+E000..F8FF |
Private Use Area (PUA) | PUA / High | ✅ Keep | ✅ Keep | 🗑️ |
U+2018..201D |
Typographic Quotes | Surface / Info | ✅ Keep | ✅ Keep | 🔄 → ' " |
U+2010..2015, U+2212 |
Dash variants / Minus | Surface / Info | ✅ Keep | ✅ Keep | 🔄 → - |
U+FF01..FF5E |
Fullwidth ASCII | Compat / Low | ✅ Keep | ✅ Keep | 🔄 → ASCII |
After every sanitization pass, NullMark re-parses the result entirely in memory.
Sanitize(input)
│
▼
In-memory re-parse
│
├─ 0 residual findings → Export unlocked ✅
└─ Any finding remains → Export blocked ❌
Canonical idempotence: sanitize(sanitize(x)) == sanitize(x) with 0 residual findings.
Every operation produces:
- SHA-256 fingerprint of input
- SHA-256 fingerprint of sanitized output
- Change ledger (max. 4,096 recorded operations)
| Vendor / Method | NullMark Coverage |
|---|---|
| Explicit Unicode payloads | ✅ Detected and removed (all modes) |
| C2PA provenance manifests | ✅ Removed across all 9 formats |
| Document & image metadata | ✅ Removed |
| Google SynthID Text | |
| OpenAI text watermarks | |
| Anthropic / Claude |
NullMark never outputs a false
verified cleanclaim for statistical watermarks. Unknown vendor state is declarednot-verifiable-without-vendor-detector.
| Parameter | Limit | Protection |
|---|---|---|
| Max text input | 8 MiB | UI freeze / string overflow prevention |
| Max file size (single) | 32 MiB | Bounded IPC memory |
| Max batch volume | 128 MiB / 50 files | Host memory exhaustion |
| ZIP decompression ceiling | 128 MiB expanded / 4,096 entries | Zip bomb / recursion protection |
| PDF objects / stream buffer | 100,000 objects / 128 MiB | PDF object flood protection |
| Finding aggregation | Max 8 positions per codepoint | O(1) memory on marker-flooded files |
| Diff change ledger | Max 4,096 operations | Render pipeline protection |
| Workspace | Purpose |
|---|---|
| Text & Unicode | Direct text input / text files — Split Diff viewer, per-step change log, 1-click mode escalation |
| Documents & Media | Batch processing — up to 50 files, sequential verification, secure download |
Internationalization: German and English (stored in localStorage).
Visual inspection: Risk color coding (High · Medium · Low · Info), codepoint display as U+XXXX, match counter and position display.
| Component | Technology | Version |
|---|---|---|
| Native Core | Rust / Tauri 2 | Edition 2021, MSRV 1.88+ · Tauri v2.11.5 |
| UI | React, TypeScript, Vite | React 19 · TS 5.8 · Vite 8 |
| XML / Streaming Parser | quick-xml |
v0.41.0 |
| PDF Engine | lopdf (zero-default-features) |
v0.44.0 |
| ZIP Engine | zip (deflate) |
v8.6.0 |
| Cryptographic Hashes | sha2 (SHA-256) |
v0.10.9 |
| Checksums | crc32fast |
v1.5.0 |
| Platform | Requirement |
|---|---|
| Windows | Windows 10 / 11 x64 — Microsoft WebView2 Runtime, VC++ Redistributable |
| macOS | macOS 12+ — Apple Silicon or Intel x64 |
| Linux | x86_64 / aarch64 — WebKitGTK 4.1+ |
| Rust | 1.95 or newer with Cargo |
| Node.js | 20.19+ or 22.12+ (required by Vite 8) |
| Disk | ~3 GiB for first build and dependencies |
START_WINDOWS.cmdOr manually:
npm ci --ignore-scripts
npm run security:check
npm run tauri:devBuild installers (NSIS .exe + WiX .msi):
BUILD_WINDOWS.cmdArtifacts land in src-tauri/target/release/bundle/.
npm install
npm run security:check
npm run tauri:devBuild:
npm run tauri:buildsrc-tauri/src/engine.rs has no external dependencies — test the sanitizer core standalone:
rustc --edition 2021 --test src-tauri/src/engine.rs -o nullmark-engine-tests
./nullmark-engine-testsOn Windows: TEST_ENGINE.cmd
src/ React/TypeScript renderer
App.tsx Main UI
lib/backend.ts Typed IPC boundary
src-tauri/
src/engine.rs Engine boundary and invariants
src/engine/ Rules, model and sanitizer policies
src-tauri/src/binary/ PNG/JPEG/WebP/PDF/SVG/Office/ODF parsers
src/lib.rs Bounded Tauri command layer + verification
permissions/ Explicit custom-command permissions
capabilities/ Single-window least-privilege capability
tauri.conf.json CSP and desktop configuration
scripts/security-check.mjs Source/config security gate
docs/ Architecture and threat model
ROADMAP.md Versioned future work and acceptance gates
.github/ CI, Dependabot and PR policy
| Document | Link |
|---|---|
| Technical Data Sheet | docs/TECHNICAL_DATASHEET.md |
| Binary Format Specification | docs/FORMAT_SPECIFICATION.md |
| Threat Model | docs/THREAT_MODEL.md |
| Security Audit Report | docs/SECURITY_AUDIT.md |
| Watermark Research | docs/WATERMARK_RESEARCH.md |
| Reproducibility Guide | docs/REPRODUCIBILITY.md |
| Benchmark Results | docs/BENCHMARK_RESULTS.md |
| Roadmap | ROADMAP.md |
- Regular PDF attachments preserved — JavaScript/launch/automatic actions removed, unrelated embedded files not silently deleted
- Office transformations target metadata and supported authorship fields — macros and arbitrary embedded objects not processed
- Statistical AI watermarks (SynthID etc.) not provably removable — declared honestly, never falsely confirmed
- Container metadata reveals: original filename, size, creation time, suite, algorithms, public-key hashes, offline factor presence
| Feature | Status |
|---|---|
| Exact split diff and bounded change ledger | 🔜 Beta 2 |
| XLSX / PPTX / SVG support | ✅ Done (beta.2) |
| Deeper PDF object inspection | 🔜 Beta 2 |
| German / English interface catalogs | ✅ Done (beta.2) |
| Restrained desktop UI with project-owned SVG identity | 🔜 Beta 2 |
| Tool | Type | Purpose |
|---|---|---|
| 🧹 VGT NullMark | Privacy Sanitizer | Watermark detection and metadata scrubbing — you are here |
| 🧠 VGT AETHEL | Sovereign AI OS | Local AI intelligence OS with operator governance |
| 🛡️ VGT GeDefense | Linux Security Fabric | Kernel-near defense, XDR, encrypted evidence |
| 🔑 VGT Infinity | PQ File Encryption | Post-quantum file vault |
| ⚔️ VGT Sentinel | WAF / IDS | Zero-Trust WordPress WAF |
| ⚡ VGT Auto-Punisher | IDS | L4+L7 Hybrid IDS |
| 🌐 GaiaCom | Communication | Post-quantum federated E2EE platform |
| 📊 VGT Dattrack | Analytics | Sovereign local analytics |
| Method | Address |
|---|---|
| PayPal | paypal.me/dergoldenelotus |
| Bitcoin | bc1q3ue5gq822tddmkdrek79adlkm36fatat3lz0dm |
| ETH / USDT (ERC-20) | 0xD37DEfb09e07bD775EaaE9ccDaFE3a5b2348Fe85 |
AGPLv3 · © 2026 VisionGaia Technology · Cologne, Germany
Enterprise deployments, TIER-0 audits (VGT SafetySys™) and commercial support: visiongaiatechnology.de