{"id":51417762,"url":"https://github.com/didrod205/shadowbuster","last_synced_at":"2026-07-04T21:30:37.904Z","repository":{"id":368312971,"uuid":"1284555400","full_name":"didrod205/shadowbuster","owner":"didrod205","description":"That black redaction bar isn't redaction — it's a sticker. Drop a PDF, Excel, Word, PowerPoint or screenshot and recover what was hidden but never removed — 100% in your browser, nothing uploaded. Zero dependencies.","archived":false,"fork":false,"pushed_at":"2026-06-30T02:11:59.000Z","size":106,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T03:21:50.324Z","etag":null,"topics":["acropalypse","in-browser","metadata","ooxml","pdf","privacy","redaction","security","zero-dependency"],"latest_commit_sha":null,"homepage":"https://didrod205.github.io/shadowbuster/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/didrod205.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-30T01:36:59.000Z","updated_at":"2026-06-30T02:12:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/didrod205/shadowbuster","commit_stats":null,"previous_names":["didrod205/shadowbuster"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/didrod205/shadowbuster","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didrod205%2Fshadowbuster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didrod205%2Fshadowbuster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didrod205%2Fshadowbuster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didrod205%2Fshadowbuster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/didrod205","download_url":"https://codeload.github.com/didrod205/shadowbuster/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didrod205%2Fshadowbuster/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35136712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acropalypse","in-browser","metadata","ooxml","pdf","privacy","redaction","security","zero-dependency"],"created_at":"2026-07-04T21:30:37.065Z","updated_at":"2026-07-04T21:30:37.885Z","avatar_url":"https://github.com/didrod205.png","language":"TypeScript","funding_links":["https://github.com/sponsors/didrod205"],"categories":[],"sub_categories":[],"readme":"# ShadowBuster 🕶️\n\n**That black redaction bar isn't redaction — it's a sticker.** Drop a PDF, Excel, Word, PowerPoint, or screenshot and ShadowBuster surfaces the parts that were hidden but *never actually removed*: text under black boxes, very-hidden spreadsheet tabs, deleted tracked changes, the uncropped original of a cropped image, white-on-white text. **100% in your browser — nothing is uploaded.**\n\n\u003e Stop trusting black rectangles.\n\n### 🌐 [**Drop a file and watch the \"deleted\" parts come back →**](https://didrod205.github.io/shadowbuster/)\n\n```bash\n# scan a whole folder of \"redacted\" documents from your terminal:\nnpx shadowbuster ./documents\n```\n\n```\n■ redacted-report.pdf  (pdf, 1 KB)\n  ■ Text hidden under a redaction box — page 1\n    A filled rectangle is painted over this text, but the text itself is\n    still in the page's content stream — selectable, copyable, recovered here.\n    ┌ recovered:\n    Jane Doe 123-45-6789 $240,000\n\n————————————————————————————————————————————————\nScanned 1 file(s) — 1 still carries hidden content, 1 with text behind a redaction.\n```\n\n## Why\n\n\"Redacting\" a document by **drawing a black box over a name**, **hiding a worksheet**, **cropping an image**, or **deleting a sentence with Track Changes on** removes *nothing*. The original is still sitting in the bytes you email out — one copy-paste, one right-click → Unhide, or one \"Accept all changes\" away from anyone who receives it. This has leaked court filings, settlement figures, troop names, and executive comp over and over.\n\nShadowBuster is the **before-you-hit-send** check. Drop the file; it shows you exactly what's recoverable, so you can really remove it — and it does this **entirely in your browser**, because a tool for finding secrets in your documents should never upload your documents.\n\n## What it finds\n\n| File | What's still in there |\n| --- | --- |\n| **PDF** | Text painted under a filled \"redaction\" rectangle, and text drawn in the same color as the box on top of it (invisible-text trick) |\n| **Excel** (`.xlsx`) | Hidden and **very-hidden** worksheets (+ their cells), hidden columns/rows with data, cached pivot-table source rows |\n| **Word** (`.docx`) | Tracked-change **deletions** that were never accepted, hidden (vanished) text, review comments |\n| **PowerPoint** (`.pptx`) | Speaker notes, and the **full uncropped original** of any image the slide only shows a crop of |\n| **PNG / JPEG** | A whole second image (or data) **appended after the file's end marker** — the \"cropped/overwritten screenshot still has the original\" failure |\n| **Office, all** | Author / `lastModifiedBy` / company metadata, and every embedded full-resolution image |\n\n## How it works\n\n```\ndrag a file in\n   └─ sniff magic bytes ─┬─ %PDF  → brute-force object scan → FlateDecode (built-in DecompressionStream)\n                         │          → tokenize content stream, track matrices + fill rectangles\n                         │          → decode glyphs via the font's /ToUnicode CMap\n                         │          → text whose anchor sits under a filled box = recovered\n                         ├─ PK..  → ZIP central directory → inflate XML → read OOXML structure\n                         └─ PNG/JPEG → walk to the logical end marker → recover trailing bytes\n```\n\n- **Zero dependencies.** The whole engine is hand-written TypeScript using only platform APIs (`DecompressionStream`, `DataView`, `TextDecoder`). No `pdf.js`, no office libraries, nothing to audit but the source. That's the point — you can read every line before you trust it with a sensitive file.\n- **Nothing leaves your machine.** The browser version reads the dropped file with `FileReader` and parses it locally; there is no upload, no backend, no network call. The CLI reads from disk. Same pure core (`src/`) in both.\n- **No false guesses.** If a PDF uses embedded subset fonts with no `/ToUnicode` map, the text under a box can't be reliably decoded — ShadowBuster says so rather than printing garbage.\n\n## Honesty \u0026 scope\n\nShadowBuster reveals what a document **already exposes to anyone who opens it** with the right click or a text selection. It is an **awareness tool, not an exploit**: it reads public structure of a file you already have. It does not break encryption, defeat *proper* redaction (where the content was actually deleted and the file flattened), or recover pixels that were genuinely discarded.\n\nThe v1 PDF detector targets the most common and most damaging failure — **real text sitting under a filled rectangle**. Exotic cases (composite fonts with no `/ToUnicode`, vector-outlined text, scanned images) are reported as undecodable rather than guessed. Use it on **your own** files before you share them.\n\n## To *actually* redact\n\n- **PDF:** use a real redaction tool that deletes the underlying text, or flatten/print the page to an image.\n- **Excel:** delete the hidden/very-hidden sheets and clear hidden rows/columns — don't just hide them.\n- **Word:** accept all tracked changes, then *Inspect Document → Remove* comments and hidden text.\n- **PowerPoint:** re-crop then compress images (this discards cropped pixels); delete speaker notes.\n- **Images:** re-export to a fresh file; never overwrite a larger image in place.\n\n## Library\n\n```ts\nimport { scanBytes } from \"shadowbuster\";\n\nconst result = await scanBytes(\"report.pdf\", new Uint8Array(buffer));\nfor (const f of result.findings) {\n  console.log(f.severity, f.title, f.location);\n  if (f.recovered?.type === \"text\") console.log(f.recovered.text);\n}\n```\n\n`scanBytes` is pure and isomorphic — give it bytes, get back typed `findings`. Works in the browser, in Node, in a worker.\n\n## CLI\n\n```bash\nnpm i -g shadowbuster          # then:  shadowbuster ./documents\n# or zero-install:\nnpx shadowbuster report.pdf\nnpx shadowbuster ./folder --json\n```\n\nExits non-zero when it finds text/data behind a redaction, so you can wire it into a pre-send or CI check. `unredact` is a shorter alias.\n\n## Contributing\n\nNew detector ideas welcome — DOCX `customXml` leftovers, EXIF/GPS in embedded images, PDF annotation/form-field values, ODF formats. See [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nMIT © [didrod205](https://github.com/didrod205)\n\n---\n\n\u003csub\u003eIt was never redacted. It was just hidden. ShadowBuster shows you the difference — locally, before you send.\u003c/sub\u003e\n\n## 💖 Sponsor\n\nFind this useful? [**Sponsor on GitHub**](https://github.com/sponsors/didrod205) — it keeps these tools maintained.\n\n[![Sponsor](https://img.shields.io/badge/Sponsor-GitHub-db61a2?logo=githubsponsors\u0026logoColor=white)](https://github.com/sponsors/didrod205)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdidrod205%2Fshadowbuster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdidrod205%2Fshadowbuster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdidrod205%2Fshadowbuster/lists"}