hush

package module
v0.1.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

README

hush

hush

Find secrets and personal data in your code and files. Runs locally on any laptop.
One small binary. No cloud. No GPU. No setup.

ci Go Reference Release

What it does

Hush reads files and points out two kinds of things you usually do not want sitting in your code or logs:

  • Secrets — API keys, tokens, passwords, certificates.
  • Personal data (PII) — emails, phone numbers, names, addresses, social security numbers, credit card numbers.

It works by combining two checks:

  1. A list of patterns that match common secrets and personal data.
  2. A small built in AI that reads the surrounding text and decides if a match is real, or just an example in a README, or something harmless that happens to look suspicious.

You get the things pattern scanners catch, plus the ones they cannot describe with a pattern (like a person's name in a sentence), and far fewer false alarms.

Why it is different

  • One file to run. A single binary. No Python, no libraries, no Docker.
  • Works offline. Your code never leaves your machine.
  • No GPU. Runs on any laptop or CI machine.
  • Fast on clean files. If a file has nothing suspicious, hush moves on in milliseconds.
  • Use it anywhere. Command line, CI, Go library, pre commit hook, log filter.

Install

# Download a prebuilt binary (Linux or macOS)
curl -sSL https://github.com/valllabh/hush/releases/latest/download/hush_linux_amd64.tar.gz | tar xz
sudo mv hush /usr/local/bin/

# Or with Go
go install github.com/valllabh/hush/cmd/hush@latest

Two modes

Hush works two ways. Pick one:

Find mode

Reports each secret or personal data item it sees. One JSON object per line. Drops into CI, scripts, dashboards.

$ hush detect path/to/file.txt
{"file":"path/to/file.txt","line":2,"column":11,"rule":"secret","redacted":"AKI**************PLE","start":29,"end":49,"confidence":1.00}
{"file":"path/to/file.txt","line":3,"column":10,"rule":"pii","redacted":"val*****************com","start":59,"end":82,"confidence":1.00}
{"file":"path/to/file.txt","line":4,"column":8,"rule":"pii","redacted":"415******671","start":90,"end":102,"confidence":1.00}

By default the raw secret value is not printed. Only the redacted preview ships in the output. This is on purpose: a finding pipeline that prints raw secrets to logs, dashboards, or CI artifacts is itself a leak. Pass --output-reveal-secrets if you really need the raw value (key rotation pipelines, automated revocation), and only when the output sink is private.

Each line tells you:

field what it means
file which file it came from
line, column where in the file
rule secret or pii
redacted a safe-to-log preview (first 3 + stars + last 3)
start, end byte offsets into the file
confidence 0 to 1 (1 means the regex matched; lower means the AI is less sure)

Exit code is non zero when findings are reported, so it drops straight into CI.

Mask mode

Reads text, writes the same text back with secrets replaced by placeholders. Useful for log redaction, cleaning up support tickets, masking before sending text to an LLM.

$ echo 'My key is AKIAIOSFODNN7EXAMPLE and email is vj@example.com' | hush --output-mask
My key is [REDACTED_AWS_ACCESS_KEY_ID_1] and email is [REDACTED_EMAIL_ADDRESS_2]

Each placeholder is unique and labeled, so you can match the same secret across multiple appearances if you need to.

Common patterns

# Scan a directory and get findings
hush detect ./my-repo

# Pipe text in
cat suspicious.log | hush detect

# Save findings as JSON
hush detect . > findings.jsonl

# Mask a file
hush --output-mask < raw.log > clean.log

# Plug your own model in
hush detect --model my-model.hbin --tokenizer my-tokenizer.json ./my-repo

Run hush --help for the full list.

As a Go library

import "github.com/valllabh/hush"

s, _ := hush.New(hush.Options{
    UseDetector:       true, // catches secrets and PII
    DetectorPrefilter: true, // fast on clean files
    MinConfidence:     0.5,
})
defer s.Close()

// Find mode: list of findings
findings, _ := s.ScanReader(reader)
for _, f := range findings {
    fmt.Println(f.Line, f.Column, f.Rule, f.Redacted, f.Confidence)
}

// Mask mode: text in, text out, secrets replaced
masked, _, _ := s.Redact(text, "[REDACTED:%s]")

One import. One call. Done. See examples/lib-basic for a runnable version.

Where to plug it in

Drop in patterns in examples/:

Quality

Tested against a small labeled set of 22 files (real secrets, real PII, README examples, test fixtures, mixed):

Category Caught False alarms
secrets 100% 1 in 10
PII 75% 1 in 10

Plain English: every secret in the test set was caught. About one in ten flagged items is a false alarm. Personal data coverage includes things older tools miss like names in prose. The test set lives in pkg/scanner/testdata/corpus, and the build fails if these numbers regress.

How it compares

tool offline uses AI covers PII extra setup single binary
hush yes yes yes none yes
trufflehog yes partial narrow none yes
gitleaks yes no narrow none yes
ggshield no yes partial Python plus API no

For exhaustive secret only coverage with no AI, pair hush with gitleaks.

Verify a release

Every release archive is signed via GitHub Actions. Verify with cosign:

cosign verify-blob \
  --certificate hush_linux_amd64.tar.gz.pem \
  --signature   hush_linux_amd64.tar.gz.sig \
  --certificate-identity-regexp "https://github.com/valllabh/hush/.github/workflows/release.yml.*" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  hush_linux_amd64.tar.gz

How it works

  1. Look for anything that could be a secret or personal data. A list of about 100 patterns plus a randomness check pulls out candidates: AWS keys, GitHub tokens, emails, phone numbers, credit cards, addresses, and so on. Cheap and fast. Files with no candidates skip the next step.

  2. Have the AI take a look. For each candidate, the AI reads the words around it and decides:

    • Real. Keep it.
    • Just an example in a README or test file. Drop it.
    • Bonus: sometimes the AI spots names, internal tokens, or addresses that no pattern describes. Those become extra findings.

The AI has been trained on labeled examples so it can tell a real AWS key from one in a tutorial that says "do not use". The model is baked into the binary and runs on your CPU.

Numbers and benchmarks: PERF.md and CHANGELOG.md.

Security · Contributing · License

Documentation

Overview

Package hush is the public, ergonomic entry point for hush.

Most library users should need only this package.

V2 detector (recommended; catches secrets and PII):

import "github.com/valllabh/hush"

s, err := hush.New(hush.Options{UseDetector: true, DetectorPrefilter: true})
if err != nil { panic(err) }
defer s.Close()

findings, _ := s.ScanReader(reader)
masked, _, _ := s.Redact(text, "[REDACTED:%s]")

V1 sequence classifier (legacy, secrets only, faster on huge dirty input):

s, err := hush.New(hush.Options{MinConfidence: 0.9})

The default build uses the pure Go runtime from pkg/native — no CGO, no libonnxruntime, truly static. Advanced users who want to drive the extractor or classifier directly can reach pkg/{scanner,native,extractor}.

Index

Constants

View Source
const ModelVersion = native.ModelVersion

ModelVersion is the version of the classifier model compiled into this build. Surface this in --version output, request logs, or telemetry so you can correlate findings with a specific model.

Variables

This section is empty.

Functions

This section is empty.

Types

type Finding

type Finding = scanner.Finding

Scanner, Options and Finding are aliased from pkg/scanner so the hush namespace is complete on its own. Any value produced by hush can be passed to pkg/scanner functions and vice versa.

type Options

type Options = scanner.Options

Scanner, Options and Finding are aliased from pkg/scanner so the hush namespace is complete on its own. Any value produced by hush can be passed to pkg/scanner functions and vice versa.

type Scanner

type Scanner = scanner.Scanner

Scanner, Options and Finding are aliased from pkg/scanner so the hush namespace is complete on its own. Any value produced by hush can be passed to pkg/scanner functions and vice versa.

func Default

func Default() (*Scanner, error)

Default returns a Scanner with the v2 detector + prefilter enabled. Mirrors `hush detect` defaults. Useful for one-shot scripts and examples that want sensible behaviour out of the box.

func New

func New(opts Options) (*Scanner, error)

New returns a Scanner ready to use.

  • Options.UseDetector=true: embedded v2 NER detector (secrets + PII). ModelOff is forced true; v1 classifier is not loaded.
  • Options.UseDetector=false: embedded v1 sequence classifier (secrets). This is the legacy path; ModelOff=true skips the model and runs the extractor only.

DetectorPrefilter only affects the v2 path. It enables a regex+entropy gate in front of the model so files with no candidates skip the model entirely. Strongly recommended (1000x faster on clean files; quality is preserved or improved by a hybrid regex+model fusion).

Directories

Path Synopsis
cmd
hush command
hush: portable secrets and PII scrubber.
hush: portable secrets and PII scrubber.
hush/cli
Package cli defines hush's cobra commands.
Package cli defines hush's cobra commands.
internal
walker
Package walker collects scannable files from a set of paths.
Package walker collects scannable files from a set of paths.
pkg
bundled
Package bundled wires the embedded classifier into pkg/scanner.
Package bundled wires the embedded classifier into pkg/scanner.
extractor
Package extractor holds the regex+entropy candidate finder.
Package extractor holds the regex+entropy candidate finder.
native
Package native is a pure Go transformer inference runtime for hush.
Package native is a pure Go transformer inference runtime for hush.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL