local-first sast

foxguard

Security scanner that runs before you commit. 98 built-in rules, single Rust binary, no network calls.

GitHub
98 rules
8 languages
<1s typical scan
terminal
$ foxguard .
Scanning 2,814 files...
src/auth/login.js:14:5
critical js/no-sql-injection CWE-89
app/views.py:42:1
high py/no-hardcoded-secret CWE-798
app/controllers/users.rb:23:5
critical rb/no-sql-injection CWE-89
UserService.java:67:12
high java/no-xxe CWE-611
cmd/server.go:31:3
high go/no-ssrf CWE-918
Found 5 issues in 2,814 files (0.92s)

Fast by default

Rust-native engine with tree-sitter parsing. No JVM startup, no Python interpreter, no network round-trips.

express
141 files
foxguard
0.284s
Semgrep
17.373s
61x faster
flask
83 files
foxguard
0.084s
Semgrep
7.325s
87x faster
gin
99 files
foxguard
0.516s
Semgrep
8.007s
16x faster

foxguard built-in rules vs Semgrep auto. Run ./benchmarks/run.sh locally to reproduce.

edit
foxguard
fix
commit

What it catches

Framework-aware rules across 7 languages. Express sessions, Django CSRF, Rails mass assignment, Spring XXE, and more.

Express / Node

24

Session secrets, cookie flags, JWT hardening, reflected response writes.

sessioncookiesjwtxss

Flask / Django

26

Secret keys, debug mode, CSRF protection, session cookie flags.

secret keyscsrfsessiondebug

Gin / net/http

8

Trusted proxies, missing timeouts, SSRF, TLS verification bypass.

proxiestimeoutsssrftls

Rails / Ruby

10

Mass assignment, CSRF bypass, unsafe deserialization, XSS escaping.

paramscsrfmarshalxss

Spring / Java

10

SQL injection, XXE, deserialization, CSRF config, CORS policy.

sqlxxecsrfcors

PHP / Laravel

10

Eval, file inclusion, unserialize, command injection, extract.

evalincludeunserializessrf

Rust

10

Unsafe blocks, transmute, command injection, TLS verification.

unsafetransmutetlsunwrap
< 1s

Single binary

No JVM, no Python runtime, no network calls. Rust-native and fast enough for pre-commit hooks.

hook

Pre-commit ready

Run foxguard init to install a repo-local hook and get a starter .foxguard.yml.

.yaml

Bring your own rules

Load a useful Semgrep-compatible YAML subset on top of built-ins when you need it.

base

Baselines

Accept existing findings once and focus only on new ones with a baseline file.

secret

Secrets scanning

Detect leaked credentials and private keys with redacted output and binary-safe handling.

SARIF

CI-friendly output

Terminal output locally, JSON and SARIF for automation and GitHub Code Scanning.

Semgrep compatibility

Bring your existing rules

Load Semgrep-compatible YAML on top of built-ins with --rules. Supports the structural matching subset most teams actually use.

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

Install

npm / npx
npx foxguard .
Rust / Cargo
cargo install foxguard
Quick start
1.
foxguard init pre-commit hook + config
2.
foxguard . scan everything
3.
foxguard --changed . scan only modified files
4.
foxguard secrets --changed . check for leaked credentials

Rules

98 built-in rules, each mapped to a CWE identifier.

JavaScript / TypeScript 24
js/no-eval critical CWE-95
js/no-hardcoded-secret high CWE-798
js/no-sql-injection critical CWE-89
js/no-xss-innerhtml high CWE-79
js/no-command-injection critical CWE-78
js/no-document-write high CWE-79
js/no-open-redirect medium CWE-601
js/no-weak-crypto medium CWE-327
js/no-path-traversal high CWE-22
js/no-ssrf high CWE-918
js/no-prototype-pollution high CWE-1321
js/no-unsafe-regex medium CWE-1333
js/no-cors-star medium CWE-942
js/express-no-hardcoded-session-secret high CWE-798
js/express-cookie-no-secure medium CWE-614
js/express-cookie-no-httponly medium CWE-1004
js/express-cookie-no-samesite medium CWE-352
js/express-session-saveuninitialized-true medium CWE-359
js/express-direct-response-write high CWE-79
js/jwt-hardcoded-secret high CWE-798
js/jwt-none-algorithm high CWE-347
js/jwt-ignore-expiration high CWE-613
js/jwt-decode-without-verify high CWE-347
js/jwt-verify-missing-algorithms high CWE-347
Python 26
py/no-eval critical CWE-95
py/no-hardcoded-secret high CWE-798
py/no-sql-injection critical CWE-89
py/no-command-injection critical CWE-78
py/no-path-traversal high CWE-22
py/no-ssrf high CWE-918
py/no-weak-crypto medium CWE-327
py/no-pickle high CWE-502
py/no-yaml-load high CWE-502
py/no-debug-true medium CWE-489
py/no-open-redirect medium CWE-601
py/no-cors-star medium CWE-942
py/flask-debug-mode high CWE-489
py/django-secret-key-hardcoded high CWE-798
py/flask-secret-key-hardcoded high CWE-798
py/session-cookie-secure-disabled medium CWE-614
py/session-cookie-httponly-disabled medium CWE-1004
py/session-cookie-samesite-disabled medium CWE-352
py/csrf-cookie-secure-disabled medium CWE-614
py/csrf-cookie-httponly-disabled medium CWE-1004
py/csrf-cookie-samesite-disabled medium CWE-352
py/csrf-exempt high CWE-352
py/wtf-csrf-disabled high CWE-352
py/wtf-csrf-check-default-disabled high CWE-352
py/django-allowed-hosts-wildcard medium CWE-346
py/secure-ssl-redirect-disabled medium CWE-319
Go 8
go/no-sql-injection critical CWE-89
go/no-command-injection critical CWE-78
go/no-hardcoded-secret high CWE-798
go/no-weak-crypto medium CWE-327
go/no-ssrf high CWE-918
go/insecure-tls-skip-verify high CWE-295
go/gin-no-trusted-proxies medium CWE-346
go/net-http-no-timeout medium CWE-400
Ruby 10
rb/no-eval critical CWE-94
rb/no-command-injection critical CWE-78
rb/no-sql-injection critical CWE-89
rb/no-mass-assignment high CWE-915
rb/no-unsafe-deserialization critical CWE-502
rb/no-open-redirect high CWE-601
rb/no-csrf-skip high CWE-352
rb/no-html-safe high CWE-79
rb/no-hardcoded-secret high CWE-798
rb/no-weak-crypto medium CWE-327
Java 10
java/no-sql-injection critical CWE-89
java/no-command-injection critical CWE-78
java/no-unsafe-deserialization critical CWE-502
java/no-ssrf high CWE-918
java/no-path-traversal high CWE-22
java/no-weak-crypto medium CWE-327
java/no-hardcoded-secret high CWE-798
java/no-xxe high CWE-611
java/spring-csrf-disabled high CWE-352
java/spring-cors-permissive medium CWE-942
PHP 10
php/no-eval critical CWE-95
php/no-command-injection critical CWE-78
php/no-sql-injection critical CWE-89
php/no-unserialize critical CWE-502
php/no-file-inclusion critical CWE-98
php/no-weak-crypto medium CWE-327
php/no-hardcoded-secret high CWE-798
php/no-ssrf high CWE-918
php/no-extract high CWE-621
php/no-preg-eval critical CWE-95
Rust 10
rs/unsafe-block medium CWE-676
rs/transmute-usage high CWE-843
rs/no-command-injection critical CWE-78
rs/no-sql-injection critical CWE-89
rs/no-weak-hash medium CWE-328
rs/no-hardcoded-secret high CWE-798
rs/tls-verify-disabled high CWE-295
rs/no-ssrf high CWE-918
rs/no-path-traversal high CWE-22
rs/no-unwrap-in-lib medium CWE-248