Static security scanner for AI-generated web app code. Finds hardcoded secrets, injection risks, CORS misconfigs and more.
Project description
security-scan
Static security scanner purpose-built for AI-generated web app code.
AI code generators (Lovable, Bolt, v0, Cursor, Copilot) frequently produce code with hardcoded secrets, missing auth guards, SQL injection patterns, and CORS misconfigs. This scanner catches those before they hit production.
Zero dependencies. Pure Python stdlib.
Quick start
# Clone and install
git clone https://github.com/nometria/security-scanner
cd security-scanner
pip install -e .
# Scan your project
security-scan ./my-app
# Scan a directory and output JSON
security-scan ./my-app --format json
# Scan the included example file
security-scan examples/ --no-color
Rules
| Rule | Severity | Catches |
|---|---|---|
| SEC-001 | ๐ด CRITICAL | Hardcoded API keys, tokens, passwords, JWT secrets |
| SEC-002 | ๐ HIGH | .env file committed without .gitignore entry |
| SEC-003 | ๐ HIGH | Dangerous eval() / exec() usage |
| SEC-004 | ๐ HIGH | SQL injection (string interpolation in queries) |
| SEC-005 | ๐ HIGH | Missing auth middleware on API routes |
| SEC-006 | ๐ก MEDIUM | CORS wildcard * in production code |
| SEC-007 | ๐ต LOW | HTTP (not HTTPS) hardcoded URLs |
| SEC-008 | ๐ HIGH | Exposed admin routes without auth |
| SEC-009 | ๐ HIGH | Auth tokens stored in localStorage (XSS risk) |
| SEC-010 | ๐ก MEDIUM | process.env values logged to console |
| SEC-011 | ๐ด CRITICAL | Supabase service_role key used client-side |
| SEC-012 | ๐ก MEDIUM | Dependency confusion risk in package.json |
Install
pip install security-scan # PyPI (coming soon)
# From source:
git clone https://github.com/nometria/security-scanner
cd security-scanner
pip install -e .
Usage
# Scan current directory
security-scan .
# Scan a specific project
security-scan ./my-vite-app
# JSON output (for CI pipelines)
security-scan . --format json --output report.json
# SARIF output (GitHub Code Scanning)
security-scan . --format sarif --output results.sarif
# Markdown report
security-scan . --format markdown --output security-report.md
# Only fail on critical issues (default: high+)
security-scan . --fail-on critical
# No color (CI-friendly)
security-scan . --no-color
# Watch mode โ re-scans on file changes (polls every 2s)
security-scan . --watch
# Watch with JSON output
security-scan ./my-app --watch --format json
Watch mode
The --watch flag monitors your project for file changes and re-runs the scan automatically.
Uses lightweight mtime polling (every 2 seconds) with zero extra dependencies -- no watchdog needed.
On each change only the modified files are re-scanned (incremental), while the full findings list is kept up to date. The terminal is cleared and refreshed so you always see a clean report.
$ security-scan ./my-app --watch
[14:31:55] Full scan
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SECURITY SCAN โ 12 files scanned, 3 findings
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
...
Watching for changes... (Ctrl+C to stop)
[14:32:07] Re-scanned 1 changed file(s)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SECURITY SCAN โ 13 files scanned, 2 findings
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
...
Watching for changes... (Ctrl+C to stop)
In watch mode the process runs continuously and does not exit on findings, making it suitable for IDE integration and development workflows.
IDE integration
Run the scanner in a side terminal while you code -- findings update live as you save files.
VS Code -- open a terminal pane (Ctrl+`` ) and run:
security-scan --watch .
Split the terminal so the scan output is always visible beside your editor.
JetBrains (WebStorm / PyCharm) -- add an External Tool or Run Configuration:
- Program:
security-scan - Arguments:
--watch $ProjectFileDir$ - Working directory:
$ProjectFileDir$
Neovim / tmux -- keep a tmux split running:
tmux split-window -h 'security-scan --watch .'
CI / pre-commit -- for one-shot scans in CI, omit --watch:
security-scan . --format sarif --output results.sarif --fail-on high
GitHub Action
Use the composite GitHub Action for a turnkey CI integration with PR comments, SARIF upload, and configurable failure thresholds.
# .github/workflows/security-scan.yml
name: Security Scan
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
pull-requests: write
security-events: write
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nometria/security-scanner@main
with:
target_dir: '.'
format: 'text'
fail_on_findings: 'true'
fail_on: 'high'
post_comment: 'true'
sarif_upload: 'true'
Action inputs
| Input | Default | Description |
|---|---|---|
target_dir |
. |
Directory to scan |
format |
text |
Output format: text, json, or markdown |
fail_on_findings |
true |
Fail the action if findings meet the severity threshold |
fail_on |
high |
Minimum severity to fail: critical, high, medium, low, any |
post_comment |
true |
Post results as a PR comment (pull_request events only) |
sarif_upload |
true |
Upload SARIF results to GitHub Code Scanning |
python_version |
3.11 |
Python version to use |
Action outputs
| Output | Description |
|---|---|
passed |
true if no findings at or above the fail threshold |
findings_count |
Total number of findings |
critical_count |
Number of critical findings |
report |
Full scan report in the requested format |
See examples/security-scan-action.yml for a complete workflow example.
Manual pip-based workflow
If you prefer not to use the composite action, you can install and run directly:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install ai-security-scan
- run: security-scan . --format sarif --output results.sarif --fail-on high
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: results.sarif
Use as a library
from security_scanner import scan_project
result = scan_project("./my-app")
print(f"Passed: {result.passed}")
print(f"Critical: {result.critical_count}")
for finding in result.findings:
print(f"[{finding.severity}] {finding.rule_id}: {finding.file}:{finding.line}")
print(f" {finding.message}")
print(f" Fix: {finding.fix}")
Add custom rules
from security_scanner.scanner import Finding, HIGH
def check_no_http_fetch(path, rel, lines):
findings = []
for i, line in enumerate(lines, 1):
if 'fetch("http://' in line:
findings.append(Finding(
rule_id="CUSTOM-001", severity=HIGH,
file=rel, line=i,
message="fetch() called with HTTP URL",
fix="Use HTTPS for all fetch calls."
))
return findings
# Register in scanner.py scan_project() loop
Immediate next steps
Publish to PyPI:Donepip install ai-security-scan- Publish to npm as
npx security-scanwrapper Submit to GitHub Marketplace as an ActionDone (action.yml)- Add SEC-005 (missing auth middleware) โ requires AST parsing
AddDone (--watchmode for IDE integration--watchflag with incremental re-scan)
Commercial viability
- Open source it โ "security scanner for AI-generated code" is high SEO value
- Drive inbound: every AI app builder user is a potential Nometria customer
- Upsell: "scan found issues โ let us help you fix and self-host securely"
- GitHub App: auto-scan every PR, post findings as PR review comments โ $9โ19/mo/repo
Example output
Running security-scan examples/ --no-color against the included examples/vulnerable.js:
Scanning /tmp/ownmy-releases/security-scanner/examples ...
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SECURITY SCAN โ 1 files scanned, 5 findings
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ด [CRITICAL] SEC-001
File : vulnerable.js:4
Issue : Hardcoded API key detected
Code : const API_KEY = "sk-live-abc123def456ghi789jkl012mno345pqr678";
Fix : Move to environment variables. Never commit secrets to source control.
๐ด [CRITICAL] SEC-001
File : vulnerable.js:5
Issue : Hardcoded password detected
Code : const DB_PASSWORD = "SuperSecret123!";
Fix : Move to environment variables. Never commit secrets to source control.
๐ [HIGH] SEC-003
File : vulnerable.js:10
Issue : Dangerous eval/exec usage โ potential code injection
Code : return eval(input);
Fix : Avoid eval/exec with user input. Use JSON.parse() or safe alternatives.
๐ [HIGH] SEC-004
File : vulnerable.js:15
Issue : Potential SQL injection โ string interpolation in query
Code : const query = `SELECT * FROM users WHERE id = ${userId}`;
Fix : Use parameterised queries: db.query('SELECT * FROM t WHERE id = $1', [id])
๐ [HIGH] SEC-004
File : vulnerable.js:20
Issue : Potential SQL injection โ string interpolation in query
Code : const sql = "SELECT * FROM products WHERE name = '" + term + "'";
Fix : Use parameterised queries: db.query('SELECT * FROM t WHERE id = $1', [id])
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Critical: 2 | High: 3 | Medium: 0 | Low: 0
Overall: โ FAIL
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ai_security_scan-0.2.0.tar.gz.
File metadata
- Download URL: ai_security_scan-0.2.0.tar.gz
- Upload date:
- Size: 17.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb7f92d8511de4b63ae97b1da905f5d78bb1927e95a4efe9c4330745b09392d5
|
|
| MD5 |
d0af9f8be5ddb32102048eefb319d536
|
|
| BLAKE2b-256 |
129fd08b093ae10083769e7ca792ae76e2feef0d374bb46d028d0963ed9154d2
|
File details
Details for the file ai_security_scan-0.2.0-py3-none-any.whl.
File metadata
- Download URL: ai_security_scan-0.2.0-py3-none-any.whl
- Upload date:
- Size: 15.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d68596318e295c5e50b9cfaaff641087af6903b9ed7736acc4116737cf8280a
|
|
| MD5 |
88df5ecb0cea7458c82f4ae4a34487d8
|
|
| BLAKE2b-256 |
33c5c8b9af694668ad5c294b44bb29f6f45d6ef5c2100560083c0afe9a5e5c15
|