xploitscan
v1.19.0
Published
AI security scanner for vibe-coded apps. Find vulnerabilities before attackers do.
Maintainers
Readme
XploitScan
Security scanner for AI-generated code. Find vulnerabilities before attackers do.
Built for developers shipping code via Cursor, Lovable, Bolt, Replit, and Claude Code. 223 security rules (30 free). Plain-English results. Copy-paste fixes.
Quick Start
npx [email protected] scan .No install, no config, no account required.
The CLI scans on your machine; XploitScan's servers never receive your source files. Its network calls are a dependency lookup against OSV.dev (package names and versions only) and, if you're logged in, a plan check plus an upload of the findings report, including a few lines of code around each finding, which we strip before storing. If ANTHROPIC_API_KEY is set, it also sends code to Anthropic under your own key for AI analysis; unset it to keep your code off Anthropic. From the CLI release that adds the ai setting, --no-ai or ai: false in .xploitscanrc does the same without unsetting the key. The web scanner processes files in memory and never writes them to disk or a database. To filter false positives, short excerpts around each finding are sent to our AI provider, Anthropic, which may keep them for up to 30 days. Signed-in users can turn this off in Settings for scans started from the Scan page. We store scan results (grade, score, and each finding's rule, file, line and fix, plus a masked preview of detected secrets), not your files.
Without an account the CLI runs the 30 free rules. On a paid plan (Pro or Team), run npx [email protected] auth login, or set XPLOITSCAN_API_KEY to a key from Settings → API Keys, and it downloads the other 193 and runs all 223 locally. API keys are a paid-plan feature — see pricing.
What It Catches
Intent check
If your project has a README, a CLAUDE.md, an AGENTS.md, a .cursorrules
file or a .xploitscan-intent file, the scan also compares what you wrote
down against what the code does:
Intent check — 1 place the code disagrees with what you wrote down
README.md:5 "Every API route requires the user to be logged in."
so the endpoint rejects unauthenticated callers
✗ /api/orders (app/api/orders/route.ts:3) — API Route Missing AuthenticationEvery line points at a finding the scan already produced, with a file and a line. It never guesses: a claim the scan cannot dispute is left alone rather than reported as a pass.
It reads whatever your project already has: README.md, CLAUDE.md,
AGENTS.md, .cursorrules, .cursor/rules/*.mdc, .windsurfrules,
.github/copilot-instructions.md, .bolt/prompt, and saved AI chat
transcripts under .specstory/history/ — where only your turns are read, not
the assistant's.
If none of those exist, say it in one line:
xploitscan intent # asks once, saves to .xploitscan-intent
xploitscan scan . --intent "Customers only see their own orders."A scan with no spec on disk offers to ask, but only in a real terminal — never
in CI, never when piped, and never inside a git hook. --no-intent-prompt
turns it off entirely.
223 rules across 14 categories (30 run free; the rest need a paid plan):
| Category | Examples | Rules | |----------|---------|-------| | Secrets | Hardcoded API keys, AI keys shipped to the browser, .env files, Terraform state | 60 | | Configuration | Missing security headers, CORS wildcards, debug mode, Docker misconfigs | 37 | | Injection | SQL, XSS, SSRF, command injection, path traversal, XXE, SSTI | 35 | | Authorization | IDOR, Supabase RLS in migrations, open Firebase rules, roles from user-editable metadata | 20 | | Cryptography | Weak RSA, deprecated TLS, ECB mode, hardcoded IVs | 12 | | Authentication | Missing auth, unverified sessions and JWTs, weak password reset | 11 | | Information Leakage | PII in logs, verbose errors, exposed admin routes | 11 | | Availability | Missing rate limits, no request size limits, ReDoS, AI calls without token caps | 9 | | Supply Chain | Unpinned GitHub Actions, vulnerable dependencies | 7 | | Infrastructure | Dockerfile, Kubernetes, Terraform, AWS IAM misconfigs | 7 | | Performance | N+1 queries, blocking the main thread | 6 | | Code Quality | Empty catch blocks, TODO/FIXME, magic numbers | 4 | | Payment Security | Unverified Stripe and other webhooks | 2 | | Logic | Webhooks without replay protection, account state kept in the browser | 2 |
Every finding includes OWASP Top 10 and CWE references, plus informational SOC 2 / ISO 27001 cross-references where a rule maps to one. That mapping is not a certification.
Detection Quality
Detection is scored publicly on a labeled fixture corpus. Checked daily and rerun when rules or fixtures change (at least weekly); updates go live with the next deploy. Live precision, recall, fixture counts, and the side-by-side comparison with Semgrep and Bearer are at xploitscan.com/benchmark — those figures are not repeated here so they cannot drift from the published results.
The scanner uses a two-layer architecture: a fast regex pre-filter for pattern-based rules (secrets, missing headers, container misconfigs), and a Babel-parsed AST layer with local taint tracking for data-flow rules (SSRF, prototype pollution, mass assignment, SSTI, command injection from user input). Recognized taint sources: Express / Fastify / Koa / Next.js App Router / Web Fetch API / AWS Lambda.
Methodology, fixture format, and reproducibility instructions: xploitscan.com/docs/detection-methodology.
Installation
# Run directly (recommended — always latest version)
npx [email protected] scan .
# Or install globally
npm install -g xploitscan
xploitscan scan .Usage
# Scan current directory
npx [email protected] scan .
# Scan a specific folder
npx [email protected] scan ./src
# JSON output (for scripting/CI)
npx [email protected] scan . --format json
# SARIF output (for GitHub Security tab)
npx [email protected] scan . --format sarif
# Scan only changed files vs main branch
npx [email protected] scan . --diff
# Watch mode — re-scan on file changes
npx [email protected] scan . --watchOutput Formats
| Format | Use Case |
|--------|----------|
| terminal | Human-readable terminal output (default) |
| json | Machine-readable JSON with all findings |
| sarif | GitHub Security tab integration |
GitHub Action
Add automated scanning to every PR:
name: Security Scan
on: [push, pull_request]
permissions:
contents: read
security-events: write
pull-requests: write
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run XploitScan
uses: bgage72590/xploitscan-action@v1
with:
path: '.'
fail-on: 'critical'
comment: 'true'
# Optional: api-key: ${{ secrets.XPLOITSCAN_API_KEY }}@v1 tracks the latest v1 release. Pin the action to a full commit SHA so a moved tag cannot change what runs: uses: bgage72590/xploitscan-action@b5db3d14ea5ca2d3d5f9f6cf59ed307a6634bc85 # v1.11.0.
security-events: write is needed only for the code-scanning upload. If you set upload-sarif: 'false', you can leave it out. The SARIF file is still written to sarif-file, for example to save as a workflow artifact.
The action automatically uploads SARIF to GitHub Security and posts a PR comment. Findings appear in the GitHub Security tab as code scanning alerts.
Configuration
Create a .xploitscanrc file in your project root. Every key below is read by
the scanner; there are no others.
{
"ai": false,
"scan": {
"exclude": ["docs/**", "examples/**"],
"extensions": ["liquid", "hbs"],
"maxFileSize": 500000,
"gradeVendored": false,
"failOnQuality": false
},
"rules": {
"disable": ["VC042", "QA005"]
},
"output": {
"format": "terminal",
"verbose": false
}
}| Key | Effect |
| --- | --- |
| ai | Turn off the AI false-positive pass, the same as --no-ai. |
| scan.exclude | Extra ignore patterns, .gitignore syntax, on top of .gitignore and .xploitscanignore. |
| scan.extensions | Additional file extensions to read. Added to the built-in list, never replacing it — otherwise one unusual extension would silently turn off every default and hand you a clean report because nothing was scanned. |
| scan.maxFileSize | Skip files larger than this many bytes. |
| scan.gradeVendored | Count findings in vendored/generated/docs paths toward the grade and the exit code. Off by default; they are reported either way. |
| scan.failOnQuality | Let quality findings (QA…) set a non-zero exit code. Off by default. |
| rules.disable | Rule IDs to turn off entirely, security or quality. |
| output.format | terminal, json, sarif, splunk-hec, elastic-ecs, datadog-logs. |
| output.verbose | Extra detail during the scan. |
To ignore paths, or to silence specific rules on specific paths, use
.xploitscanignore below — it is more precise than scan.exclude and is the
mechanism the scanner itself uses.
.xploitscanignore
A .gitignore-style file in your project root. Plain lines exclude whole
files from scanning (negate with !). A line may also carry a trailing
rule-ID list to suppress only those rules on matching paths while still
scanning the files for everything else:
# Don't scan generated code at all
generated/**
# Allow log-injection (VC044) in internal cron scripts only
scripts/cron/** VC044
# Silence two rules across all test files
**/*.test.ts VC031, VC043
# Suppress every rule on a legacy tree (the `scanner` wildcard)
legacy/** scannerFor a single reviewed-and-accepted finding, prefer an inline
// VC<id>-OK: <reason> comment instead of a file- or path-wide rule. Put it on
the flagged line or anywhere in the comment block above it; // scanner-OK:
silences any rule at that site. Security findings and quality findings both
honour a matching marker. #, -- (SQL) and /* */ work as well as //.
A marker needs a rule ID.
Where it is looked up. Every .xploitscanignore between your project root
and the directory being scanned applies, so xploitscan scan packages/web/src
still honours the file at the top of the repo. Patterns are interpreted
relative to the file that declares them — a root file naming
packages/web/src/lib/demo.ts matches that file whether you scan the repo root
or packages/web/src — and a nested file takes precedence over a broader rule
above it, the same way .gitignore does.
A marker may sit at most one blank line above the code it covers, and it covers only that first line. A marker inside a string does not hide a finding. The CLI reads nested ignore files. The GitHub App, the API, and web uploads read only the root file and warn that a nested file was skipped. An ignore file over 64 KB or 2,000 lines is skipped with a warning, and nothing in it is applied. Paths that use .., a drive letter, or a single-segment absolute path are rejected. A leading / with another path segment is an anchor, not a reject. Reports show the suppressed count. A whole-file line such as generated/** does not need a rule ID.
Vendored and generated code
Some of what a scanner finds isn't code you wrote. AI app builders copy
shadcn/ui into your project verbatim; codegen writes into __generated__/;
your README contains example code that exists to show what not to do.
XploitScan scans all of it and reports everything it finds — but findings in these paths don't count toward your grade or the CI exit code:
**/components/ui/** **/shadcn/** **/ui/shadcn/**
**/vendor/** **/vendored/** **/third_party/**
**/generated/** **/__generated__/**
**/*.md **/*.mdx
.claude/** .agent/** .cursor/** .superpowers/** .windsurf/**They still appear in every report, tagged [not graded], with the count shown
next to the grade. Nothing is hidden — a grade that held findings out always
says so.
Hardcoded credentials are the exception and are always graded, in every
path above. A key committed to your repository is live no matter which
directory holds it, so "the generator wrote that file" doesn't apply. A
service-role key in __generated__/client.ts or a plaintext Kubernetes Secret
under generated/ still counts against your grade.
Why: shadcn's chart.tsx writes CSS custom properties through
dangerouslySetInnerHTML, which trips a critical XSS rule. It ships
byte-identically in a large share of AI-scaffolded projects, and one critical
caps a project at grade D. Grading it means grading shadcn's code as yours.
To opt out and grade everything:
xploitscan scan . --grade-vendoredOr persistently, in .xploitscanrc:
{ "scan": { "gradeVendored": true } }Web Dashboard
Scan via the web at xploitscan.com:
- Drag-and-drop file/ZIP upload
- GitHub URL scanning
- Scan history and score trends
- PDF security reports
- Informational SOC 2 / ISO 27001 mapping (not a certification)
- Slack and Discord webhook notifications
Free: 5 scans/day, 30 core rules. Pro ($19/mo): unlimited scans, all 223 rules, PDF reports, webhooks, AI false-positive filter. Informational compliance mapping (SOC 2, ISO 27001, OWASP, CWE) is on every plan. New subscribers get a 7-day free trial (one trial per customer; not available if you have had an XploitScan trial or paid subscription before). Team ($99/mo): self-serve. New subscribers get a 7-day free trial (one trial per customer; not available if you have had an XploitScan trial or paid subscription before). 2 months free with annual billing.
Supported Languages
Vulnerability rules focus on JavaScript and TypeScript (including React, Next.js, Vue and Svelte) and Python, with some rules for Ruby, Go, Java and PHP. Hardcoded-secret detection also runs on the other source files the scanner reads, such as Rust, Swift, Kotlin, C#, Dart and C/C++. We also scan config files: Dockerfile, docker-compose, Terraform, Kubernetes manifests, CI/CD workflows, .env files, and package manifests.
Links
- Website: xploitscan.com
- Documentation: xploitscan.com/docs
- Changelog: xploitscan.com/changelog
- Issues: [email protected]
- Email: [email protected]
License
MIT -- Cipherline LLC
