Detailed content
🎯 The scanner's goal
Security audits are often rare events: someone runs a few tools before an important deploy and forgets about them the rest of the time. With local AI unlimited and always on, you can reverse this—a worker scans your repository continuously, looking for leaked secrets, vulnerable dependencies, and unsafe patterns without costing you anything beyond electricity.
🆕 New here?
"Secret" is any credential that accidentally leaks into code: an API key, token, database password. "Security scanner" is a program that scans code for these secrets and other known risks. Here it becomes a 24/7 worker: a process that runs on its own, in a loop, without you having to press a button.
🔑 What this employee searches for
- •Leaked secrets: API keys and passwords that accidentally made it into a commit.
- •Vulnerable dependencies: libraries with known CVEs (npm, pip).
- •Unsafe patterns: suspicious things that deserve a reviewer’s attention.
- •What’s new: alert only when something appears that wasn’t there yesterday.
📊 Why this only makes sense locally
- Continuous scanning = many model calls. In the cloud, each call has a toll; 24/7 gets expensive fast.
- Your source code is sensitive — sending it to a third-party server just to “analyze” it is exactly what you want to avoid.
- Local solves both at once: unlimited e private. The code never leaves the machine.
🗺️ Solution design
Before the code, the design. The secret to a good scanner isn’t throwing everything at the LLM—it’s a conveyor belt: inexpensive, precise tools detect; the local model just screens and explains, and cron runs it again. Each part does what it does best.
Read from left to right: the repository feeds the deterministic tools (step 1), the findings go to the local model that screens the risk (step 2), and returns a dated report. The cyan arrow below is the cron (step 3), closing the 24/7 loop.
These three steps are exactly the next three sections. In summary:
Deterministic scanning first
Tools like gitleaks e npm audit find secrets and CVEs accurately — fast, inexpensive, and without hallucinations. They do the raw detection.
The local model triages the findings
The LLM steps in then: reads the list of findings, classifies the risk (high/medium/low), and suggests a fix in clear language. It explains; it doesn’t make things up.
Cron schedules and keeps it running 24/7
A scheduler runs the script every few hours, saves relatorio-AAAA-MM-DD.md and only lets you know when something appears new. No noise.
🔍 Step 1 · deterministic scan
The temptation is to ask the LLM to "find the security issues". Don’t do this first. A model might miss an obvious secret or invent one that doesn’t exist. Deterministic tools — which always give the same answer for the same input — detect them with surgical precision. Run them first. The LLM comes in only at step 2.
⌨️ Copy-run: the detection tools
Objective: find leaked secrets and vulnerable dependencies without touching the model. Run it from your project root.
How to check: if there’s a secret, the gitleaks exits with a nonzero code and lists the file + line. The npm audit / pip-audit print CVEs by severity. Clean repo = empty output and exit 0.
💡 Practical tip
Intentionally combine the two worlds: the deterministic tool is needed but dumb (spots the pattern, doesn't understand the context); the LLM is flexible but fallible (understands, but can be wrong). Let each do what it's good at — the tool detects, the model explains. Never the other way around.
🤖 Step 2 · the agent reviews
Now the local model becomes truly useful. It doesn't search for anything—it receives the list of findings of the tools and does what a human would do in a review: assigns a risk level to each item and explains the fix in one line. You call the model through the OpenAI-compatible local API (the one from Ollama, from track 3.5).
⌨️ Copy-run: the local model triages a finding
Objective: send a finding to the model and receive a risk assessment + fix. Endpoint localhost — nothing leaves the machine.
How to check: the JSON response contains .choices[0].message.content with something like "Risk: high — revoke the key in AWS, remove it from history, and use an environment variable." A temperature low keeps triage consistent.
The key point is division of labor: the model is great at prioritizing and explaining, and terrible as a source of truth. See where to trust it and where not to:
✓ Good model usage
- ✓Prioritize: what’s truly serious versus noise
- ✓Explain the risk in plain English
- ✓Suggest a concrete fix
- ✓Summarize 50 findings in one paragraph
✗ Model misuse
- ✗Be the only one who “looks for” secrets
- ✗Trust it to say everything is clean
- ✗Apply fixes on its own, without you seeing them
- ✗Invent CVEs the tool didn’t find
⏰ Step 3 · schedule 24/7
Detection + triage become a employee when they run on their own. This is where the cron (the time-based scheduler, from section 4.2) comes in: it runs the script every few hours, records a dated report and—and the part that keeps you sane—only bothers you when there’s something new since the last round.
⌨️ Copy-run main: the pipeline script
Objective: put it all together — gitleaks detects, the local API triages, and out comes relatorio-AAAA-MM-DD.md. Save it as scan.sh.
How to check: run bash scan.sh once. It should appear ok: relatorios/relatorio-2026-06-29.md and the file contains the model’s triage. All via localhost.
⏱️ Copy-run: keep it running 24/7
Objective: run every 6 hours, automatically. Open crontab -e and add:
How to check: after a few hours, check ~/scan.log and the folder relatorios/ getting dated files. To “alert only on new items,” compare today’s report with yesterday’s (diff) and notify only if there’s a difference.
💡 Practical tip
The enemy of a 24/7 worker is alert fatigue: if it alerts you every round, you’ll stop reading. That’s why “alert only on what’s new” isn’t a minor detail—it determines whether you’ll trust the employee or silence it in the first week.
🔒 Hardening the worker
It works — now make it reliable. A scanner that screams false positive all day, or slips out of scope, becomes just more noise to ignore. And there's a line that doesn't overlap: the code doesn’t go anywhere. These practices separate a toy from an employee you can trust.
✓ Do this
- ✓Keep the model 100% local (endpoint localhost)
- ✓Define the scope: folders and file types that matter
- ✓Maintain an allowlist of known false positives
- ✓Treat the report as a suggestion—you decide and make corrections
✗ Avoid
- ✗Sending snippets of code to a cloud API "just to help"
- ✗Letting the agent apply fixes without human review
- ✗Scan everything without scope (slow and noisy)
- ✗Trust that “no alert” = “100% safe”
⚠️ Alert box: the golden rule
The whole point of this worker is to scan code without exposing code. If at any point you send the findings — or worse, the snippets — to a third-party service, you’ve lost the game: you’ve created a new leak while hunting for leaks.
- •Everything local: tools and the model run on your machine; traffic doesn't leave localhost (or your private tailnet).
- •Human review: the scanner prioritizes and suggests; you’re the one who revokes a key and opens a PR.
Self-check (optional): why run gitleaks / npm audit BEFORE calling the local model?
📌 Module summary
Next module:
4.4 — Web watcher hunting for opportunities