<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lovix Clouds</title>
    <description>The latest articles on DEV Community by Lovix Clouds (@lovixcloud).</description>
    <link>https://dev.to/lovixcloud</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4189693%2Fe49be416-31ca-44f4-a4de-cb4de4c4303f.png</url>
      <title>DEV Community: Lovix Clouds</title>
      <link>https://dev.to/lovixcloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lovixcloud"/>
    <language>en</language>
    <item>
      <title>I almost pasted my AWS key into ChatGPT, so I built a goblin to stop me</title>
      <dc:creator>Lovix Clouds</dc:creator>
      <pubDate>Sat, 17 Oct 2026 12:11:02 +0000</pubDate>
      <link>https://dev.to/lovixcloud/i-almost-pasted-my-aws-key-into-chatgpt-so-i-built-a-goblin-to-stop-me-2kb8</link>
      <guid>https://dev.to/lovixcloud/i-almost-pasted-my-aws-key-into-chatgpt-so-i-built-a-goblin-to-stop-me-2kb8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu65mnitcju8t8tcr72d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu65mnitcju8t8tcr72d6.png" alt="Leak Goblin AI Generated Image" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2l6n46bp5k8r2vmr8ge7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2l6n46bp5k8r2vmr8ge7.png" alt="Leak Goblin Documentation Snapshot" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scan locally. Redact sensitive-looking values. Review before sharing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;I didn't send it. But I sat there for a moment thinking about all the times I might not have noticed.&lt;/p&gt;

&lt;p&gt;That moment is why I built &lt;strong&gt;LeakGoblin&lt;/strong&gt; 🛡️, a small open-source CLI that checks your text for secrets &lt;em&gt;before&lt;/em&gt; 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.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why AI tools make this worse
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

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

&lt;p&gt;The usual answer is "never put secrets in your code or logs," and that's right. But real projects have &lt;code&gt;.env&lt;/code&gt; 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.&lt;/p&gt;


&lt;h2&gt;
  
  
  What LeakGoblin does
&lt;/h2&gt;

&lt;p&gt;It does two main jobs, &lt;strong&gt;scan&lt;/strong&gt; and &lt;strong&gt;sanitize&lt;/strong&gt;, plus a repo mode.&lt;/p&gt;
&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Try it without installing&lt;/span&gt;
npx leakgoblin &lt;span class="nt"&gt;--help&lt;/span&gt;

&lt;span class="c"&gt;# Or install globally (Node &amp;gt;= 20)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; leakgoblin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  1. Scan text from stdin
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;prompt.txt | leakgoblin scan &lt;span class="nt"&gt;--stdin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Output looks like this (secrets are always masked):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⚠️  The goblin found 2 suspicious tokens!

  &amp;lt;stdin&amp;gt;
    [CRITICAL] Private Key Block (confidence: high) L1:1
      → -----BEGIN RSA PRIVATE KEY----- [REDACTED]
    [HIGH] AWS Access Key (confidence: high) L2:10
      → apiKey = [REDACTED]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each finding includes the type, line number, severity and confidence, plus a masked snippet. It never prints the full secret.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Sanitize stdin
&lt;/h3&gt;

&lt;p&gt;This is the one I use most. Instead of just telling you what it found, it gives you a safe copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;prompt.txt | leakgoblin sanitize &lt;span class="nt"&gt;--stdin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AKIAIOSFODNN7EXAMPLE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3cr3tP@ssw0rd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[REDACTED:API_KEY:aws_access_key]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[REDACTED:PASSWORD:password_assignment]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;em&gt;kind&lt;/em&gt; of secret was removed, which helps when you're reviewing the result.&lt;/p&gt;

