lenny_nif

Elixir NIF bindings for the Lenny secret redaction engine.

Scans and redacts known secrets using BLAKE3 + rolling hash (no secret values stored in memory at runtime). Includes 216 built-in pattern rules for detecting unknown secrets (API keys, tokens, connection strings).

Installation

Add to your mix.exs:

def deps do
  [{:lenny_nif, "~> 0.1.0"}]
end

Requires Elixir 1.14+ and Rust 1.88+ (for NIF compilation via Rustler).

Usage

Exact-match redaction

engine = Lenny.new_engine()

:ok = Lenny.load_secrets(engine, [
  %{name: "db_pass", value: "hunter2", tier: "alert"}
])

result = Lenny.scan_string(engine, "password is hunter2")
result.output      #=> "password is [REDACTED:db_pass]"
result.has_redactions  #=> true

Pattern scanning

scanner = Lenny.new_pattern_scanner()
matches = Lenny.scan_patterns(scanner, "AWS_KEY=AKIAIOSFODNN7EXAMPLE")
hd(matches).rule_id  #=> "aws-access-key"

API

Engine

Secret format

Each secret is a map with required keys name and value:

%{
  name: "db_pass",
  value: "hunter2",
  tier: "alert",        # "log" (default) | "alert" | "page"
  canary: false,        # default: false
  redaction: "tagged",  # "tagged" (default) | "full" | "partial"
  prefix: 4,            # for "partial" redaction
  suffix: 4,            # for "partial" redaction
  transformations: []   # ["base64", "url"]
}

Legacy 2-tuple format is also supported: {"db_pass", "hunter2"}.

Pattern Scanner

Full Documentation

See the Lenny project for configuration, deployment, threat model, and the complete list of pattern rules.

License

MIT