GitHub App is live. PR scans without wiring CI by hand. Install it ->

An extremely fast security scanner, written in Rust.

Cross-file taint tracking, 196 built-in rules, and a post-quantum crypto audit in a single binary. Free and open source.

Scans in milliseconds

Written in Rust, with no database to build.

Scanning express, from scratch. · 141 files · 19x faster
foxguard
0.000s
Semgrep
0.00s
OpenGrep
0.00s
Scanning flask, from scratch. · 83 files · 20x faster
foxguard
0.000s
Semgrep
0.00s
OpenGrep
0.00s
Scanning gin, from scratch. · 99 files · 15x faster
foxguard
0.000s
Semgrep
0.00s
OpenGrep
0.00s

foxguard 0.8.1 built-ins vs Semgrep 1.156 & OpenGrep 1.22 (--config auto, identical findings) · median of 3 runs, Apple Silicon · bars animate at true measured wall-clock time · full comparison vs CodeQL, Snyk & SonarQube →

Cross-file taint analysis

foxguard tracks untrusted input across files in Python, JavaScript, and Go, linking a source in one file to a sink in another in 0.03 seconds.

views.py
from . import queries

def search(request):
    name = request.GET["name"]
    return queries.run_query(name)
queries.py
def run_query(name):
    cur = db.cursor()
    cur.execute(
        "SELECT * FROM users"
        " WHERE name = '" + name + "'"
    )
request.GET views.py queries.py cursor.execute

Dataflow traces

--explain prints the full source-to-sink path, file and line, plus a fix.

Confidence-scored

Findings are ranked by dataflow depth, so the most certain ones surface first.

Branch diffing

foxguard diff main shows only findings your branch introduces.

Built for your terminal

Readable scan output, plus an interactive TUI. Run foxguard tui . to browse findings, read dataflow traces, and dismiss false positives.

terminal
foxguard v0.7.0
src/auth/login.js · 2 issues
CRITICAL Untrusted input reaches `db.query`
js/taint-sql-injection (CWE-89) line 14:5
db.query("SELECT * FROM users WHERE id = '" + req.params.id + "'")
Fix: Use parameterized queries
HIGH Hardcoded JWT secret
js/jwt-hardcoded-secret (CWE-798) line 8:1
const JWT_SECRET = "super-secret-prod-key"
app/views.py · 1 issue
CRITICAL `request.GET` reaches `cursor.execute`
py/taint-sql-injection (CWE-89) line 52:12
cursor.execute("SELECT * FROM users WHERE id = '%s'" % user_id)
Fix: Use parameterized queries
3 issues 1,204 files · 0.14s
2 critical 1 high
foxguard tui .
foxguard TUI showing the findings list on the left and the full dataflow detail for a selected SQL injection on the right
$ npx foxguard tui .

Framework-aware by default

Built-in rules understand Express, Django, Flask, and Spring, so a safe idiom won't raise a false alert.

Express / Node
40 rules
Flask / Django
42 rules
Gin / net/http
25 rules
Rails / Ruby
12 rules
Spring / Java
17 rules
PHP / Laravel
10 rules
Rust
11 rules
C# / .NET
10 rules
Kotlin / Ktor
13 rules
Swift / iOS
10 rules

Cross-file taint tracking

Trace untrusted input across file boundaries. Source in one file, sink in another — the engine connects them.

Branch diffing

foxguard diff main shows only new findings your branch introduces. No noise from existing code.

PR review comments

--github-pr posts findings as inline review comments directly on pull requests.

Fix suggestions

Every taint finding includes a concrete fix with safe code patterns. --explain shows full dataflow traces.

Secrets scanning

Detect leaked credentials and private keys with redacted output in the same tool.

Semgrep YAML bridge

Load existing Semgrep/OpenGrep rules with --rules. Focused subset, parity-tested in CI.

Semgrep compatibility

Load your existing rules with --rules. Parity-tested in CI.

pattern pattern-regex pattern-either pattern-not pattern-not-regex pattern-inside pattern-not-inside patterns (AND) metavariable-regex paths.include/exclude Full Semgrep syntax

Post-quantum crypto audit, built in

One command flags RSA, ECDSA, ECDH, DH, and DSA across five languages, web-server configs, and six lockfile formats.

$ foxguard pqc .

CNSA 2.0 deadlines

Every finding carries its CNSA 2.0 migration deadline. Know what moves, and by when.

Migration readiness

A readiness score: how exposed you are, and where to start.

CycloneDX CBOM

foxguard pqc . --format cbom exports a CycloneDX cryptography bill of materials.

Rules

201 built-in rules, each mapped to a CWE.

