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.5.0"
# CLI
Library usage
Pick a masking strategy
use ;
// [REDACTED:EMAIL] (default)
new;
// fixed string, from either a literal or a runtime String
new.mask;
new.mask;
// keep the last 4 chars: 4111 1111 1111 1111 -> ***************1111
new.mask;
// stable non-cryptographic fingerprint for correlation (not anonymization)
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 '#'
# Redact everything except phone numbers
# Print supported detector names
# CI guard: fail the build if a file contains secrets; print kinds/offsets to stderr
||
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)
Security model and limitations
leakguard is a best-effort redaction tool intended to reduce accidental leakage of secrets and personally identifiable information in logs, text, and CI workflows. It is not a substitute for secret management, access control, code review, or incident response.
Important limitations:
- Detectors are intentionally conservative in several places to reduce false positives, so some real secrets or PII formats may not be detected.
- Some detectors can still produce false positives, especially phone numbers and opt-in high-entropy scanning.
- Redaction should happen as early as possible, before sensitive data leaves your process or enters persistent logs.
Mask::Hashis a stable, non-cryptographic fingerprint for correlation only. It is not anonymization and does not protect low-entropy values from guessing or dictionary attacks.- Keep raw logs and unredacted inputs protected. Treat leakguard as a defense in depth layer, not as the only control protecting sensitive data.
If you believe you found a vulnerability or a serious redaction bypass, please report it privately through GitHub's vulnerability reporting flow when available, or contact the maintainer through GitHub before opening a public issue.
Performance
leakguard uses hand-written, single-pass byte scanners — no regex backtracking. Detection is roughly linear in input size. Run the bundled example and benchmark harness:
The benchmark harness is intentionally dependency-free and uses
std::time::Instant, so run it several times on an otherwise idle machine when
comparing changes.
no_std
[]
= { = "0.5", = false }
This drops the CLI and std-only conveniences but keeps the full detection and
redaction API (it needs alloc).
Reporting detector issues
False positives and false negatives are extremely useful for improving leakguard. Please report them with fake or synthetic examples only. Do not paste real secrets, tokens, private keys, customer data, or production logs into GitHub issues, pull requests, or discussions.
Helpful reports usually include:
- leakguard version
- detector kind, if known
- fake input text
- actual output
- expected output
- whether the issue affects the library, CLI, or both
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.