leakguard
Fast, zero-dependency redaction of secrets & PII from text and logs — in pure Rust.
leakguard finds and removes sensitive data — emails, credit cards, IP addresses,
JWTs, SSNs, MAC addresses, AWS keys, and URLs with embedded credentials — from
arbitrary strings and log lines. It's a library and a CLI.
use Redactor;
let s = new;
let clean = s.clean;
assert_eq!;
Why leakguard?
The Rust ecosystem has crypto, parsers, and web frameworks — but no small,
maintained, dependency-free library for the everyday job of not leaking PII
and secrets into your logs. Python has scrubadub, JS has redact-pii. leakguard
fills that gap with:
- Zero dependencies. No
regex, nolazy_static, nothing. Justcore+alloc. Tiny build, tiny binary, fast compile. #![no_std]friendly. Works in embedded / WASM withdefault-features = false.#![forbid(unsafe_code)]. 100% safe Rust.- Correct by construction. Match offsets always land on UTF-8 boundaries, Luhn-validated card numbers, range-checked IP octets — fewer false positives.
- Extensible. Plug in your own detectors with a closure.
- Batteries included. A
leakguardCLI you can pipe logs through.
Install
# Library
[]
= "0.1.0"
# CLI
Library usage
Pick a masking strategy
use ;
// [REDACTED:EMAIL] (default)
new;
// fixed string
new.mask;
// keep the last 4 chars: 4111 1111 1111 1111 -> ***************1111
new.mask;
// stable fingerprint so equal values stay equal (non-cryptographic)
new.mask;
Pick what to detect
use ;
let s = only;
let s = new.without; // everything except IPv4
Inspect without mutating
use Redactor;
let s = new;
for m in s.find
assert!;
Add a custom detector
use ;
let tickets = new;
let s = new.with_detector;
assert_eq!;
CLI usage
# Pipe a live log through it
|
# Redact a file to stdout, keeping last 4 chars
# Only redact emails and IPv4, masking with '#'
# CI guard: fail the build if a file contains secrets
||
Detectors
| Kind | Example | Notes |
|---|---|---|
Email |
alice@example.com |
requires a real-looking TLD |
CreditCard |
4111 1111 1111 1111 |
Luhn-validated, 13–19 digits |
IpV4 |
192.168.0.1 |
each octet range-checked 0–255 |
IpV6 |
2001:db8::1 |
supports :: compression |
Jwt |
eyJ….eyJ….sig |
three base64url segments |
UsSsn |
123-45-6789 |
rejects invalid area numbers |
MacAddress |
00:1A:2B:3C:4D:5E |
: or - separators |
AwsAccessKey |
AKIAIOSFODNN7EXAMPLE |
AKIA/ASIA/… + 16 chars |
UrlCredentials |
https://user:pass@host |
redacts the user:pass userinfo |
PhoneNumber |
+1 (415) 555-0132 |
conservative; needs grouping/+ |
GitHubToken |
ghp_…, github_pat_… |
PAT / OAuth / app / refresh |
SlackToken |
xoxb-…, xoxp-… |
bot / user / app tokens |
StripeKey |
sk_live_…, pk_test_… |
secret / restricted / publishable |
GoogleApiKey |
AIza… (39 chars) |
fixed-length token |
OpenAiKey |
sk-…, sk-proj-… |
hyphenated form (≠ Stripe sk_) |
PrivateKey |
-----BEGIN … PRIVATE KEY----- |
whole PEM block, incl. body |
Iban |
DE89370400440532013000 |
mod-97 checksum-validated |
GenericSecret |
high-entropy tokens | opt-in HighEntropy detector |
Custom(&str) |
anything you want | via FnDetector |
GenericSecret(theHighEntropydetector) is not in the defaults — it's the most false-positive-prone, so you enable it explicitly:use ; let s = new.with_detector; // or tune it: HighEntropy::new(/* min_len */ 24, /* min_entropy bits */ 4.0)
Performance
leakguard uses hand-written, single-pass byte scanners — no regex backtracking. Detection is roughly linear in input size. Run the bundled example:
no_std
[]
= { = "0.1", = false }
This drops the CLI and std-only conveniences but keeps the full detection and
redaction API (it needs alloc).
Contributing
Issues and PRs welcome — especially new detectors and false-positive reports
with sample inputs. Run cargo test && cargo clippy --all-targets -- -D warnings
before submitting.
Author
Created and maintained by ptukovar.
License
Licensed under either of MIT or Apache-2.0 at your option.