oauthlint
Catch the OAuth / OIDC / JWT / session / CORS anti-patterns AI coding tools systematically produce.
A curated, multi-language Semgrep rule pack · JS/TS · Python · Go · Rust · Java · CLI + GitHub Action + VS Code · free & MIT
npx oauthlint scan ./srcRequires Semgrep on the machine running the scan (
pipx install semgreporbrew install semgrep). The CLI invokes it under the hood and normalises the output for humans and CI.
Full docs & rule catalogue → oauthlint.dev/docs · the research behind it → oauthlint.dev/research
Quick start
# one-shot scan, no install
npx oauthlint scan ./src
# fail CI on HIGH severity and above
npx oauthlint scan ./src --fail-on HIGH
# GitHub Code Scanning (SARIF) or a shareable HTML audit report
npx oauthlint scan ./src --format sarif > oauthlint.sarif
npx oauthlint scan ./src --format html > report.html
# preview safe autofixes as a diff, then apply them
npx oauthlint scan ./src --fix-dry-run
npx oauthlint scan ./src --fix
# learn a rule in the terminal: the why, the fix, and vulnerable/safe examples
npx oauthlint explain auth.jwt.alg-noneScan only what changed for fast pre-commit hooks and editors with --diff / --staged, or adopt on a large repo with a baseline (oauthlint baseline ./src then scan --baseline) so you're alerted on new findings only. Other commands: list, explain, init, doctor. Run oauthlint --help or see the full CLI reference.
Every finding teaches
Each finding ends with a hint, ↳ run \oauthlint explain ` for details + the fix. oauthlint explainbrings the rule docs into your terminal, offline, from the bundled pack: severity, CWE/OWASP with canonical links,llm-prevalence, the why + how-to-fix, and side-by-side **vulnerable** vs **safe** code. It resolves a rule by id (auth.jwt.alg-none), slug (jwt-alg-none), or oauthlint-rule-id (AUTH-JWT-001); add --json` for the structured rule object.
What it catches
AI coding assistants (tools like GitHub Copilot, Cursor, and Claude Code, and others) ship the same auth bugs across every project: a JWT accepted with alg: none, a hard-coded client_secret, an OAuth flow with no state/PKCE, a token in localStorage, a * wildcard redirect_uri, an unrate-limited /login, a plaintext password, Math.random() for a CSRF token.
- 138 rules across JavaScript/TypeScript, Python, Go, Rust, and Java, each mapped to CWE/OWASP with a fix page (a lesson, not a grep hit).
- Dataflow (taint) analysis. Beyond pattern-matching, the pack traces untrusted input through to dangerous sinks: an OAuth credential reaching a log sink, request input reaching a JWT verification key, open-redirect and SSRF.
- Autofix.
--fixapplies safe rewrites (cookie flags and similar) in place;--fix-dry-runpreviews them as a unified diff first. Per-finding fix data also rides along in--jsonand SARIF underfixes. - HTML report.
scan --format htmlrenders a self-contained, offline, no-JavaScript audit you can email or attach to a PR. - Plus SARIF for Code Scanning, incremental
--diff/--staged, and a baseline for existing codebases.
Browse the always-current catalogue at oauthlint.dev/rules.
Use directly with Semgrep, no install
Already have Semgrep? Run the full pack with one command, no config file:
semgrep --config https://oauthlint.dev/r/oauthlint.yaml ./srcPer-language bundles exist too (oauthlint-python.yaml, oauthlint-go.yaml, …). That URL is always the latest pack; for a pinned ruleset in CI, use this CLI (npx oauthlint@<version> scan) or vendor oauthlint-rules. See the Semgrep docs.
Why oauthlint, and not just Semgrep?
Honest answer: nothing stops you writing these rules yourself. Semgrep is open source and it's the engine we run, so there's no technical moat. What oauthlint gives you is the work most people never do:
- Low false positives, validated against real auth libraries.
jose, NextAuth, PyJWT, Authlib,golang/oauth2,oauth2-rs, Spring Security and more. Anything that fires on mature library source goes to a triage queue, not to you (validation report). - One coherent product across every language. Same concepts, same ID scheme, same docs, not a patchwork of community rules.
- The angle the registry doesn't have. It targets the auth bugs AI tools ship on repeat, encoded in each rule's
llm-prevalencemetadata and measured by a reproducible benchmark (the research).
Use oauthlint when you'd rather not write and maintain an auth rule pack yourself. That's the whole pitch.
Also available
- GitHub Action.
Auspeo/oauthlint@v1(theAuspeo/oauthlint/action@v1subpath still works), Docker-based (any language), with inline PR annotations and a job summary. Docs. - CI recipes. SARIF uploads to GitHub Code Scanning, and there's a worked example for GitLab CI.
- VS Code / Cursor / Windsurf. oauthlint on the VS Code Marketplace and OpenVSX: inline diagnostics on save, a status-bar finding count, an "Apply fix" Quick Fix where a rule ships a safe autofix, and Quick Fix suppressions.