Skip to content

Releases: PwnKit-Labs/foxguard

v0.7.1

17 Apr 13:58

Choose a tag to compare

foxguard v0.7.1 — Taint engine 2× faster

A performance release. Go, Python, and JavaScript taint engines were each re-walking every file's AST once per rule. We collapsed that to one walk per sanitizer group. Gin scans are 2.2× faster. Express and Flask are ~1.25× faster. Findings are byte-identical.

Full write-up: Making foxguard taint tracking 2× faster in v0.7.1

npx foxguard@latest .

Benchmark (avg ms, 15 iterations, 3 warmups)

Repo v0.4.0 v0.7.0 v0.7.1 v0.7.1 vs v0.7.0 v0.7.1 vs v0.4.0
express 128 183 145 -21% +13%
flask 127 233 187 -20% +47%
gin 111 364 166 -55% +50%

Express now lands within 13% of the pre-taint v0.4.0 baseline while doing strictly more work (cross-file taint tracking, multi-hop propagation).

What changed

Performance — the taint trilogy

  • #199 — Share Go taint Pass 1 summaries across rules
  • #202 — Share Python taint Pass 1 summaries across rules
  • #203 — Share JavaScript taint Pass 1 summaries across rules

Same pattern across all three: group rules by sanitizer fingerprint, compute function summaries once per group, share across rules. For Go, 9 taint rules collapse from 9 AST walks per file to 2. For JavaScript, 11 rules collapse from 22 walks to 4. Findings are attributed back via a new rule_id_hint field on TaintFinding.

Distribution

  • #205 — New one-line installer: curl -fsSL https://foxguard.dev/install.sh | sh
    Detects OS + arch, hits GitHub API for latest release, drops the binary in $HOME/.local/bin. ~80 lines of POSIX sh, no maintenance.
  • #195 — Removed Homebrew tap automation. The brew install peaktwilight/tap/foxguard path still works at v0.6.3 for existing users; new users should use the installer, npx, or cargo install.

Docs + infra polish

  • #194 — New TriageShowcase section on the landing page
  • #196 — Unified tagline: "A security scanner as fast as a linter, written in Rust." Matches the Astral positioning pattern and the HN-validated post title. Rule count standardized on 170+.
  • #197scripts/release.sh now auto-bumps README install refs. CI guard asserts they match Cargo.toml.
  • #198 — Bumped ratatui 0.290.30 (pulls lru past GHSA-rhfx-m35p-ff5j).

Correctness

All refactors verified with:

  • Byte-identical JSON diffs on express, flask, and gin between pre- and post-refactor binaries
  • Dogfood — foxguard scans its own Rust source and reports the same 1,082 findings with identical severity breakdown
  • Test suite — 415+ tests passing, clippy clean under -D warnings

Upgrade

npx foxguard@latest .
# or
curl -fsSL https://foxguard.dev/install.sh | sh
# or
cargo install foxguard

v0.7.1 is a drop-in replacement for v0.7.0. Same rules, same findings, faster.

Closed

  • #174 (perf regression v0.6.2 is 2-5× slower than v0.4.0) — closed
  • #200 (extend batched walks to Python) — delivered in #202
  • #191 (automate README version refs) — delivered in #197
  • #173 (Homebrew automation) — superseded by #205 installer

v0.7.0

17 Apr 09:36
d2e6186

Choose a tag to compare

foxguard v0.7.0 — Interactive TUI

foxguard tui — a full-screen terminal UI for local security triage. Pick a mode, walk findings, mark/baseline/ignore, and jump to source — without leaving the terminal.

npx foxguard@latest tui .

Highlights

  • New tui command as the first-class interactive surface (renamed from ui).
  • Launch picker with three modes: Scan, Diff, Secrets. Nothing runs until you choose.
  • Richer detail pane — source context, cleaner snippet section, dataflow path rendering.
  • Explicit Open targetsfinding / source / sink, cycled with Tab, opened with Enter.
  • In-app triage actions (i): mark reviewed / todo / ignore, clear review state, add to baseline, ignore rules in config. Preview before apply.
  • Diff and Secrets share the same UX language as Scan: same launch flow, footer, key hints.

Screenshots

foxguard TUI launch picker

foxguard TUI findings + detail split

foxguard TUI triage popup

Usage

npx foxguard tui .                 # full scan triage
npx foxguard tui --diff main .     # only new findings vs target branch
npx foxguard tui --secrets .       # credentials and token leaks

Keys: h/l move, 1-3 jump, Tab cycle open target, Enter open, i triage, ? help, q quit.

Upgrade notes

  • Use tui instead of uiui is reserved for future web experiences.
  • Non-interactive scan commands are unchanged.

Also in this release

  • Multi-hop cross-file taint tracking (#188)
  • Cross-version benchmark harness for perf regressions (#187)
  • Taint extraction optimizations and code formatting (#186)

Read more

Introducing foxguard TUI in v0.7.0

v0.6.3

13 Apr 15:35

Choose a tag to compare

What's Changed

Full Changelog: v0.6.2...v0.6.3

v0.6.2

12 Apr 21:05

Choose a tag to compare

What's Changed

Full Changelog: v0.6.1...v0.6.2

v0.6.1

12 Apr 18:44

Choose a tag to compare

Precision & quality release

25 commits since v0.6.0 focused on precision, quality, and developer experience.

New rules & sources

  • Kotlin taint rules: kt/taint-sql-injection, kt/taint-command-injection, kt/taint-ssrf with Ktor + Spring Boot sources
  • NoSQL injection: py/taint-nosql-injection, js/taint-nosql-injection, go/taint-nosql-injection for MongoDB
  • XXE taint: py/taint-xxe, js/taint-xxe with defusedxml sanitizer support
  • Log injection: py/taint-log-injection, js/taint-log-injection, go/taint-log-injection
  • Deserialization: js/no-unsafe-deserialization, go/no-unsafe-deserialization
  • JWT: py/jwt-no-verify, py/jwt-hardcoded-secret, go/jwt-no-verify, go/jwt-hardcoded-secret
  • Java XSS, C# path traversal, Ruby SSRF + path traversal, Go path traversal taint
  • Framework sources: Koa, NestJS (JS), Echo/Fiber/Chi (Go), Tornado/Bottle (Python)

Taint engine fixes

  • Python walrus operator (:=) now tracked
  • JS await expressions no longer break taint chain
  • Go type assertions preserve taint
  • JS spread elements (...arr) propagate taint
  • Python comprehensions propagate taint
  • Ternary/conditional expressions propagate taint in Python + JS
  • JS export default functions now included in cross-file summaries

Precision improvements (false positive reduction)

  • LDAP rules: .search()/.bind() no longer match String.search()/Function.bind()
  • NoSQL rules: .find() restricted to MongoDB collection patterns, not Array.find()
  • Log injection: .error()/.log() restricted to console.* to avoid generic method FPs
  • Ruby system("literal") no longer fires
  • NoSQL severity downgraded from Critical → High
  • Sanitizers now match fix suggestions: shlex.quote, DOMPurify.sanitize, shellescape, html.escape, encodeURIComponent all recognized
  • Fix suggestions always visible (not gated behind --explain)
  • Noise path exclusions: /spec/, /__tests__/, /__snapshots__/, /generated/, /gen/, /stubs/

Refactoring

  • impl_rule! macro eliminates 1,665 lines of boilerplate across 174 rules
  • Single-pass language partition in scanner (was 3 separate filter passes)
  • Integration tests organized into 12 language-grouped modules

Totals

  • 174 built-in rules across 10 languages
  • 337 tests all passing
  • Cross-file taint for Python, JavaScript, Go

Upgrading

npx foxguard@0.6.1 .

What's Changed

Full Changelog: v0.6.0...v0.6.1

v0.6.0 — Cross-file taint analysis

12 Apr 14:53
130e981

Choose a tag to compare

Cross-file taint analysis

foxguard now traces taint across file boundaries — the first open-source security scanner to do this at sub-second speed.

# views.py
from . import queries
def search(request):
    name = request.GET["name"]
    return queries.run_query(name)   # ← py/taint-sql-injection fires here

# queries.py  
def run_query(name):
    cur.execute("SELECT * FROM users WHERE name = '" + name + "'")

How it works

Two-pass parallel scan: pass 1 builds function-level taint summaries for every file, pass 2 resolves imported calls against those summaries. The Django shop fixture scans in 0.03s.

Supported patterns

  • Python: from .module import func, from module import func, sibling file resolution
  • JavaScript: require('./services'), import { fn } from './services' with extensionless path probing (.js/.ts/.mjs/.cjs/.jsx/.tsx)
  • Go: same-package resolution (all .go files in a directory share exported functions)

Also in this release

  • Kotlin — 10th supported language with 10 security rules
  • 9 new taint rules: SSTI, XPath injection, LDAP injection for Python, JS, and Go
  • Python taint improvements: % formatting, .format(), tuple/list propagation, os.environ.get() source
  • Fix suggestions on all taint findings with concrete code examples
  • --explain flag showing source-to-sink dataflow traces
  • --max-file-size flag for memory safety on large files
  • Lock-free parallel scanner (Mutex eliminated)
  • Iterative AST walker (stack overflow prevention)

Totals

  • 153 built-in rules across 10 languages
  • 276 tests all passing
  • Cross-file taint for Python, JavaScript, and Go

Upgrading

npx foxguard@0.6.0 .

v0.5.1

12 Apr 12:28

Choose a tag to compare

What's new since v0.5.0

Kotlin — 10th supported language

Full Kotlin support via tree-sitter-kotlin-sg. 10 security rules targeting JVM APIs: SQL injection, command injection, unsafe deserialization, SSRF, path traversal, weak crypto, hardcoded secrets, XXE, CORS wildcard, and ScriptEngine eval.

9 new taint rules: SSTI, XPath, LDAP injection

Every taint language (Python, JS, Go) now covers three additional sink categories:

  • Server-Side Template Injectionpy/taint-ssti, js/taint-ssti, go/taint-ssti (CWE-1336)
  • XPath injectionpy/taint-xpath-injection, js/taint-xpath-injection, go/taint-xpath-injection (CWE-643)
  • LDAP injectionpy/taint-ldap-injection, js/taint-ldap-injection, go/taint-ldap-injection (CWE-90)

Python taint improvements

  • % operator propagation: "SELECT %s" % user_input now detected
  • .format() propagation: "SELECT {}".format(user_input) now detected
  • Tuple/list literal propagation: "... %s" % (clean, tainted) now detected
  • os.environ.get() now recognized as a taint source

Performance

  • Lock-free parallel scanner: replaced Mutex<Vec<Finding>> with par_iter().flat_map().collect(), eliminating lock contention

Totals

  • 134 built-in rules across 10 languages
  • 275 tests all passing

Upgrading

npx foxguard@0.5.1 .

What's Changed

  • feat(py): propagate taint through % formatting, .format(), and tuple/list literals by @peaktwilight in #75
  • perf: lock-free parallel scanner via flat_map/collect by @peaktwilight in #76
  • feat(go): add SSTI, XPath, LDAP taint rules by @peaktwilight in #78
  • feat(js): add SSTI, XPath, LDAP taint rules by @peaktwilight in #79
  • feat(py): add SSTI, XPath, LDAP taint rules and os.environ.get source by @peaktwilight in #80
  • feat: add Kotlin as 10th supported language with 10 security rules by @peaktwilight in #81

Full Changelog: v0.5.0...v0.5.1

v0.5.0

12 Apr 11:52

Choose a tag to compare

Highlights

--explain flag: source-to-sink dataflow traces

Taint findings now show exactly how data flows from source to sink. Pass --explain to see source and sink trace lines with file, line number, and description.

src/routes.py:42  CRITICAL  py/taint-sql-injection (CWE-89)
  source → line 38: flask.request.args (user-controlled input)
  sink   → line 42: cursor.execute (SQL execution)
  Fix: use parameterized queries: cur.execute("SELECT * FROM users WHERE name = ?", (name,))

Fix suggestions for all taint findings

Every taint rule now includes a concrete fix suggestion — parameterized queries for SQL injection, shlex.quote for command injection, html.escape for XSS, URL allowlisting for SSRF, and more. Suggestions appear in terminal (--explain), JSON, and SARIF output.

New taint rules

  • js/taint-sql-injection — SQL injection via string-built queries in Express/Knex/Sequelize
  • js/taint-eval — eval/Function constructor with user input
  • js/taint-command-injection — child_process.exec with user input
  • js/taint-ssrf — fetch/axios/http.get with user-controlled URLs
  • go/taint-*: closure analysis for Gin handler patterns (r.GET("/path", func(c *gin.Context) { ... }))

MCP server (foxguard-mcp)

AI coding agents can now invoke foxguard via Model Context Protocol. Ships as a separate binary.

Claude Code hook integration

Run foxguard automatically on every file edit in Claude Code. See docs/claude-code-integration.md.

Semgrep taint YAML bridge — JS & Go support

The --semgrep-rules flag now supports taint rules targeting JavaScript and Go, in addition to Python.

Internal improvements

  • Shared AliasTable eliminates duplicate import alias logic across Python/JS/Go engines
  • AnalysisContext struct replaces ad-hoc parameter passing in taint engine signatures
  • Dead code cleanup across taint engines and scanner

Upgrading

npx foxguard@0.5.0 .
# or
cargo install foxguard

Update GitHub Actions:

- uses: PwnKit-Labs/foxguard/action@v0.5.0

Update pre-commit:

rev: v0.5.0

What's Changed

New Contributors

Full Changelog: v0.4.0...v0.5.0

What's Changed

New Contributors

Full Changelog: v0.4.0...v0.5.0

v0.4.0

11 Apr 16:19

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.3.3...v0.4.0

v0.3.3

08 Apr 13:54

Choose a tag to compare

Full Changelog: v0.3.2...v0.3.3