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, 200+ 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 eight languages — Python, JavaScript, Go, Java, Ruby, PHP, C#, and Kotlin — 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.GETviews.pyqueries.pycursor.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
src/auth/login.js · 2 issues
CRITICALUntrusted 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
HIGHHardcoded 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
3issues1,204 files · 0.14s
2 critical1 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
41 rules
Flask / Django
43 rules
Gin / net/http
26 rules
Rails / Ruby
17 rules
Spring / Java
18 rules
PHP / Laravel
15 rules
Rust
12 rules
C# / .NET
16 rules
Kotlin / Ktor
13 rules
Swift / iOS
14 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. Loads ~98% of the public Semgrep/OpenGrep registry, parity-tested in CI.

Semgrep compatibility

Load your existing rules with --rules — foxguard loads ~98% of the public registry, parity-tested in CI.

patternpattern-regexpattern-eitherpattern-notpattern-not-regexpattern-insidepattern-not-insidepatterns (AND)metavariable-regexpaths.include/excludeFull 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

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

JavaScript / TypeScript41
js/express-cookie-no-httponlymediumCWE-1004
js/express-cookie-no-samesitemediumCWE-352
js/express-cookie-no-securemediumCWE-614
js/express-direct-response-writehighCWE-79
js/express-no-hardcoded-session-secrethighCWE-798
js/express-session-resave-truemediumCWE-384
js/express-session-saveuninitialized-truemediumCWE-359
js/hardcoded-crypto-algorithmlowCWE-327
js/jwt-decode-without-verifyhighCWE-347
js/jwt-hardcoded-secrethighCWE-798
js/jwt-ignore-expirationhighCWE-613
js/jwt-none-algorithmhighCWE-347
js/jwt-verify-missing-algorithmshighCWE-347
js/no-command-injectioncriticalCWE-78
js/no-cors-starmediumCWE-942
js/no-document-writehighCWE-79
js/no-evalcriticalCWE-95
js/no-hardcoded-secrethighCWE-798
js/no-open-redirectmediumCWE-601
js/no-path-traversalhighCWE-22
js/no-prototype-pollutionhighCWE-1321
js/no-sql-injectioncriticalCWE-89
js/no-ssrfhighCWE-918
js/no-unsafe-deserializationcriticalCWE-502
js/no-unsafe-format-stringmediumCWE-134
js/no-unsafe-regexmediumCWE-1333
js/no-weak-cryptomediumCWE-327
js/no-xss-innerhtmlhighCWE-79
js/pq-ready-cryptolow
js/pq-vulnerable-cryptohighCWE-327
js/taint-command-injectioncriticalCWE-78
js/taint-evalcriticalCWE-95
js/taint-ldap-injectionhighCWE-90
js/taint-log-injectionmediumCWE-117
js/taint-nosql-injectionhighCWE-943
js/taint-sql-injectioncriticalCWE-89
js/taint-ssrfhighCWE-918
js/taint-ssticriticalCWE-1336
js/taint-xpath-injectionhighCWE-643
js/taint-xss-innerhtmlhighCWE-79
js/taint-xxehighCWE-611
Python43
py/csrf-cookie-httponly-disabledmediumCWE-1004
py/csrf-cookie-samesite-disabledmediumCWE-352
py/csrf-cookie-secure-disabledmediumCWE-614
py/csrf-exempthighCWE-352
py/django-allowed-hosts-wildcardmediumCWE-346
py/django-secret-key-hardcodedhighCWE-798
py/flask-debug-modehighCWE-489
py/flask-secret-key-hardcodedhighCWE-798
py/hardcoded-crypto-algorithmlowCWE-327
py/jwt-hardcoded-secrethighCWE-798
py/jwt-no-verifycriticalCWE-347
py/no-command-injectioncriticalCWE-78
py/no-cors-starmediumCWE-942
py/no-debug-truemediumCWE-489
py/no-evalcriticalCWE-95
py/no-hardcoded-secrethighCWE-798
py/no-open-redirectmediumCWE-601
py/no-path-traversalhighCWE-22
py/no-picklehighCWE-502
py/no-sql-injectioncriticalCWE-89
py/no-ssrfhighCWE-918
py/no-weak-cryptomediumCWE-327
py/no-yaml-loadhighCWE-502
py/pq-ready-cryptolow
py/pq-vulnerable-cryptohighCWE-327
py/secure-ssl-redirect-disabledmediumCWE-319
py/session-cookie-httponly-disabledmediumCWE-1004
py/session-cookie-samesite-disabledmediumCWE-352
py/session-cookie-secure-disabledmediumCWE-614
py/taint-command-injectioncriticalCWE-78
py/taint-evalcriticalCWE-95
py/taint-ldap-injectionhighCWE-90
py/taint-log-injectionmediumCWE-117
py/taint-nosql-injectionhighCWE-943
py/taint-pickle-deserializationcriticalCWE-502
py/taint-sql-injectioncriticalCWE-89
py/taint-ssrfhighCWE-918
py/taint-ssticriticalCWE-1336
py/taint-xpath-injectionhighCWE-643
py/taint-xxehighCWE-611
py/taint-yaml-loadcriticalCWE-502
py/wtf-csrf-check-default-disabledhighCWE-352
py/wtf-csrf-disabledhighCWE-352
Go26
go/cookie-missing-httponlymediumCWE-1004
go/cookie-missing-securemediumCWE-614
go/gin-no-trusted-proxiesmediumCWE-346
go/insecure-tls-skip-verifyhighCWE-295
go/jwt-hardcoded-secrethighCWE-798
go/jwt-no-verifycriticalCWE-347
go/math-random-usedmediumCWE-338
go/missing-ssl-minversionmediumCWE-326
go/net-http-no-timeoutmediumCWE-400
go/no-command-injectioncriticalCWE-78
go/no-hardcoded-secrethighCWE-798
go/no-sql-injectioncriticalCWE-89
go/no-ssrfhighCWE-918
go/no-unsafe-deserializationhighCWE-502
go/no-weak-cryptomediumCWE-327
go/pq-ready-cryptolow
go/pq-vulnerable-cryptohighCWE-327
go/taint-command-injectioncriticalCWE-78
go/taint-ldap-injectionhighCWE-90
go/taint-log-injectionmediumCWE-117
go/taint-nosql-injectionhighCWE-943
go/taint-path-traversalhighCWE-22
go/taint-sql-injectioncriticalCWE-89
go/taint-ssrfhighCWE-918
go/taint-ssticriticalCWE-1336
go/taint-xpath-injectionhighCWE-643
Ruby17
rb/no-command-injectioncriticalCWE-78
rb/no-csrf-skiphighCWE-352
rb/no-evalcriticalCWE-95
rb/no-hardcoded-secrethighCWE-798
rb/no-html-safehighCWE-79
rb/no-mass-assignmenthighCWE-915
rb/no-open-redirecthighCWE-601
rb/no-path-traversalhighCWE-22
rb/no-sql-injectioncriticalCWE-89
rb/no-ssrfhighCWE-918
rb/no-unsafe-deserializationcriticalCWE-502
rb/no-weak-cryptomediumCWE-327
rb/taint-command-injectioncriticalCWE-78
rb/taint-open-redirectmediumCWE-601
rb/taint-sql-injectioncriticalCWE-89
rb/taint-unsafe-deserializationcriticalCWE-502
rb/taint-xsshighCWE-79
Java18
java/hardcoded-crypto-algorithmlowCWE-327
java/no-command-injectioncriticalCWE-78
java/no-hardcoded-secrethighCWE-798
java/no-path-traversalhighCWE-22
java/no-sql-injectioncriticalCWE-89
java/no-ssrfhighCWE-918
java/no-unsafe-deserializationcriticalCWE-502
java/no-weak-cryptomediumCWE-327
java/no-xsshighCWE-79
java/no-xxehighCWE-611
java/pq-ready-cryptolow
java/pq-vulnerable-cryptohighCWE-327
java/spring-cors-permissivemediumCWE-942
java/spring-csrf-disabledhighCWE-352
java/taint-command-injectioncriticalCWE-78
java/taint-sql-injectioncriticalCWE-89
java/taint-ssrfhighCWE-918
java/taint-unsafe-deserializationcriticalCWE-502
PHP15
php/no-command-injectioncriticalCWE-78
php/no-evalcriticalCWE-95
php/no-extracthighCWE-621
php/no-file-inclusioncriticalCWE-98
php/no-hardcoded-secrethighCWE-798
php/no-preg-evalcriticalCWE-95
php/no-sql-injectioncriticalCWE-89
php/no-ssrfhighCWE-918
php/no-unserializecriticalCWE-502
php/no-weak-cryptomediumCWE-327
php/taint-command-injectioncriticalCWE-78
php/taint-file-inclusioncriticalCWE-98
php/taint-sql-injectioncriticalCWE-89
php/taint-unsafe-deserializationcriticalCWE-502
php/taint-xsshighCWE-79
Rust12
rs/no-command-injectioncriticalCWE-78
rs/no-hardcoded-secrethighCWE-798
rs/no-path-traversalmediumCWE-22
rs/no-sql-injectioncriticalCWE-89
rs/no-ssrfhighCWE-918
rs/no-unwrap-in-libmediumCWE-248
rs/no-weak-hashmediumCWE-328
rs/pq-ready-cryptolow
rs/pq-vulnerable-cryptohighCWE-327
rs/tls-verify-disabledhighCWE-295
rs/transmute-usagehighCWE-843
rs/unsafe-blockmediumCWE-676
C#16
cs/no-command-injectioncriticalCWE-78
cs/no-cors-starmediumCWE-942
cs/no-hardcoded-secrethighCWE-798
cs/no-ldap-injectionhighCWE-90
cs/no-path-traversalhighCWE-22
cs/no-sql-injectioncriticalCWE-89
cs/no-ssrfhighCWE-918
cs/no-unsafe-deserializationcriticalCWE-502
cs/no-weak-cryptomediumCWE-327
cs/no-xxehighCWE-611
csharp/taint-command-injectioncriticalCWE-78
csharp/taint-open-redirectmediumCWE-601
csharp/taint-sql-injectioncriticalCWE-89
csharp/taint-unsafe-loadcriticalCWE-502
csharp/taint-xsshighCWE-79
csharp/taint-xxehighCWE-611
Swift14
swift/no-command-injectioncriticalCWE-78
swift/no-eval-jscriticalCWE-95
swift/no-hardcoded-secrethighCWE-798
swift/no-insecure-keychainhighCWE-311
swift/no-insecure-transporthighCWE-319
swift/no-path-traversalhighCWE-22
swift/no-sql-injectioncriticalCWE-89
swift/no-ssrfhighCWE-918
swift/no-tls-disabledhighCWE-295
swift/no-weak-cryptomediumCWE-327
swift/taint-command-injectioncriticalCWE-78
swift/taint-js-injectionhighCWE-79
swift/taint-nsexpression-injectionhighCWE-95
swift/taint-sql-injectioncriticalCWE-89
Kotlin13
kt/no-command-injectioncriticalCWE-78
kt/no-cors-starmediumCWE-942
kt/no-evalcriticalCWE-94
kt/no-hardcoded-secrethighCWE-798
kt/no-path-traversalhighCWE-22
kt/no-sql-injectioncriticalCWE-89
kt/no-ssrfhighCWE-918
kt/no-unsafe-deserializationcriticalCWE-502
kt/no-weak-cryptomediumCWE-327
kt/no-xxehighCWE-611
kt/taint-command-injectioncriticalCWE-78
kt/taint-sql-injectioncriticalCWE-89
kt/taint-ssrfhighCWE-918
Solidity3
solidity/taint-arbitrary-delegatecallcriticalCWE-829
solidity/taint-unchecked-callhighCWE-829
solidity/taint-unprotected-selfdestructcriticalCWE-284
Haskell6
semgrep/cardano-haskell/cbor-decoder-edgehighCWE-248
semgrep/cardano-haskell/ffi-foreign-importcriticalCWE-125
semgrep/cardano-haskell/ffi-pointer-offsetcriticalCWE-787
semgrep/cardano-haskell/lazy-eval-doshighCWE-400
semgrep/cardano-haskell/partial-functionhighCWE-248
semgrep/cardano-haskell/unsafe-escapecriticalCWE-704
Nginx2
config/nginx-pq-ready-tlslow
config/nginx-pq-vulnerable-tlsmediumCWE-327
Apache2
config/apache-pq-ready-tlslow
config/apache-pq-vulnerable-tlsmediumCWE-327
HAProxy2
config/haproxy-pq-ready-tlslow
config/haproxy-pq-vulnerable-tlsmediumCWE-327
Dockerfile1
config/dockerfile-insecure-tls-envhighCWE-295
Manifest9
manifest/cargo-pq-ready-deplow
manifest/cargo-pq-vulnerable-dephighCWE-327
manifest/npm-pq-vulnerable-dephighCWE-327
manifest/osv-vulnerable-dephighCWE-937
manifest/pip-pq-ready-deplow
manifest/pip-pq-vulnerable-dephighCWE-327
manifest/pipfile-pq-vulnerable-dephighCWE-327
manifest/pnpm-pq-vulnerable-dephighCWE-327
manifest/poetry-pq-vulnerable-dephighCWE-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.