Try it in your browser: the real engine compiled to WebAssembly, so what you paste never leaves the page.
Mask secrets and personal data in logs so they can be shared safely (bug reports, tickets, chat).
some-command | logscrub > clean.log
logscrub app.log # files work too
logscrub --check app.log # CI gate: exit 1 if anything would be masked
logscrub --report app.log # counts per detector, never the matched text
logscrub -r -i logs/ # clean a whole directory in place (add --backup-suffix .bak to keep originals)
logscrub app.log.gz # gzip input is read transparently
logscrub --mode pseudonym app.log # stable tags for emails and IPs: the log stays debuggable
logscrub --mode pseudonym --map-file map.json app.log > out.log # ... and `logscrub restore --map-file map.json out.log` reverses it
logscrub --config logscrub.toml app.log # allow-list, custom rules, enable/disable detectors
logscrub serve # local web UI: paste or drop a log, see what would be masked
logscrub --check --report --report-format sarif app.log > logscrub.sarif # for CI and code scanning$ printf 'GET /cb?access_token=abc123\nconnect postgres://app:s3cret@db/x\n' | logscrub
GET /cb?access_token=[REDACTED:kv-secret]
connect postgres://[REDACTED:url-credentials]@db/x
Secrets: AWS access and secret keys, GitHub / GitLab / Slack / Stripe tokens, JWTs, PEM private keys (including multi-line blocks), Authorization headers and long Bearer tokens, user:password@ in URLs, and password= / token= / "api_key": "..." style pairs.
Personal data: email addresses, IPv4 and IPv6 addresses (loopback is left alone), payment card numbers (Luhn-checked, known issuer prefixes), and, if you enable it, international phone numbers.
Provider tokens (Docker Hub, Anthropic, OpenAI, Google, npm, PyPI, SendGrid, Hugging Face and more), cookies and session ids, IBANs, and user names in home-directory paths are covered too; the full list with what each one finds is on the Detectors page, and logscrub --list-detectors prints it. SSNs, MAC addresses and a high-entropy catch-all are available as opt-in detectors. Version strings (Chrome/126.0.0.0), timestamps, MAC addresses, ssh://git@host and [email protected] are guarded by tests so they stay untouched.
Pseudonym mode replaces emails and IPs with [email:k3x9p2qa]-style tags derived from an HMAC key, so the same address maps to the same tag across a file and across runs (give --key-file or LOGSCRUB_KEY). Secrets always get a fixed marker, never a tag. See the wiki for the config file. The roadmap is in docs/SPEC.md.
Try it without installing anything: https://logscrub.hbenali.ovh/ (the engine runs in your browser as WebAssembly; open the network tab and you will see no request carrying your text). Locally:
logscrub serve opens a local page (default http://127.0.0.1:8080): paste or drop a log, see every match highlighted by detector, toggle detectors, switch between markers and stable tags, and download the cleaned text. It uses the same engine as the CLI. The text is processed in memory by the local process; the page loads nothing from anywhere else (strict CSP, no CDN, no analytics). It listens on loopback only unless you pass --allow-remote, because it has no authentication. See the wiki.
- Linear-time matching. Go's RE2 engine: hostile input cannot trigger ReDoS.
- Measured false positives. A "must not change" corpus of realistic logs runs in CI;
max_tokens=100andssh://git@hoststay untouched. - Bounded memory, fail closed. Streams line by line; a line it cannot scan safely is an error (exit 3), never passed through.
- No network, no files written, never echoes what it finds. Reports and errors contain counts and ids only.
- One static binary, a distroless Docker image, signed releases, and a web UI that cannot phone home.
- uses: hbenali/[email protected] # GitHub Action: fails if a file would be masked
with: { files: build.log }- repo: https://github.com/hbenali/logscrub # pre-commit hook
rev: 1.2.1
hooks: [{ id: logscrub }]See Using it in CI for SARIF / JSON reports and code scanning.
From 1.0, the command-line flags, exit codes, the config file format and the [REDACTED:id] / [kind:tag] output formats are stable across 1.x. New detectors may be added in minor releases, so a log that was clean before can have new matches; --check is the way to notice.
# macOS and Linux: Homebrew
brew install hbenali/tap/logscrub
# Ubuntu 22.04, 24.04, 26.04 (amd64): PPA
sudo add-apt-repository ppa:hbenali/logscrub
sudo apt install logscrub
# Fedora 43, 44, rawhide (x86_64): Copr
sudo dnf copr enable hbenali/logscrub
sudo dnf install logscrub
# Any Linux with snapd (amd64): Snap Store
sudo snap install logscrub
# Docker (Docker Hub; the same image is at ghcr.io/hbenali/logscrub)
docker run --rm -i hbenali/logscrub < app.log
# From source (Go 1.26+)
go install github.com/hbenali/logscrub/cmd/logscrub@latestThe PPA and Copr packages install the binary, man page and shell completions, and the package manager keeps them up to date. The snap is strictly confined: it reads and writes files in your home directory and on removable media only (for other files, pipe them in: sudo cat /var/log/app.log | logscrub).
Prebuilt binaries (linux, macOS and windows; amd64 and arm64) and .deb, .rpm and .apk packages are on Releases. They come with a checksum file and build attestations: gh attestation verify FILE --repo hbenali/logscrub. Check an install with logscrub --version. More detail, including shell completion: Installation.
Regex detection cannot find secrets with no recognisable shape (a password in prose, an unlabelled random string) or encoded ones (base64, URL-encoded). Review the output before sharing it publicly; --check in CI lowers the risk, it does not remove it.
Docs: wiki, SECURITY.md, CONTRIBUTING.md. MIT licensed.


![The cleaned text with stable tags such as [email:ggyjbrrk] and [ipv4:znrrpfi2]; secrets keep fixed markers](/hbenali/logscrub/raw/main/docs/screenshots/web-ui-pseudonyms.png)