JavaScript / TypeScript 40
js/express-cookie-no-httponly medium CWE-1004
js/express-cookie-no-samesite medium CWE-352
js/express-cookie-no-secure medium CWE-614
js/express-direct-response-write high CWE-79
js/express-no-hardcoded-session-secret high CWE-798
js/express-session-resave-true medium CWE-384
js/express-session-saveuninitialized-true medium CWE-359
js/hardcoded-crypto-algorithm low CWE-327
js/jwt-decode-without-verify high CWE-347
js/jwt-hardcoded-secret high CWE-798
js/jwt-ignore-expiration high CWE-613
js/jwt-none-algorithm high CWE-347
js/jwt-verify-missing-algorithms high CWE-347
js/no-command-injection critical CWE-78
js/no-cors-star medium CWE-942
js/no-document-write high CWE-79
js/no-eval critical CWE-95
js/no-hardcoded-secret high CWE-798
js/no-open-redirect medium CWE-601
js/no-path-traversal high CWE-22
js/no-prototype-pollution high CWE-1321
js/no-sql-injection critical CWE-89
js/no-ssrf high CWE-918
js/no-unsafe-deserialization critical CWE-502
js/no-unsafe-format-string medium CWE-134
js/no-unsafe-regex medium CWE-1333
js/no-weak-crypto medium CWE-327
js/no-xss-innerhtml high CWE-79
js/pq-vulnerable-crypto high CWE-327
js/taint-command-injection critical CWE-78
js/taint-eval critical CWE-95
js/taint-ldap-injection high CWE-90
js/taint-log-injection medium CWE-117
js/taint-nosql-injection high CWE-943
js/taint-sql-injection critical CWE-89
js/taint-ssrf high CWE-918
js/taint-ssti critical CWE-1336
js/taint-xpath-injection high CWE-643
js/taint-xss-innerhtml high CWE-79
js/taint-xxe high CWE-611
Python 42
py/csrf-cookie-httponly-disabled medium CWE-1004
py/csrf-cookie-samesite-disabled medium CWE-352
py/csrf-cookie-secure-disabled medium CWE-614
py/csrf-exempt high CWE-352
py/django-allowed-hosts-wildcard medium CWE-346
py/django-secret-key-hardcoded high CWE-798
py/flask-debug-mode high CWE-489
py/flask-secret-key-hardcoded high CWE-798
py/hardcoded-crypto-algorithm low CWE-327
py/jwt-hardcoded-secret high CWE-798
py/jwt-no-verify critical CWE-347
py/no-command-injection critical CWE-78
py/no-cors-star medium CWE-942
py/no-debug-true medium CWE-489
py/no-eval critical CWE-95
py/no-hardcoded-secret high CWE-798
py/no-open-redirect medium CWE-601
py/no-path-traversal high CWE-22
py/no-pickle high CWE-502
py/no-sql-injection critical CWE-89
py/no-ssrf high CWE-918
py/no-weak-crypto medium CWE-327
py/no-yaml-load high CWE-502
py/pq-vulnerable-crypto high CWE-327
py/secure-ssl-redirect-disabled medium CWE-319
py/session-cookie-httponly-disabled medium CWE-1004
py/session-cookie-samesite-disabled medium CWE-352
py/session-cookie-secure-disabled medium CWE-614
py/taint-command-injection critical CWE-78
py/taint-eval critical CWE-95
py/taint-ldap-injection high CWE-90
py/taint-log-injection medium CWE-117
py/taint-nosql-injection high CWE-943
py/taint-pickle-deserialization critical CWE-502
py/taint-sql-injection critical CWE-89
py/taint-ssrf high CWE-918
py/taint-ssti critical CWE-1336
py/taint-xpath-injection high CWE-643
py/taint-xxe high CWE-611
py/taint-yaml-load critical CWE-502
py/wtf-csrf-check-default-disabled high CWE-352
py/wtf-csrf-disabled high CWE-352
Go 25
go/cookie-missing-httponly medium CWE-1004
go/cookie-missing-secure medium CWE-614
go/gin-no-trusted-proxies medium CWE-346
go/insecure-tls-skip-verify high CWE-295
go/jwt-hardcoded-secret high CWE-798
go/jwt-no-verify critical CWE-347
go/math-random-used medium CWE-338
go/missing-ssl-minversion medium CWE-326
go/net-http-no-timeout medium CWE-400
go/no-command-injection critical CWE-78
go/no-hardcoded-secret high CWE-798
go/no-sql-injection critical CWE-89
go/no-ssrf high CWE-918
go/no-unsafe-deserialization high CWE-502
go/no-weak-crypto medium CWE-327
go/pq-vulnerable-crypto high CWE-327
go/taint-command-injection critical CWE-78
go/taint-ldap-injection high CWE-90
go/taint-log-injection medium CWE-117
go/taint-nosql-injection high CWE-943
go/taint-path-traversal high CWE-22
go/taint-sql-injection critical CWE-89
go/taint-ssrf high CWE-918
go/taint-ssti critical CWE-1336
go/taint-xpath-injection high CWE-643
Ruby 12
rb/no-command-injection critical CWE-78
rb/no-csrf-skip high CWE-352
rb/no-eval critical CWE-95
rb/no-hardcoded-secret high CWE-798
rb/no-html-safe high CWE-79
rb/no-mass-assignment high CWE-915
rb/no-open-redirect high CWE-601
rb/no-path-traversal high CWE-22
rb/no-sql-injection critical CWE-89
rb/no-ssrf high CWE-918
rb/no-unsafe-deserialization critical CWE-502
rb/no-weak-crypto medium CWE-327
Java 17
java/hardcoded-crypto-algorithm low CWE-327
java/no-command-injection critical CWE-78
java/no-hardcoded-secret high CWE-798
java/no-path-traversal high CWE-22
java/no-sql-injection critical CWE-89
java/no-ssrf high CWE-918
java/no-unsafe-deserialization critical CWE-502
java/no-weak-crypto medium CWE-327
java/no-xss high CWE-79
java/no-xxe high CWE-611
java/pq-vulnerable-crypto high CWE-327
java/spring-cors-permissive medium CWE-942
java/spring-csrf-disabled high CWE-352
java/taint-command-injection critical CWE-78
java/taint-sql-injection critical CWE-89
java/taint-ssrf high CWE-918
java/taint-unsafe-deserialization critical CWE-502
PHP 10
php/no-command-injection critical CWE-78
php/no-eval critical CWE-95
php/no-extract high CWE-621
php/no-file-inclusion critical CWE-98
php/no-hardcoded-secret high CWE-798
php/no-preg-eval critical CWE-95
php/no-sql-injection critical CWE-89
php/no-ssrf high CWE-918
php/no-unserialize critical CWE-502
php/no-weak-crypto medium CWE-327
Rust 11
rs/no-command-injection critical CWE-78
rs/no-hardcoded-secret high CWE-798
rs/no-path-traversal medium CWE-22
rs/no-sql-injection critical CWE-89
rs/no-ssrf high CWE-918
rs/no-unwrap-in-lib medium CWE-248
rs/no-weak-hash medium CWE-328
rs/pq-vulnerable-crypto high CWE-327
rs/tls-verify-disabled high CWE-295
rs/transmute-usage high CWE-843
rs/unsafe-block medium CWE-676
C# 10
cs/no-command-injection critical CWE-78
cs/no-cors-star medium CWE-942
cs/no-hardcoded-secret high CWE-798
cs/no-ldap-injection high CWE-90
cs/no-path-traversal high CWE-22
cs/no-sql-injection critical CWE-89
cs/no-ssrf high CWE-918
cs/no-unsafe-deserialization critical CWE-502
cs/no-weak-crypto medium CWE-327
cs/no-xxe high CWE-611
Swift 10
swift/no-command-injection critical CWE-78
swift/no-eval-js critical CWE-95
swift/no-hardcoded-secret high CWE-798
swift/no-insecure-keychain high CWE-311
swift/no-insecure-transport high CWE-319
swift/no-path-traversal high CWE-22
swift/no-sql-injection critical CWE-89
swift/no-ssrf high CWE-918
swift/no-tls-disabled high CWE-295
swift/no-weak-crypto medium CWE-327
Kotlin 13
kt/no-command-injection critical CWE-78
kt/no-cors-star medium CWE-942
kt/no-eval critical CWE-94
kt/no-hardcoded-secret high CWE-798
kt/no-path-traversal high CWE-22
kt/no-sql-injection critical CWE-89
kt/no-ssrf high CWE-918
kt/no-unsafe-deserialization critical CWE-502
kt/no-weak-crypto medium CWE-327
kt/no-xxe high CWE-611
kt/taint-command-injection critical CWE-78
kt/taint-sql-injection critical CWE-89
kt/taint-ssrf high CWE-918
Nginx 1
config/nginx-pq-vulnerable-tls medium CWE-327
Apache 1
config/apache-pq-vulnerable-tls medium CWE-327
HAProxy 1
config/haproxy-pq-vulnerable-tls medium CWE-327
Dockerfile 1
config/dockerfile-insecure-tls-env high CWE-295
Manifest 7
manifest/cargo-pq-vulnerable-dep high CWE-327
manifest/npm-pq-vulnerable-dep high CWE-327
manifest/osv-vulnerable-dep high CWE-937
manifest/pip-pq-vulnerable-dep high CWE-327
manifest/pipfile-pq-vulnerable-dep high CWE-327
manifest/pnpm-pq-vulnerable-dep high CWE-327
manifest/poetry-pq-vulnerable-dep high CWE-327

Try it on your codebase

One command, no setup.

foxguard secrets . also catches leaked AWS, GitHub, Stripe, Slack, and private keys, redacted by default.