AST-based SAST for Python and JavaScript — detects IDOR, auth bypass, and ownership flaws that Bandit misses.
Project description
The world's most precise offline static application security testing engine.
Zero dependencies. 98.8% CVE recall. Five languages. Ships as a single .exe.
What makes it different
Existing SAST tools detect subprocess(shell=True). They miss the bugs that actually appear in CVE databases:
# CWE-639 — Insecure Direct Object Reference
# Bandit: silent. Semgrep OSS: silent. ansede-static: CRITICAL
@app.route("/invoice/<invoice_id>")
@login_required
def get_invoice(invoice_id):
return db.execute("SELECT * FROM invoices WHERE id = ?", (invoice_id,))
# ^ no WHERE user_id = current_user.id → any user can see any invoice
# CWE-862 — Missing Authentication on admin endpoint
# Bandit: silent. Semgrep OSS: silent. ansede-static: HIGH
@app.route("/admin/users")
def list_users(): # no @login_required, no permission check
return User.query.all()
# CWE-285 — Missing Ownership Check on destructive action
# Bandit: silent. Semgrep OSS: silent. ansede-static: HIGH
@app.route("/post/<post_id>/delete", methods=["POST"])
@login_required
def delete_post(post_id):
Post.query.filter_by(id=post_id).delete()
# no if post.author_id != current_user.id: abort(403)
ansede-static models routes, decorators, auth guards, and ownership patterns at the AST level. This is how it achieves 98.8% CVE recall while Bandit OSS sits at ~65%.
Install
pip install ansede-static
# Or download the standalone .exe (zero Python required):
# https://github.com/mattybellx/Ansede/releases/latest
# Scan a directory
ansede-static src/
# SARIF for GitHub Code Scanning
ansede-static src/ --format sarif --output results.sarif
# JSON for scripting
ansede-static src/ --format json --output findings.json
# Only fail CI on critical findings
ansede-static src/ --fail-on critical
# Incremental — only changed files (monorepo-friendly)
ansede-static src/ --incremental
Verified Performance — May 2026
| Benchmark | Result |
|---|---|
| Regression suite | 919 tests passed |
| NVD CVE recall | 81/82 (98.78%) |
| NVD CVE precision | 96.43% |
| False positive rate | 3.57% |
| Web-wild recall | 100.00% |
| Web-wild precision | 95.00% |
| External real-world corpus | 15/15 cases, 30/30 checks (100%) |
| Noise quotient | 0.861 findings / kLOC |
| Raw engine speed | ~0.02s per 100k LOC |
| Languages | Python · JavaScript · TypeScript · Go · Java · C# |
| World-Best Audit | ✅ All quality gates passed |
Full methodology and machine-readable artifacts: BENCHMARKS.md
Detection Coverage
| Category | CWEs detected | Example |
|---|---|---|
| Broken Access Control (IDOR, auth bypass) | CWE-639, CWE-862, CWE-285, CWE-287 | Route missing @login_required, no ownership check on DB query |
| Injection | CWE-89, CWE-78, CWE-94, CWE-95 | SQLi via f-string, command injection via subprocess(shell=True), eval injection |
| Cryptographic Failures | CWE-327, CWE-328, CWE-798 | MD5/SHA1 for passwords, hardcoded AWS keys, API tokens in source |
| Path Traversal & SSRF | CWE-22, CWE-918 | Unsanitized os.path.join, user-controlled URLs in requests.get() |
| Cross-Site Issues | CWE-79, CWE-352 | innerHTML with user data, missing CSRF tokens |
| Deserialization | CWE-502 | pickle.loads() on untrusted input |
| Open Redirect | CWE-601 | User-controlled next parameter in redirect() |
| Log Injection | CWE-117 | Unsanitized user input in log messages |
| ReDoS | CWE-1333 | Catastrophic backtracking in regex patterns |
| And more | 20+ categories | See ansede-static --list-rules for the full catalog |
GitHub Action
# .github/workflows/security.yml
- uses: mattybellx/Ansede@v2.2.0
with:
path: src/
fail-on: high
upload-sarif: true
license-key: ${{ secrets.ANSEDE_LICENSE_KEY }}
Pricing
| Free | Pro | |
|---|---|---|
| Scans per day | 500 | Unlimited |
| Languages | 5 | 5 |
| Text & JSON output | ✓ | ✓ |
| SARIF (GitHub Code Scanning) | — | ✓ |
| SBOM (CycloneDX / SPDX) | — | ✓ |
| HTML dashboard | — | ✓ |
| CI/CD recipes | — | ✓ |
| Price | Free | £4.99 one-time or £49/year |
Features
- Incremental scanning — scan only changed files with
--incremental(git diff) or--incremental-sha256(content hash) - Baseline diffing — freeze legacy debt with
--baseline baseline.json, only fail on new findings - Auto-fix — apply safe inline fixes with
--apply-fixes - AI triage — suppress test/mock/fixture false positives with
--ai-triage - Parallel workers — speed up large repos with
--parallel - Entropy scanning — detect hardcoded secrets in string literals with
--entropy ansede.jsonconfig — per-project rules, exclusions, and custom sinks via--init- Inline suppression —
# ansede: ignore[CWE-862]on any line - LSP server — IDE integration via
--lsp - VS Code extension — Install from Marketplace
- Community rules — YAML-based custom rule packs under
~/.ansede/community_rules/ - SBOM generation — CycloneDX and SPDX output with
--sbom - Offline CWE explanations — enriched finding descriptions with
--explain - HTML reports — interactive browser dashboard with
--format html
Comparison
| ansede-static | Bandit OSS | Semgrep OSS | CodeQL CLI | |
|---|---|---|---|---|
| CVE Recall | 98.8% | ~65% | ~72% | ~88% |
| FP Rate | 3.6% | ~45% | ~30% | ~12% |
| Offline (no network) | ✓ | ✓ | ✗ | ✗ |
| Zero dependencies | ✓ | ✗ | ✗ | ✗ |
| Single binary (.exe) | ✓ | ✗ | ✗ | ✗ |
| IDOR / Auth bypass | ✓ | ✗ | Partial | Partial |
| Languages | 5 | 1 | 20+ | 7 |
| Install size | <5 MB | ~15 MB | ~200 MB | ~600 MB |
| Speed (scan_file) | 0.02s/100k LOC | 0.5s | 3s | 10s |
Contributing
git clone https://github.com/mattybellx/Ansede.git
cd Ansede
pip install -e ".[dev]"
pytest tests/ -q
See CONTRIBUTING.md for guidelines, docs/writing-rules.md for building custom rules, and docs/zero-friction-ci-rollout.md for adoption playbooks.
Built with ❤️ by Matty Bell. MIT licensed. Zero telemetry. No cloud dependency.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ansede_static-2.2.1.tar.gz.
File metadata
- Download URL: ansede_static-2.2.1.tar.gz
- Upload date:
- Size: 569.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ea3b0a75de6c2bee22c856e88dbb3af81159bdfa1478d6a14930c98ab35eb9a
|
|
| MD5 |
3c3ae196c007a733d2e065125039a145
|
|
| BLAKE2b-256 |
8308a67b1110406ffa5dcf8d8d1de193f6c74b7ef799a09d635e77fc13b54978
|
Provenance
The following attestation bundles were made for ansede_static-2.2.1.tar.gz:
Publisher:
publish.yml on mattybellx/Ansede
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ansede_static-2.2.1.tar.gz -
Subject digest:
5ea3b0a75de6c2bee22c856e88dbb3af81159bdfa1478d6a14930c98ab35eb9a - Sigstore transparency entry: 1566805974
- Sigstore integration time:
-
Permalink:
mattybellx/Ansede@a7a9433e46b3d04a9a4fd274f2e178482fadb5fa -
Branch / Tag:
refs/heads/master - Owner: https://github.com/mattybellx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a7a9433e46b3d04a9a4fd274f2e178482fadb5fa -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file ansede_static-2.2.1-py3-none-any.whl.
File metadata
- Download URL: ansede_static-2.2.1-py3-none-any.whl
- Upload date:
- Size: 571.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a79f311593177ab36606247a6749a735b89ffc2546277acac65fc382cacfdfc
|
|
| MD5 |
85494b3538f9e13783fc2bd9c71e7ace
|
|
| BLAKE2b-256 |
57e9c96a2d50e3c8d61604f842643fcf1f18fdd458bdb9e28bb8065a8d633b94
|
Provenance
The following attestation bundles were made for ansede_static-2.2.1-py3-none-any.whl:
Publisher:
publish.yml on mattybellx/Ansede
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ansede_static-2.2.1-py3-none-any.whl -
Subject digest:
3a79f311593177ab36606247a6749a735b89ffc2546277acac65fc382cacfdfc - Sigstore transparency entry: 1566806020
- Sigstore integration time:
-
Permalink:
mattybellx/Ansede@a7a9433e46b3d04a9a4fd274f2e178482fadb5fa -
Branch / Tag:
refs/heads/master - Owner: https://github.com/mattybellx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a7a9433e46b3d04a9a4fd274f2e178482fadb5fa -
Trigger Event:
workflow_run
-
Statement type: