Free Security Scanning Tools You Should Run Today
Security First — Part 21 of 30
Last September, a security engineer named Luke Marshall ran TruffleHog against 5.6 million public GitLab repositories. In just over 24 hours — at a total cost of $770 in cloud compute — he found 17,430 verified live secrets: Google Cloud credentials, MongoDB keys, OpenAI API tokens, and hundreds of GitLab access keys sitting in plain sight. Many of those secrets were committed by developers who thought they were being careful.
Here's the part that should concern you: most of those repos weren't abandoned hobbyist projects. They were active codebases — the kind that handle real users, real data, and real money.
If you're a vibe coder — someone who builds with AI assistance and ships fast — the odds are good that your codebase has at least one of the issues we've covered in this series: a SQL injection hole, an XSS vector, a hardcoded secret, or a dependency carrying a known CVE. The good news? There are free tools that can find these in minutes. You don't need to be a security expert. You just need to run the right commands.
Let's do it.
Why Automated Scanning Matters Right Now
Before we get into the tools, here's the context that should motivate you to act today:
- In 2025, 28.65 million new hardcoded secrets were added to public GitHub repositories — a 34% increase over the prior year, according to GitGuardian's 2026 State of Secrets Sprawl report. Repositories using AI coding assistants had a 40% higher secret leakage rate than average.
- In September 2025, a self-replicating npm worm called Shai-Hulud compromised 18 popular packages — including
chalkanddebug, with a combined 2.6 billion weekly downloads. It used TruffleHog itself as a payload to scan hosts and exfiltrate developer credentials. - According to DeepStrike's 2025 vulnerability statistics, XSS and SQL injection are still among the most commonly reported vulnerability classes in 2025. These are problems that SAST tools catch automatically.
The attack surface is growing. Scanners are fast and free. There's no excuse not to run them.
The Eight Tools
Here's what we're covering, matched to the vulnerabilities from earlier in this series:
| Tool | What It Catches | Language/Platform |
|---|---|---|
| Semgrep | SQLi, XSS, insecure patterns | Any (Python, JS, Go, Java, etc.) |
| Bandit | Python-specific security issues | Python |
| ESLint security plugins | XSS, injection in JS/TS | JavaScript/TypeScript |
| npm audit | Known CVEs in dependencies | Node.js |
| pip-audit | Known CVEs in dependencies | Python |
| Trivy | Container vulnerabilities, misconfigs | Docker/Kubernetes |
| TruffleHog / Gitleaks | Hardcoded secrets, leaked credentials | Any (scans git history) |
| OWASP ZAP | Runtime web vulnerabilities | Any web app |
Let's go tool by tool.
1. Semgrep — Your First Line of Defense
Semgrep is a static analysis tool that scans your source code for patterns that match known vulnerability signatures. It supports 30+ languages and has a massive free ruleset.
Install and run:
# Install
pip install semgrep
# Run against your project with the default security ruleset
semgrep --config=auto .
# Run only the OWASP Top 10 rules
semgrep --config=p/owasp-top-ten .
# Run Python-specific security rules
semgrep --config=p/python .
What you'll see:
┌─────────────────┐
│ 3 findings │
└─────────────────┘
app/db.py
python.sqlalchemy.security.sqlalchemy-execute-raw-query.sqlalchemy-execute-raw-query
Line 42: db.execute(f"SELECT * FROM users WHERE id = {user_id}")
Severity: ERROR
Message: Detected string formatting in a possibly vulnerable SQL query.
Use parameterized queries instead.
That finding? That's the SQL injection bug from Part 7. Semgrep caught it in seconds.
For JavaScript/TypeScript projects, add:
semgrep --config=p/javascript .
semgrep --config=p/typescript .
2. Bandit — Python Security Linting
Bandit was built specifically for Python. It scans your AST (abstract syntax tree) and flags dangerous patterns: eval() calls, hardcoded passwords, use of weak cryptography, shell injection risks.
Install and run:
# Install
pip install bandit
# Scan your project recursively
bandit -r ./myproject
# Get a full report with severity and confidence levels
bandit -r ./myproject -l -i
# Output as JSON for CI integration
bandit -r ./myproject -f json -o bandit-report.json
Example output:
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection
Severity: MEDIUM Confidence: MEDIUM
Location: app/routes.py:34
34 query = "SELECT * FROM orders WHERE user=" + username
>> Issue: [B106:hardcoded_password_funcarg] Possible hardcoded password
Severity: LOW Confidence: MEDIUM
Location: app/config.py:12
12 connect(password="admin123")
Bandit won't catch everything, but for pure Python projects it's the fastest tool to run and the output is human-readable even if you're not a security professional.
3. ESLint Security Plugin — JavaScript/TypeScript
If your project has any frontend JavaScript or TypeScript, the eslint-plugin-security package adds security-focused linting rules on top of your existing ESLint setup.
Install and configure:
# Install
npm install --save-dev eslint-plugin-security
# Or for TypeScript projects:
npm install --save-dev eslint-plugin-security @typescript-eslint/eslint-plugin
Add to your .eslintrc.js:
module.exports = {
plugins: ['security'],
extends: ['plugin:security/recommended'],
rules: {
// Catch common injection patterns
'security/detect-non-literal-regexp': 'warn',
'security/detect-possible-timing-attacks': 'warn',
'security/detect-non-literal-fs-filename': 'error',
'security/detect-child-process': 'error',
}
};
Run it:
npx eslint . --ext .js,.ts,.tsx
You'll get warnings like:
app/api.js
Line 23: security/detect-non-literal-regexp RegExp with user-supplied input
Line 45: security/detect-child-process Found child_process import
4. npm audit — Dependency Vulnerability Scanning
npm audit is built into npm. It checks your installed packages against a database of known CVEs. You should be running this before every deployment.
# Run a full audit
npm audit
# Auto-fix compatible vulnerabilities
npm audit fix
# Force-fix (careful: may introduce breaking changes)
npm audit fix --force
# Get JSON output for automation
npm audit --json > npm-audit-report.json
Example output:
found 3 vulnerabilities (1 moderate, 2 high)
high Prototype Pollution in lodash
Package: lodash
Current version: 4.17.11
Patched in: >=4.17.21
Run `npm audit fix` to resolve
In 2025, attackers published 454,648 malicious npm packages in a single year, with 99% of all open source malware now targeting the npm ecosystem (Sonatype, 2026). npm audit won't catch intentionally malicious packages, but it catches the known CVEs — and that's a lot of your attack surface.
5. pip-audit — Python Dependency Scanning
The Python equivalent of npm audit. It checks your installed packages against the PyPI Advisory Database and OSV.
# Install
pip install pip-audit
# Audit your current environment
pip-audit
# Audit from a requirements file
pip-audit -r requirements.txt
# Audit with a specific output format
pip-audit --format json -o pip-audit-report.json
# Auto-fix when possible
pip-audit --fix
Example output:
Name Version ID Fix Versions
---------- -------- ------------------- ------------
requests 2.25.1 GHSA-j8r2-6x86-q33q 2.31.0
jinja2 2.11.3 GHSA-g3rq-g295-4j3m 3.1.3
If you're using a virtual environment (and you should be), run pip-audit inside it so it checks exactly what your app is using.
6. Trivy — Container and Infrastructure Scanning
If you're deploying with Docker, Trivy is essential. It scans container images for OS-level CVEs, application dependency vulnerabilities, exposed secrets, and infrastructure misconfigurations.
Install:
# macOS
brew install aquasecurity/trivy/trivy
# Linux
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Or use Docker
docker pull aquasec/trivy
Run it:
# Scan a Docker image
trivy image myapp:latest
# Scan only HIGH and CRITICAL vulnerabilities
trivy image --severity HIGH,CRITICAL myapp:latest
# Scan your local filesystem
trivy fs .
# Scan and output as SARIF for GitHub Advanced Security
trivy image --format sarif --output trivy-results.sarif myapp:latest
# Scan for secrets in an image
trivy image --scanners secret myapp:latest
Example output:
myapp:latest (ubuntu 22.04)
Total: 5 (HIGH: 3, CRITICAL: 2)
┌──────────────────────┬────────────────┬──────────┬────────────────────┐
│ Library │ Vulnerability │ Severity │ Fixed Version │
├──────────────────────┼────────────────┼──────────┼────────────────────┤
│ openssl │ CVE-2024-4603 │ HIGH │ 3.0.14-1ubuntu2 │
│ libexpat1 │ CVE-2024-45492 │ CRITICAL │ 2.5.0-1ubuntu0.1 │
└──────────────────────┴────────────────┴──────────┴────────────────────┘
Trivy is especially powerful for catching vulnerabilities that live in your base image — the Ubuntu or Alpine layer that your app sits on top of — which no application-level scanner will ever see.
7. TruffleHog and Gitleaks — Secret Detection
These two tools scan your git history for secrets: API keys, passwords, tokens, private keys. The critical insight is that they scan your entire commit history — meaning secrets you deleted two years ago are still findable in git.
TruffleHog
# Install
curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin
# Scan your current repository (full history)
trufflehog git file://.
# Scan only verified (confirmed-active) secrets
trufflehog git file://. --only-verified
# Scan a remote GitHub repo
trufflehog github --repo https://github.com/yourname/yourrepo
# Scan since last commit only (good for CI/pre-push hook)
trufflehog git file://. --since-commit HEAD --fail
Gitleaks
Gitleaks has the highest recall rate (88%) in independent benchmarks — meaning it finds the most secrets while TruffleHog specializes in verifying whether found secrets are still live.
# Install
brew install gitleaks # macOS
# Or download from: https://github.com/gitleaks/gitleaks/releases
# Scan the current repo
gitleaks detect --source .
# Scan with verbose output
gitleaks detect --source . --verbose
# Scan and output report
gitleaks detect --source . --report-format json --report-path gitleaks-report.json
# Pre-commit hook mode (fast, only new changes)
gitleaks protect --staged
Use both: TruffleHog to verify which found secrets are still active; Gitleaks for its broad detection coverage. When Luke Marshall scanned 5.6 million GitLab repositories in 2025, he found that roughly 1 in every 1,060 repos contained valid GCP credentials. That's not a hypothetical risk — it's a statistical certainty at scale.
8. OWASP ZAP — Dynamic Web Application Scanning
All the tools above are static — they analyze your code without running it. OWASP ZAP is different: it's a dynamic scanner that actually attacks your running application to find real exploitable vulnerabilities. Think of it as a safe, automated penetration tester.
Install and run a baseline scan:
# Run via Docker (easiest approach)
docker pull ghcr.io/zaproxy/zaproxy:stable
# Baseline scan against a running app
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
-t http://localhost:3000
# Full scan (more thorough, takes longer)
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-full-scan.py \
-t http://localhost:3000
# Generate HTML report
docker run -v $(pwd):/zap/wrk/:rw \
-t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
-t http://localhost:3000 \
-r zap-report.html
ZAP will test for XSS, SQL injection, security headers, CSRF, and dozens of other issues against your actual running app. For vibe coders deploying web apps, run this before any major release.
Putting It All Together: A Pre-Deploy Security Script
Here's a shell script that runs the static analysis tools in sequence. Save it as security-check.sh in your project root:
#!/bin/bash
# security-check.sh — Run before every deployment
set -e
echo "=== Security Scan Starting ==="
# Secret detection (run first — critical if found)
echo "\n[1/5] Scanning for secrets with Gitleaks..."
gitleaks detect --source . --no-banner || { echo "SECRETS FOUND — fix before deploying!"; exit 1; }
# Dependency vulnerabilities
if [ -f "package.json" ]; then
echo "\n[2/5] Auditing npm dependencies..."
npm audit --audit-level=high
fi
if [ -f "requirements.txt" ]; then
echo "\n[2/5] Auditing Python dependencies..."
pip-audit -r requirements.txt
fi
# SAST scanning
echo "\n[3/5] Running Semgrep SAST..."
semgrep --config=auto . --error
# Python-specific
if [ -f "requirements.txt" ]; then
echo "\n[4/5] Running Bandit..."
bandit -r . -l -i --exclude ./tests,./venv
fi
# Container scanning
if [ -f "Dockerfile" ]; then
echo "\n[5/5] Scanning Docker image with Trivy..."
trivy image --severity HIGH,CRITICAL --exit-code 1 $(basename $(pwd)):latest
fi
echo "\n=== Security Scan Complete ==="
Make it executable and wire it into your workflow:
chmod +x security-check.sh
./security-check.sh
What These Tools Don't Catch
Be honest about limitations:
- Business logic flaws — a scanner can't know that your discount code should only be used once
- Brand-new malicious packages —
npm auditonly knows about reported CVEs; September 2025's Shai-Hulud worm was missed bynpm auditbecause it was a fresh supply chain attack, not a known CVE - Authentication design errors — a scanner won't tell you your JWT secret is too short or your session expiry is 30 days
- Configuration drift — production environment variables that were secure at deploy time but rotated without updating the app
Automatic scanners are a floor, not a ceiling. They catch the obvious, repeatable mistakes — and that's enormously valuable.
Action Checklist
Run these today, in order:
- Run Gitleaks on your repo right now:
gitleaks detect --source . --verbose - Run npm audit or pip-audit on your dependencies
- Install Semgrep and run
semgrep --config=auto .on your codebase - Run Bandit if you have a Python project:
bandit -r . -l -i - Add ESLint security plugin to your JavaScript/TypeScript project
- Run Trivy if you're deploying containers:
trivy image myapp:latest - Run OWASP ZAP baseline scan against your staging environment
- Save the
security-check.shscript to your project and commit it - Add a pre-commit hook that runs Gitleaks:
gitleaks protect --staged - Block deployment if any scanner returns HIGH/CRITICAL findings
Ask The Guild
Community prompt: Which of these tools did you run first, and what did it find? Share your results in the Guild forum — even (especially) if it found something embarrassing. The best learning happens when we're honest about what we missed. Did Semgrep catch a SQL injection? Did Gitleaks find an old API key in your history? Tell us what tool, what it found, and how you fixed it. Your story might save someone else's project.
Tom Hundley is a software architect with 25 years of experience. He has been teaching developers — and now vibe coders — how to build things that last. This is Part 21 of the 30-part Security First series.
Sources: TruffleHog GitLab Scan Research | Snyk State of Secrets 2026 | npm Security Vulnerabilities 2026 | DeepStrike Vulnerability Statistics 2025