AI-powered security scanner for modern web apps. SAST + DAST + LLM code review in a single scan.
Built for developers and vibe coders shipping web apps who need to know if their code is secure β without becoming security experts.
Supports: TypeScript/JavaScript (Next.js, Express, tRPC), Python (Django, FastAPI, Flask), Java/Kotlin (Spring Boot) β and any HTTP API for DAST.
isitsecure scan --repo ./your-app
β every scanner narrates as it runs, then you get a graded report (and a browseable HTML page) with the fixes.
DemoΒ·What It DoesInstallΒ·Quick StartΒ·What It CostsScan ModesΒ·Scan DepthWhat It ScansβDASTΒ·Special DASTΒ·SASTΒ·LLMΒ·Cross-ReferencingLanguage SupportΒ·Output FormatsAuto-FixΒ·Security BadgeHow We CompareΒ·What It Does NOT CoverConfigurationβAPI KeysΒ·OOB CallbacksΒ·Authenticated ScanningCLI ReferenceΒ·Web UIΒ·Try It on the Test AppBenchmarksΒ·PrivacyΒ·ArchitectureScanner DocumentationΒ·LSP SetupContributingΒ·LicenseΒ·Acknowledgements
isitsecure runs 40 rule-based scanners by default β up to 44 with --depth deep β (plus optional AI code review) against your web app in a single command. It combines four approaches that commercial tools sell separately:
SAST (Static Analysis)β scans your source code for vulnerabilities without running it** DAST (Dynamic Analysis)β tests your live app by sending real HTTP requests LLM Code Review**β uses AI to find business logic flaws that pattern matchers can't detect** AI Fix Generation**β generates code patches with unified diffs for every finding
The unique parts:
SAST findings automatically generate targeted DAST tests. Code shows no auth check β scanner sends an unauthenticated request and confirms it's exploitable.** AI generates fixes, not just reports**.--output fixes
produces a Markdown fix plan you can paste into Cursor or Claude Code.
Code β SAST β Findings β Guide DAST β Test β Cross-Reference β LLM Triage β Report β Fixes
β |
βββββββββββββββββ LSP validates / suppresses false positives ββββββββββββββββββββββββββββ
Requirements: Python 3.11+ and git
. (isitsecure isn't on PyPI β the isitsecure
name there is an unrelated project, so don't pip install
it.)
The installer verifies Python/git, then clones the repo, sets up an isolated environment, installs everything, and runs first-time setup:
curl -fsSLo install.sh https://raw.githubusercontent.com/jaurakunal/isitsecure/main/install.sh
bash install.sh
irm https://raw.githubusercontent.com/jaurakunal/isitsecure/main/install.ps1 -OutFile install.ps1
./install.ps1
If Python or git are missing, the installer tells you the exact command to install them for your OS and stops cleanly β it never leaves a half-finished state.
Prefer to do it by hand:
git clone https://github.com/jaurakunal/isitsecure.git
cd isitsecure
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[all]"
isitsecure setup
pip install -e ".[all]"
is the recommended install and enables every scanner. If you want a lighter footprint, the extras are opt-in:
| Install | What works |
|---|---|
pip install -e . |
|
SAST / code-only scans only (--mode code-only ) |
|
pip install -e ".[browser]" |
|
Adds DAST / live-URL scanning (requires isitsecure setup to install Chromium) |
|
pip install -e ".[llm]" |
|
| Adds LLM code review, triage, and AI fixes (requires an API key) | |
pip install -e ".[all]" |
|
| Everything |
URL/DAST scanning needs the [browser]
extra β without it, isitsecure scan <url>
exits with a message telling you to install it.
isitsecure scan https://your-app.com --llm none
isitsecure scan --repo https://github.com/you/your-app --mode code-only --llm none
isitsecure scan https://your-app.com --repo https://github.com/you/your-app --mode full
isitsecure fix --repo ./your-app
isitsecure fix --repo ./your-app --dry-run
isitsecure badge --repo ./your-app
isitsecure scan --repo https://github.com/you/your-app --output sarif
isitsecure launch
isitsecure is free and open source. The only cost is LLM API tokens for the AI-powered features:
| Scan Mode | API Key Needed | Estimated Cost |
|---|---|---|
| URL-only (DAST without LLM) | ||
| No | $0 | |
| Code-only (SAST without LLM) | ||
| No | $0 | |
| Code-only + LLM review | ||
| Yes | ~$5β8 | |
| Full scan (SAST + DAST + LLM) | ||
| Yes | ~$10β15 |
Without an API key, you still get all rule-based scanners β 40 in the default quick depth (15 DAST + 8 special DAST + 17 SAST), or
44 with(which adds 4 slower/aggressive DAST scanners). The LLM adds business logic review, semantic rule verification, and intelligent triage β things no pattern matcher can do.
--depth deep
Supported LLM providers: Anthropic (Claude), Google (Gemini)
| Mode | What It Does | Requires |
|---|---|---|
url-only |
||
| DAST scanners against a live URL | Target URL | |
code-only |
||
| SAST scanners against source code | GitHub repo URL | |
authenticated |
||
| DAST with login credentials (IDOR, cross-user BOLA, RLS, privilege escalation) | URL + credentials (add a second account for cross-user tests) | |
full |
||
| Everything: SAST + DAST + authenticated + LLM review + cross-referencing | URL + repo + credentials + API key | |
auto (default) |
||
| Detects mode from what you provide | Whatever you give it |
Orthogonal to mode, --depth
trades speed for coverage:
| Depth | What runs | When to use |
|---|---|---|
quick (default) |
||
| Structural + config checks, error-based injection, and the snapshot-based scanners (headers, CORS, RLS, source-map, SRI, client-exposure, redirectsβ¦). Fast. | Everyday scans β a solid first pass in a fraction of the time. | |
deep |
||
Everything in quick plus the slow/aggressive probes: time-based (blind) SQL injection, active XSS, auth-bypass timing, rate-limit bursts, and password-reset flows. |
||
| When you want the full arsenal and can wait. |
isitsecure scan https://your-app.com --llm none
isitsecure scan https://your-app.com --depth deep --llm none
The scan narrates each phase and every scanner as it runs (with elapsed time), so a longer deep
scan shows continuous progress rather than appearing to hang.
19 total β 15 run in the default quick
depth; the 4 marked β (slower/aggressive probes) are added by --depth deep
.
| Scanner | What It Finds |
|---|---|
| XSS Scanner β | |
| Reflected, POST body, and DOM-based cross-site scripting | |
| Active Injection Scanner | SQL injection (error + time-based, incl. SQLAlchemy/sqlite3/psycopg errors), command injection, NoSQL injection, XXE, SSTI β injects query, body, and path parameters |
| CSRF Scanner | Cross-site request forgery on state-changing endpoints |
| Rate Limit Scanner β | |
| Missing or bypassable rate limiting on auth endpoints | |
| Session Scanner | Insecure token storage (localStorage), missing cookie flags, long-lived JWTs |
| GraphQL Scanner | Introspection enabled, no depth limits, batch query abuse |
| SSRF Scanner | Server-side request forgery (internal IPs, cloud metadata) |
| File Upload Scanner | Unrestricted file types, path traversal in filenames |
| Mass Assignment Scanner | Accepting privileged fields (role, isAdmin) in request body |
| Security Headers Scanner | Missing CSP, HSTS, X-Frame-Options; server version disclosure |
| CORS Scanner | Wildcard origins, credentials with permissive CORS |
| Open Redirect Scanner | Unvalidated redirect parameters |
| Auth Bypass Scanner β | |
| Username enumeration, default credentials, account lockout bypass | |
| HTTP Probe Scanner | Method tampering, host header injection, directory listing, .env exposure |
| Password Reset Scanner β | |
| Token leakage in response body, email enumeration, no rate limiting | |
| Source Map Scanner | Publicly exposed .map files leaking original source (verified, not just present) |
| Mixed Content Scanner | http:// resources loaded on an HTTPS page |
| SRI Scanner | External CDN scripts/styles loaded without Subresource Integrity hashes |
| Client Exposure Scanner | Secrets in client JS β Supabase service_role keys, internal URLs, unreplaced env placeholders |
| Scanner | What It Finds |
|---|---|
| IDOR Scanner | Insecure direct object references via ID swapping, plus authenticated cross-user (BOLA) testing with two accounts and an anonymous-access false-positive guard |
| JWT Scanner | Algorithm none bypass, weak secrets, key confusion attacks |
| RLS Deep Scanner | Supabase Row Level Security bypass via anon key and cross-user queries |
| Privilege Escalation Scanner | Admin route access, role self-elevation, object-level write bypass |
| Authenticated Crawler | Playwright-based login + BFS crawl to discover authenticated endpoints |
| Race Condition Scanner | TOCTOU bugs via concurrent mutation requests |
| DOM XSS Scanner | Playwright-based sink hooking (innerHTML, eval, location.assign) |
| Body Param Fuzzer | Prototype pollution, type confusion, injection via JSON body fields |
| Scanner | What It Finds |
|---|---|
| Git Secret Scanner | API keys, tokens, and credentials in git history (not just HEAD) |
| Route Auth Analyzer | Next.js/Express/Django/FastAPI/Spring routes missing authentication |
| RLS Policy Analyzer | Supabase tables without Row Level Security enabled |
| Middleware Analyzer | Incomplete middleware coverage (protects pages but not API routes) |
| Express Middleware Analyzer | Express-specific auth middleware gaps |
| Drizzle Schema Analyzer | Sensitive fields (isAdmin, role) exposed to mass assignment |
| Prisma Schema Analyzer | Similar checks for Prisma schemas |
| IaC Scanner | Terraform/CloudFormation misconfigurations (public S3, no encryption) |
| Docker Scanner | Running as root, exposed ports, .env copied into image |
| Shell Script Scanner | Command injection in deploy scripts |
| Dependency Scanner (npm) | Known CVEs in package.json dependencies |
| Python Dependency Scanner | Known CVEs in requirements.txt / pyproject.toml (Django, Flask, FastAPI, PyJWT, etc.) |
| Java Dependency Scanner | Known CVEs in pom.xml / build.gradle (Log4Shell, Spring, Struts, Jackson, etc.) |
| OSV Dependency Scanner | Real-time CVE lookups against Google's OSV.dev database (200K+ vulns, all ecosystems: npm, PyPI, Maven, Gradle, Go, Rust) β no hardcoded CVE list, no API key |
| Firebase Rules Analyzer | Overly permissive Firestore/RTDB security rules |
| OpenAPI Scanner | Internal endpoints exposed in API specifications |
| K8s Scanner | Privileged containers, no resource limits, hostPath mounts |
| Scanner | What It Finds |
|---|---|
| LLM Code Reviewer | Business logic flaws: missing ownership checks, race conditions in payments, incorrect authorization logic |
| Semantic Rule Verifier | Logical errors in RLS policies and Firebase rules (wrong column references, tenant isolation bugs) |
| LLM Business Logic Scanner | Attack planning: price manipulation, double-spend, privilege escalation via application logic |
| LLM Triage Service | Deduplicates findings, assigns priority, generates plain-language owner summary with AβF grade |
| AI Fix Generator | Generates code patches (unified diffs) for each finding β paste into Cursor/Claude Code to fix |
| Feature | What It Does |
|---|---|
| OpenAPI/Swagger Discovery | Probes /openapi.json , /swagger.json , /v3/api-docs and parses the spec into testable endpoints β finds attack surface on APIs with no crawlable frontend |
| HTML Form/Link Discovery | Reads <form> /<input> /query-links from server-rendered pages (bounded url-only crawl + inside the authenticated crawler) β finds attack surface on classic MVC apps with no JS API bundle |
| Endpoint Prioritizer + Time Budget | Ranks likely-vulnerable endpoints first and tests within a per-scanner time budget, so high-risk paths get covered before the clock runs out |
| SASTβDAST Feedback Loop | SAST findings generate targeted DAST tests (6 strategies: auth bypass, IDOR, injection, mass assignment, race condition, RLS bypass) |
| Cross-Referencer | Matches DAST + SAST findings for high-confidence confirmed vulnerabilities |
| Import Graph Centrality | Identifies shared utility files imported by many risky routes for LLM review |
| LSP Auth Flow Tracing | Uses TypeScript Language Server to verify auth middleware is genuinely applied |
| Language | Route Mapping | Auth Detection | Dependency Scan | DAST |
|---|---|---|---|---|
| TypeScript/JavaScript (Next.js, Express, tRPC, GraphQL) | ||||
| Yes | Yes | Yes (npm) | Yes | |
| Python (Django, FastAPI, Flask) | ||||
| Yes | Yes | Yes (pip) | Yes | |
| Java/Kotlin (Spring Boot) | ||||
| Yes | Yes | Yes (Maven, Gradle) | Yes | |
| Go, Ruby, Rust, etc. | ||||
| No | No | No | Yes (DAST works against any HTTP API) |
DAST scanners test live HTTP endpoints regardless of backend language. SAST route mapping, auth detection, and dependency scanning are language-specific.
isitsecure scan URL --output table # Terminal table (default)
isitsecure scan URL --output json # Full JSON report
isitsecure scan URL --output html # Self-contained HTML report
isitsecure scan URL --output sarif # SARIF 2.1.0 for GitHub Code Scanning
isitsecure scan URL --output fixes # AI-generated fix plan (Markdown with diffs)
isitsecure fix --repo ./my-app
isitsecure fix --repo ./my-app --dry-run
isitsecure fix --repo ./my-app --severity critical
What it does:
- Scans your repo with all SAST scanners
- For each critical/high finding with a code location, sends the file to the LLM
- Generates a fixed version of the file
- Writes the fixed code directly to your files
- Shows a summary of what changed
After running, check git diff
to review the changes, run your tests, and commit.
Add a security grade badge to your README:
isitsecure badge --repo ./my-app -o badge.svg
Then add to your README:

