Security scanner
as fast as a linter

174 built-in rules across 10 languages. Cross-file taint tracking for Python, JavaScript, and Go. Single Rust binary, sub-second scans.

terminal
foxguard v0.6.2
src/auth/login.js · 2 issues
CRITICAL Untrusted input reaches db.query — SQL injection
js/taint-sql-injection (CWE-89) line 14:5
db.query("SELECT * FROM users WHERE id = '" + req.param...
Fix: Use parameterized queries
HIGH Hardcoded JWT secret
js/jwt-hardcoded-secret (CWE-798) line 8:1
app/views.py · 1 issue
CRITICAL request.GET reaches cursor.execute
py/taint-sql-injection (CWE-89) line 52:12
source → views.py:51 django.request.GET
sink → views.py:52 cursor.execute (via cross-file call)
Fix: Use parameterized queries
3 issues 1,204 files · 0.14s
2 critical 1 high

Cross-file taint analysis

Traces untrusted input across file boundaries.

Source in one file, sink in another — connected 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 shows the full path from source to sink with file and line references.

Fix suggestions

Every taint finding includes a concrete remediation with safe code patterns.

Branch diffing

foxguard diff main shows only findings your branch introduces.

Fast enough to leave on

Security scanning that takes minutes gets turned off.

foxguard finishes before your editor saves.

express
22x 141 files
foxguard
0.276s
Semgrep
6.1s
flask
20x 83 files
foxguard
0.333s
Semgrep
6.5s
gin
10x 99 files
foxguard
0.499s
Semgrep
5.0s

foxguard built-ins vs Semgrep auto · ./benchmarks/run.sh to reproduce

Framework-aware by default

Built-in rules for the frameworks teams actually use.

No rule files to download, no config to write.

Express / Node
38 rules
Flask / Django
40 rules
Gin / net/http
20 rules
Rails / Ruby
12 rules
Spring / Java
11 rules
PHP / Laravel
10 rules
Rust
10 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 existing rules with --rules. Focused subset, 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

Rules

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

JavaScript / TypeScript 38
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/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/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 40
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/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/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 20
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/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/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 11
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/spring-cors-permissive medium CWE-942
java/spring-csrf-disabled high CWE-352
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 10
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/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

Try it on your codebase

One command. No config. No signup.