DEV Community

Lovix Clouds
Lovix Clouds

Posted on

I almost pasted my AWS key into ChatGPT, so I built a goblin to stop me

Leak Goblin AI Generated Image
Leak Goblin Documentation Snapshot

LeakGoblin is a free, local-only CLI that scans and redacts API keys, tokens and passwords before you paste text into AI tools. Here's why I built it and how it works.

Scan locally. Redact sensitive-looking values. Review before sharing.

It was a boring Tuesday. I was debugging a failing deploy, so I did what I do a dozen times a day: I selected a wall of terminal output, copied it, and switched to an AI chat window.

My finger was already on Enter when I noticed line 14 of the log. It was an AWS_ACCESS_KEY_ID, sitting there in plain text, followed by the secret right below it.

I didn't send it. But I sat there for a moment thinking about all the times I might not have noticed.

That moment is why I built LeakGoblin 🛡️, a small open-source CLI that checks your text for secrets before it leaves your machine. This post covers why the problem is getting worse, how the tool works, the design decisions I made, and where it falls short.


Why AI tools make this worse

Leaking secrets by copy-paste isn't new. People have pasted credentials into Stack Overflow questions and GitHub issues for years. But AI tools changed the volume and the habit:

  • We paste far more context. Asking an assistant to debug something usually means pasting the whole stack trace, the config file, the Dockerfile and the relevant .env lines, because more context gets better answers.
  • It's conversational and low-friction. A chat box feels private. It doesn't feel like publishing, so we don't get the pause we'd get before posting publicly.
  • Agents read files directly. Coding agents and assistants can pull files into their context on their own. Whatever is in those files goes with them.
  • We rely on remembering to check. Every paste is a chance to forget, and "I'll be careful" is not a security control.

The usual answer is "never put secrets in your code or logs," and that's right. But real projects have .env files, verbose logs, connection strings in error messages, and tokens in curl commands you copied from a tutorial. The goal isn't perfection. It's a safety net at the exact moment of the paste.


What LeakGoblin does

It does two main jobs, scan and sanitize, plus a repo mode.

Install

# Try it without installing
npx leakgoblin --help

# Or install globally (Node >= 20)
npm install -g leakgoblin
Enter fullscreen mode Exit fullscreen mode

1. Scan text from stdin

cat prompt.txt | leakgoblin scan --stdin
Enter fullscreen mode Exit fullscreen mode

Output looks like this (secrets are always masked):

⚠️  The goblin found 2 suspicious tokens!

  <stdin>
    [CRITICAL] Private Key Block (confidence: high) L1:1
      → -----BEGIN RSA PRIVATE KEY----- [REDACTED]
    [HIGH] AWS Access Key (confidence: high) L2:10
      → apiKey = [REDACTED]
Enter fullscreen mode Exit fullscreen mode

Each finding includes the type, line number, severity and confidence, plus a masked snippet. It never prints the full secret.

2. Sanitize stdin

This is the one I use most. Instead of just telling you what it found, it gives you a safe copy:

cat prompt.txt | leakgoblin sanitize --stdin
Enter fullscreen mode Exit fullscreen mode

Input:

api_key = "AKIAIOSFODNN7EXAMPLE"
password = "s3cr3tP@ssw0rd"
Enter fullscreen mode Exit fullscreen mode

Output:

api_key = "[REDACTED:API_KEY:aws_access_key]"
password = "[REDACTED:PASSWORD:password_assignment]"
Enter fullscreen mode Exit fullscreen mode

Surrounding text and line breaks are preserved, so the AI still gets the context it needs (the structure of your config, the shape of the error) without the actual credentials. The placeholder tells you what kind of secret was removed, which helps when you're reviewing the result.

A workflow that works well for me is to pipe straight into the clipboard, review, then paste:

cat prompt.txt | leakgoblin sanitize --stdin | pbcopy   # macOS
cat prompt.txt | leakgoblin sanitize --stdin | xclip -selection clipboard   # Linux
Enter fullscreen mode Exit fullscreen mode

3. Scan a repository

leakgoblin scan .
leakgoblin scan ./src
leakgoblin scan . --format json > leakgoblin-report.json
Enter fullscreen mode Exit fullscreen mode

It skips the usual noise (.git, node_modules, dist, build, .next, coverage), plus large and binary files. --verbose shows what was skipped, and --exclude adds your own patterns.

4. Use it in CI

leakgoblin scan . --quiet
echo $?
Enter fullscreen mode Exit fullscreen mode

The exit codes are simple:

Code Meaning
0 No secrets found
1 Secrets found
2 Error (bad path, invalid config, input too large, etc.)

So a pipeline step can fail the build on a finding:

leakgoblin scan . --quiet
if [ $? -eq 1 ]; then echo "Secrets detected!"; exit 1; fi
Enter fullscreen mode Exit fullscreen mode

How detection works

The part I thought about most is what to flag and how to say how sure you are.

Signatures first

The core of LeakGoblin is a set of format-specific signatures, patterns for credentials that have a recognizable shape:

