PTENES
Skip to content
MODULE 4.3

🛡️ Step-by-step #1: 24/7 security scanner

Time to build the first worker in your fleet: a worker that scans your code all the time for leaked secrets and vulnerable dependencies — deterministic tools do the heavy lifting, the local model triages what’s serious, and cron keeps everything running. Nothing leaves the machine.

6
Topics
~40
Minutes
Advanced
Level
Practical
Type

Detailed content

1

🎯 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.
Secrets
leaked keys
Deps
Known CVEs
24/7
always watching
Local
nothing leaks
2

🗺️ 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.

step 3 · cron repeats the cycle 24/7 — alert only on what's new step 1 · detect step 2 · triage Repo your local code Tools gitleaks · audit Local LLM risk screening Report dated + alert

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:

1

Deterministic scanning first

Tools like gitleaks e npm audit find secrets and CVEs accurately — fast, inexpensive, and without hallucinations. They do the raw detection.

2

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.

3

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.

3

🔍 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.

# 1) secrets in code and in git history
gitleaks detect --source . --no-banner
# 2) vulnerable dependencies — Node
npm audit --audit-level=high
# 2) vulnerable dependencies — Python
pip-audit

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.

gitleaks
secrets
npm audit
Node dependencies
pip-audit
Python dependencies
Deterministic
without hallucinating
4

🤖 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.

curl -s http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" -d '{
    "model": "qwen2.5:7b",
    "temperature": 0.2,
    "messages": [
      {"role":"system","content":"You are a reviewer of
      security. For each finding, give the risk
      (high/medium/low) and the correction in 1 line.
      Don’t make up findings that aren’t on the list."},
      {"role":"user","content":"gitleaks finding:"}
      AWS_SECRET_KEY exposed in config/prod.env:12"}
    ]
  }'

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
5

⏰ 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.

#!/usr/bin/env bash
# scan.sh — local 24/7 scan, nothing leaves the machine
set -euo pipefail
DATA=$(date +%F)             # 2026-06-29
REL="relatorios/relatorio-$DATA.md"; mkdir -p relatorios
# 1) deterministic: detects secrets
gitleaks detect --source . --no-banner \
  --report-format json --report-path /tmp/leaks.json || true
# 2) triage with the LOCAL model (Ollama API)
BODY=$(jq -n --rawfile L /tmp/leaks.json '{
  model:"qwen2.5:7b", temperature:0.2, messages:[
  {role:"system",content:"Security reviewer. Give
  risk and fix in 1 line per finding."},
  {role:"user",content:("Findings:\n"+$L)}]}')
RESP=$(curl -s http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" -d "$BODY" \
  | jq -r '.choices[0].message.content')
# 3) save the dated report
printf '# Security — %s\n\n%s\n' "$DATA" "$RESP" > "$REL"
echo "ok: $REL"

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:

# min hour day month weekday command
0 */6 * * * cd ~/meu-projeto && bash scan.sh >> ~/scan.log 2>&1

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.

6

🔒 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?

Scope
less noise
Allowlist
false positive +
Local
nothing leaks
Human
decides and corrects

📌 Module summary

✓
The goal — a worker that scans the codebase 24/7 for secrets and vulnerable dependencies, unlimited and private because it’s local.
✓
Step 1: detect — deterministic tools (gitleaks, npm audit, pip-audit) provide precise detection.
✓
Step 2: triage — the local model classifies risk and suggests a fix via an OpenAI-compatible API.
✓
Step 3: schedule — cron runs the script, saves a dated report, and alerts only on what’s new. Everything stays local, with human review.

Next module:

4.4 — Web watcher hunting for opportunities