The badge shows your grade (AβF) and total finding count, styled like a shields.io badge.
isitsecure is not a replacement for enterprise security platforms. It's designed to be the one tool a solo developer or small team needs β combining capabilities that otherwise require 4-5 separate tools.
- SAST findings automatically generate targeted DAST tests (closed feedback loop)
- LLM reviews business logic (race conditions, price manipulation, ownership checks)
- One command scans + generates + applies AI fixes (
isitsecure fix
) - Cross-references DAST + SAST findings for confirmed vulnerabilities
- LSP traces auth flows through call chains (TypeScript, Python, Java)
| Need | Best specialized tool | How isitsecure compares |
|---|---|---|
| Deep SAST (30+ languages) | ||
OWASP ZAP/Burp SuiteTruffleHog/GitleaksTrivy/CheckovSnyk/CheckmarxNuclei(28K+ stars)| You are | Use this | |---|---| | Solo dev / vibe coder shipping a web app | isitsecure β one tool, one command | | Team with $25K+ security budget | Snyk + GitHub Advanced Security | | Enterprise with compliance requirements | Checkmarx / Veracode | | Pentester doing deep exploitation | Burp Suite Pro + Nuclei | | DevOps focused on containers/IaC | Trivy + Checkov + Gitleaks |
isitsecure works well alongside other tools. Run isitsecure scan
for the combined SAST+DAST+LLM view, and use specialized tools where you need deeper coverage.
Formal taint analysisβ No dataflow tracking across function boundaries. Uses regex + LLM reasoning instead** WAF evasion**β DAST payloads don't include advanced bypass techniques** Compliance mapping**β No OWASP Top 10, CWE, or PCI-DSS tagging (yet)** Network-level scanning**β No port scanning, TLS analysis, or infrastructure enumeration** Mobile apps**β Web APIs only** Go/Ruby/Rust SAST**β Route mapping not yet implemented (DAST and dependency scanning via OSV still work)
Set via environment variable, .env
file, or ~/.isitsecure/config.toml
:
export ANTHROPIC_API_KEY=sk-ant-...
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env
isitsecure setup
isitsecure detects blind SSRF, XXE, and injection vulnerabilities using out-of-band (OOB) callbacks. By default it uses oob.isitsecure.ai
β a free community server running interactsh.
What data is sent? Only the scan target makes DNS/HTTP requests to the OOB server. Your source code never leaves your machine.
Self-host your own:
docker run projectdiscovery/interactsh-server
[oob]
server = "http://oob.yourdomain.com"
Disable entirely: Add enabled = false
under [oob]
in config.
isitsecure scan https://your-app.com \
--auth-email user@example.com \
--auth-password yourpassword \
--auth-provider supabase
isitsecure scan https://your-app.com \
--auth-email user@example.com \
--auth-password yourpassword \
--auth-provider firebase
isitsecure scan https://your-app.com \
--auth-provider token \
--auth-token "eyJ..."
Cross-user IDOR / BOLA β supply a second account and isitsecure logs in as both users and checks whether one user can read or mutate another user's objects (broken object-level authorization). An anonymous-access guard suppresses false positives from endpoints that are simply public.
isitsecure scan https://your-app.com \
--auth-email alice@example.com --auth-password alicepass \
--auth-email-b bob@example.com --auth-password-b bobpass \
--mode authenticated
Frontend-less / plain REST APIs β use --auth-provider token
, which logs in against a generic REST login endpoint (auto-discovered, or pass it explicitly with --login-url
):
isitsecure scan https://api.your-app.com \
--auth-provider token \
--auth-email alice@example.com --auth-password alicepass \
--auth-email-b bob@example.com --auth-password-b bobpass \
--login-url https://api.your-app.com/login
isitsecure scan [URL] [OPTIONS]
Arguments:
URL Target URL to scan (DAST)
Options:
-r, --repo TEXT GitHub repo URL (SAST)
-b, --branch TEXT Git branch [default: main]
-m, --mode TEXT Scan mode: auto|url-only|code-only|authenticated|full
--depth TEXT Scan depth: quick|deep [default: quick]
--llm TEXT LLM provider: anthropic|google|none [default: anthropic]
-o, --output TEXT Output format: table|json|html|sarif|fixes [default: table]
-f, --output-file TEXT Write report to file
--auth-email TEXT Auth email/username for authenticated scanning (user A)
--auth-password TEXT Auth password (user A)
--auth-provider TEXT Auth provider: supabase|firebase|browser|token
(use token for a plain REST login)
--auth-email-b TEXT Second user's email β enables cross-user IDOR/BOLA testing
--auth-password-b TEXT Second user's password (paired with --auth-email-b)
--login-url TEXT Explicit login endpoint (else auto-discovered)
--github-token TEXT GitHub token for private repos
-v, --verbose Enable debug logging
isitsecure launch [OPTIONS]
-p, --port INT Port for web UI [default: 3000]
--host TEXT Host to bind [default: 127.0.0.1]
isitsecure setup Interactive first-time setup
isitsecure version Show version
Prefer a GUI? isitsecure launch
starts a local web interface backed by the same scan engine β no CLI flags to remember:
isitsecure launch
The UI provides:
Visual scan configurationβ target URL, repo, scan mode, AI provider, and optional login credentials** Live scan progress**β a progress bar and a streaming scanner log** Finding browser**β filter by severity or scanner, plus full-text search, with each finding expandable for evidence, technical detail, and remediationPlain-language risk summaryβ an AβF grade, key risks, and a phased remediation plan** One-click AI fixes**β a "Generate Fix" button on any finding produces a unified diff inline (one finding at a time)** Report export**β download JSON, or open the self-contained HTML report in a new tab** Scan history**β recent scans are remembered locally in your browser
The web server resolves your LLM API key the same way the CLI does (ANTHROPIC_API_KEY
, a .env
file, or isitsecure setup
), so scans and fixes work without pasting a key into the browser. You can still enter one in the scan form to override it.
The repo includes VibeTasks β an intentionally vulnerable Next.js + Supabase app with ~50 security issues. All commands below are run from the repo root.
isitsecure scan --repo ./test-app --mode code-only --llm none
To also run the live-app (DAST) scanners, start the app first, then scan its URL:
cd test-app && npm install && npm run dev # serves on port 4000
isitsecure scan http://localhost:4000 --repo ./test-app --mode full
--repo
accepts a local directory (scanned in place, including uncommitted changes) or a remote git URL like https://github.com/you/your-app
. See examples/sample-report.json
for what a scan produces.
isitsecure ships a repeatable benchmark harness that scores recall (of the vulnerability classes an app is known to have, how many we catch) and false positives (findings that must not appear against a hardened build) on public, deliberately-vulnerable apps.
Measured coverage β be realistic about what a scanner catches. On OWASP Juice Shop β a deliberately hard benchmark of 100+ challenges β isitsecure detects roughly 40% of the 45 DAST-detectable challenge classes in an authenticated scan (36% url-only), scored automatically against the app's own /api/Challenges
list. It's strong on authentication bypass, cross-user BOLA/IDOR, injection and misconfiguration, and open redirects; it's weak on interactive client-side XSS and challenges that require multi-step business-logic exploitation. In other words: it's a solid automated first pass that catches whole classes of real bugs in one command β not a substitute for a manual pentest. Full per-class breakdown and methodology are in benchmarks/RESULTS.md.
python benchmarks/run_benchmarks.py # VAmPI (vulnerable + secure builds)
python benchmarks/run_benchmarks.py --all # + NodeGoat + crAPI (heavy)
Each run spins the target up in Docker, runs a DAST scan, scores against a known ground truth, and tears it down (requires Docker). Measured results are tracked in benchmarks/RESULTS.md; see benchmarks/README.md for targets and how scoring works.
Rule-based scanning is fully local. SAST scanners clone your repo to a local temp directory and analyze it on your machine β no code leaves your computer unless you enable LLM review.DAST scanners send HTTP requests to your target URL. Nothing is proxied through external servers.LLM review sends code to your chosen API provider(Anthropic or Google). To be precise: it sends the** full contents of files flagged by the rule-based scanners**(capped at ~50 KB per file) β not your entire codebase, but for most source files that is the whole file, not just a snippet. Run--llm none
to keep everything local.OOB callbacks only involve your scan target making DNS/HTTP requests to the callback server. Your code is never sent there.
See docs/architecture.md for the full pipeline design, including how SAST feeds DAST, how LLM review is prioritized, and how cross-referencing works.
See docs/scanners/ for detailed documentation on every scanner β what it detects, why it matters, real-world breach examples, and how to fix the vulnerabilities it finds.
Language servers let the scanner trace auth flows through your code (via go-to-definition) and suppress false positives β confirming auth middleware is genuinely applied, not just imported.
Let isitsecure install them for you:
isitsecure setup --lsp # install/verify the Python, TypeScript, and Java language servers
isitsecure setup --check # report what's installed (API key, DAST browser, LSP) β installs nothing
setup --lsp
installs what it can cleanly (Python via pip always; TypeScript via npm if Node is present; Java via Homebrew if available) and prints guidance for anything it can't. It's also offered as a step in the full isitsecure setup
. This is optional β scans still work without it using regex-based detection. For manual setup and per-language detail, see docs/lsp-setup.md.
isitsecure is built on protocols and the strategy pattern. Adding a new scanner is straightforward:
- Implement
DASTScannerProtocol
orCodeScannerProtocol
-
Add it to the scanner list in
isitsecure/engine/factory.py -
Add tests under
tests/
Set up a dev environment with pip install -e ".[all,dev]"
, then run the suite with pytest
. Issues and pull requests welcome at github.com/jaurakunal/isitsecure.
Apache 2.0 β see LICENSE.
interactshby ProjectDiscovery for the OOB callback protocolPlaywrightfor browser automation in authenticated crawling and DOM XSS detection