&lt;p&gt;A workflow that works well for me is to pipe straight into the clipboard, review, then paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;prompt.txt | leakgoblin sanitize &lt;span class="nt"&gt;--stdin&lt;/span&gt; | pbcopy   &lt;span class="c"&gt;# macOS&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;prompt.txt | leakgoblin sanitize &lt;span class="nt"&gt;--stdin&lt;/span&gt; | xclip &lt;span class="nt"&gt;-selection&lt;/span&gt; clipboard   &lt;span class="c"&gt;# Linux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Scan a repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;leakgoblin scan &lt;span class="nb"&gt;.&lt;/span&gt;
leakgoblin scan ./src
leakgoblin scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; leakgoblin-report.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  4. Use it in CI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;leakgoblin scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exit codes are simple:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No secrets found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Secrets found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Error (bad path, invalid config, input too large, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So a pipeline step can fail the build on a finding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;leakgoblin scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Secrets detected!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How detection works
&lt;/h2&gt;

&lt;p&gt;The part I thought about most is what to flag and how to say how sure you are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signatures first
&lt;/h3&gt;

&lt;p&gt;The core of LeakGoblin is a set of &lt;strong&gt;format-specific signatures&lt;/strong&gt;, patterns for credentials that have a recognizable shape:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Private keys&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN RSA PRIVATE KEY-----&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud credentials&lt;/td&gt;
&lt;td&gt;AWS &lt;code&gt;AKIA...&lt;/code&gt;, &lt;code&gt;aws_secret_access_key&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API keys&lt;/td&gt;
&lt;td&gt;GitHub &lt;code&gt;ghp_...&lt;/code&gt;, Stripe &lt;code&gt;sk_live_...&lt;/code&gt;, Slack &lt;code&gt;xoxb-...&lt;/code&gt;, Google &lt;code&gt;AIza...&lt;/code&gt;, OpenAI-style &lt;code&gt;sk-...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bearer tokens / JWTs&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Bearer ...&lt;/code&gt;, &lt;code&gt;eyJ...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passwords&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;password = "..."&lt;/code&gt;, &lt;code&gt;secret: ...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection strings&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mongodb://user:pass@host&lt;/code&gt;, &lt;code&gt;postgres://...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Env vars&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;GITHUB_API_KEY=...&lt;/code&gt;, &lt;code&gt;*_SECRET=...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;h3&gt;
  
  
  Then a &lt;em&gt;labeled&lt;/em&gt; heuristic
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I deliberately made two choices here:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Why not "flag everything"?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing it
&lt;/h3&gt;

&lt;p&gt;If your company has its own token format, add a rule in &lt;code&gt;leakgoblin.config.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"severityThreshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidenceThreshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxFileSizeMB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customPatterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"internal_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INTERNAL_[A-Z0-9_]{16,}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Internal token format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api_key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowlist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"patterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"^AKIAIOSFODNN7EXAMPLE$"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  Design decisions I care about
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. It never prints the full secret
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Fully local, with no telemetry
&lt;/h3&gt;

&lt;p&gt;LeakGoblin makes &lt;strong&gt;no network requests&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;That also keeps the trust model simple. You can read the source and confirm it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Boring, predictable exit codes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;. That's it. It works in a shell script, a GitHub Action, a pre-push hook or a Makefile without parsing anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Synthetic test data only
&lt;/h3&gt;

&lt;p&gt;All the tests use canary values like &lt;code&gt;AKIAIOSFODNN7EXAMPLE&lt;/code&gt;, 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.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;p&gt;I'd rather you hear this from me than discover it later:&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;




&lt;h2&gt;
  
  
  Roadmap, and a call for contributors
&lt;/h2&gt;

&lt;p&gt;LeakGoblin is MIT licensed and free to use. Here's what's planned next, and where I'd love help:&lt;/p&gt;

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

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




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx leakgoblin &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"test AKIAIOSFODNN7EXAMPLE"&lt;/span&gt; | npx leakgoblin scan &lt;span class="nt"&gt;--stdin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/leakgoblin" rel="noopener noreferrer"&gt;npm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/lovixcloud/leakgoblin" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;em&gt;The goblin is watching. Stay vigilant.&lt;/em&gt; 🛡️&lt;/p&gt;

</description>
      <category>node</category>
      <category>security</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>I almost pasted my AWS key into ChatGPT, so I built a goblin to stop me</title>
      <dc:creator>Lovix Clouds</dc:creator>
      <pubDate>Sat, 17 Oct 2026 02:45:00 +0000</pubDate>
      <link>https://dev.to/lovixcloud/i-almost-pasted-my-aws-key-into-chatgpt-so-i-built-a-goblin-to-stop-me-352p</link>
      <guid>https://dev.to/lovixcloud/i-almost-pasted-my-aws-key-into-chatgpt-so-i-built-a-goblin-to-stop-me-352p</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>node</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