Category Examples
Private keys -----BEGIN RSA PRIVATE KEY-----
Cloud credentials AWS AKIA..., aws_secret_access_key
API keys GitHub ghp_..., Stripe sk_live_..., Slack xoxb-..., Google AIza..., OpenAI-style sk-...
Bearer tokens / JWTs Bearer ..., eyJ...
Passwords password = "...", secret: ...
Connection strings mongodb://user:pass@host, postgres://...
Env vars GITHUB_API_KEY=..., *_SECRET=...

When a string starts with AKIA and has the right length and character set, that's a strong signal. Findings like that are marked high confidence. Looser patterns, like generic password = ... assignments or JWT-looking strings, are medium.

Then a labeled heuristic

Not every secret has a neat prefix. For those, LeakGoblin also has a heuristic for long, high-entropy strings. These are the random-looking blobs that might be a token, or might be a hash, a UUID or a build ID.

I deliberately made two choices here:

  1. Heuristic findings are labeled confidence: low and severity: low. They're never mixed in with signature matches as if they were equally certain.
  2. You control the noise. If the heuristic is too chatty for your codebase, raise confidenceThreshold to medium in your config and it goes quiet.

Why not "flag everything"?

It's tempting to make a secret scanner paranoid. Flag every long string, every base64 blob, every hex value. The tool then feels thorough, but it fails in practice.

If a scanner cries wolf constantly, people stop reading its output. Then they add it to an ignore list, or stop running it. A tool that gets disabled protects nobody. So the design goal is that when LeakGoblin says "critical, high confidence," you believe it, and when it says "low, heuristic," you know to look but not panic.

Customizing it

If your company has its own token format, add a rule in leakgoblin.config.json:

{
  "version": 1,
  "severityThreshold": "low",
  "confidenceThreshold": "low",
  "maxFileSizeMB": 5,
  "customPatterns": [
    {
      "id": "internal_token",
      "pattern": "INTERNAL_[A-Z0-9_]{16,}",
      "description": "Internal token format",
      "category": "api_key",
      "severity": "high",
      "confidence": "medium"
    }
  ],
  "allowlist": {
    "patterns": ["^AKIAIOSFODNN7EXAMPLE$"]
  }
}
Enter fullscreen mode Exit fullscreen mode

The allowlist is for approved test fixtures like AWS's documented example key, so they don't trigger every run. Use it carefully.


Design decisions I care about

1. It never prints the full secret

This sounds obvious, but a secret scanner that echoes secrets into your terminal, your CI logs or its JSON report becomes a new leak path.

Every finding is masked in text output. In JSON output, the raw match fields are stripped. The tool is built so that its own output is safe to look at, share in a bug report, or save as a CI artifact.

2. Fully local, with no telemetry

LeakGoblin makes no network requests during scan or sanitize. There's no upload, no account and no phoning home. For a tool whose whole purpose is keeping sensitive data from leaving your machine, anything else would be absurd.

That also keeps the trust model simple. You can read the source and confirm it.

3. Boring, predictable exit codes

0, 1, 2. That's it. It works in a shell script, a GitHub Action, a pre-push hook or a Makefile without parsing anything.

4. Synthetic test data only

All the tests use canary values like AKIAIOSFODNN7EXAMPLE, never real credentials. If you report a false positive or a missed format, please do the same and send a synthetic example of the shape, never a real secret.


Honest limitations

I'd rather you hear this from me than discover it later:

  • It's a best-effort filter, not a guarantee. It uses signatures plus conservative heuristics, and it can't identify every possible secret. Always review the sanitized output before sharing it.
  • Novel or obfuscated formats can be missed. If a provider changes its token format, or a secret is split or encoded, the scanner may not catch it. Custom patterns help.
  • The heuristic is only a hint. Low-confidence findings can be false positives.
  • It's not a secrets manager. It doesn't replace a vault, encrypted env files or proper rotation. If a real secret does leak, rotate it no matter what any scanner said.
  • It assumes you trust your machine. It doesn't protect against a compromised OS.
  • It's not a compliance certification.

It also isn't trying to replace tools like gitleaks or trufflehog, which are built for scanning git history and org-wide repos. LeakGoblin targets a narrower moment: the clipboard on its way to an AI chat or an issue tracker.


Roadmap, and a call for contributors

LeakGoblin is MIT licensed and free to use. Here's what's planned next, and where I'd love help:

  • [ ] More provider tokens (Azure, GCP, npm and others) with high-confidence signatures
  • [ ] SARIF output for GitHub Code Scanning
  • [ ] --fix as an explicit opt-in that writes sanitized files
  • [ ] Pre-commit hook example
  • [ ] VS Code extension using the same engine
  • [ ] Better .env and Docker secret detection

The easiest way to contribute is adding a detection rule for a token format you know well. CONTRIBUTING.md walks through it. Reporting a false positive or a missed secret format with a synthetic example is just as valuable.


Try it

npx leakgoblin --help
echo "test AKIAIOSFODNN7EXAMPLE" | npx leakgoblin scan --stdin
Enter fullscreen mode Exit fullscreen mode

If it saves you from one bad paste, a ⭐ on the repo helps other developers find it. And I'd really like to hear: how do you keep secrets out of your AI chats today? Tell me in the comments, along with any token formats you want covered.

The goblin is watching. Stay vigilant. 🛡️

Top comments (0)