Skip to content
lambdasecPublic

Repository files navigation

Frame

The sound, open SAST for modern apps: code, dependencies, secrets, infrastructure and AI, in one tool

Tests PyPI version PyPI Downloads GitHub Marketplace License

Frame finds vulnerabilities by following attacker data through your code, across functions, files and layers, and proves each finding with a solver instead of pattern-matching. One open tool covers what a modern app needs scanned: the code, its dependencies, its secrets, its infrastructure and its AI calls. It runs offline, and the same soundness that keeps false alarms down lets it prove a fix actually removed the bug.

XBOW / ZeroPath AI-SAST benchmark: Frame 78.8% technical and 87.5% business-logic detection, level with ZeroPath and ahead of Semgrep, Snyk and Bearer

Where a team runs Semgrep for code, Snyk or Endor Labs for dependencies, gitleaks for secrets and checkov for infrastructure, Frame is one tool that does all of it, proves what it reports, and stays free and local. It is a genuine alternative to Semgrep, Snyk, Endor Labs, Veracode and ZeroPath: open where they are closed, sound where they pattern-match, and complete where they cover one layer. The numbers are in Benchmarks.

What Frame scans

  • Code, across files, in five languages: Python, JavaScript/TypeScript, Java, C# and C/C++. A request that enters a controller and reaches a query three files away is one finding, not a lead. 100+ finding types, from SQL injection and SSRF to IDOR and C/C++ memory safety, each proved by taint or by the separation logic engine. 110 framework packs (Flask, Django, Spring, ASP.NET, Express, and more), plus your own stack in one TOML file.
  • Broken access control, with an agent the engine directs: IDOR, missing authorization, privilege escalation and mass assignment turn on intent, so --hunt-authz sends a model through the app unit by unit, with the engine planning the work and answering its questions. Every handler gets a verdict, and what the code cannot decide is reported as unresolved rather than called safe. 22 of 30 real advisories on BAC-Bench, ahead of ABSENTIA's 19; CodeQL and Semgrep find none.
  • Dependencies, by reachability: lockfiles of 11 ecosystems plus C/C++ and vendored copies, matched against OSV offline, ranked by whether attacker data actually reaches the vulnerable function, with upgrades Frame plans, applies and verifies against your tests, plus licence policy, SBOM and VEX.
  • Secrets, including git history: credential-named values and 15 providers' key formats (AWS, GitHub, Stripe, OpenAI, and more), in code and in every commit the history ever added, with optional live verification against the provider's own API so a real leak is told from a test fixture.
  • Infrastructure as code: Kubernetes against the Pod Security Standards (matching the admission controller's own evaluator), Dockerfiles as BuildKit parses them, Terraform as HCL evaluates it (AWS, Azure, Google Cloud), and CloudFormation with its intrinsic functions. Every policy is decided with Z3, and what depends on values the files do not give is reported as undecided, not guessed.
  • Containers: OS packages read from an image's layers (Debian, Ubuntu, Alpine, RHEL and more) and matched against the distributions' own advisories.
  • AI applications: prompt injection, model output reaching a sink, and MCP servers, including hidden instructions in tool metadata that the person approving the tool cannot see, mapped to the OWASP LLM Top 10.

Why it is different

  • Sound, not pattern-based: findings are proved by a solver (its own separation logic engine on Z3: entailment, frame inference, bi-abduction, countermodels), so there are fewer false alarms and a fix can be proved to remove the bug.
  • Proof-carrying findings: a finding the solver proves reachable becomes a runnable test that triggers it in your own code, raised to the exploit-confirmed level when the fault is actually observed, a true positive by construction. frame scan --confirm-proofs compiles C integer-overflow and out-of-bounds findings with the solver's own inputs under AddressSanitizer and UndefinedBehaviorSanitizer (no model). frame exploit --deps drives your app to the sink for injection flows and vulnerable dependency calls in Python, JavaScript/TypeScript, Java and C#, confirmed by a spy that only counts data arriving through your own code; with --check-fixed the same test proves a fix removed the flow. (AI layer)
  • Open rules and advisories, as data: framework packs and the full advisory database ship as versioned public datasets, lambdasec/frame-kb and lambdasec/frame-advisories (rebuilt daily), updated between releases and pinnable for air-gapped CI. Nothing in them runs.
  • Built for the AI-coding era: scan only what changed, baseline what you accept, verify that a fix removed the bug, diff two scans to see what a pull request introduced, and fail CI only on proven findings (--fail-on-evidence). Reports as SARIF, JSON, Markdown (pull-request comments), GitLab SAST and SonarQube; a GitHub Action, a pre-commit hook, and an MCP server for Claude Code, Codex, Cursor and other coding agents.
  • Runs on open models, local or hosted: an optional LLM layer adds recall for business-logic and authorization flaws, triages, and proposes fixes the sound core then verifies; it works with any OpenAI-compatible model, including on-device.
  • One config file: every setting in .frame.toml (or [tool.frame] in pyproject.toml), checked strictly, with one precedence order: flag, then environment variable, then file, then default. Example configs.

Quick start

pip install "frame-security[scan]"
frame scan src/

A three-file Flask app, where the request enters in app.py and the query runs in services/orders.py:

# shop/app.py
@app.route("/orders")
def list_orders():
    customer = request.args.get("customer", "")
    return jsonify(orders.for_customer(customer))

# shop/services/orders.py
def for_customer(name):
    cur.execute("SELECT * FROM orders WHERE customer = '" + name.strip() + "'")
$ frame scan benchmarks/exemplars/quickstart --root benchmarks/exemplars/quickstart
1. [CRITICAL] 🔴 sql_injection
   Location: benchmarks/exemplars/quickstart/shop/services/orders.py:8:4
   Description: Tainted data from 'customer' flows to sql sink
   CWE: CWE-89
   Data flow: shop/app.py:11 -> shop/services/orders.py::for_customer(name)
...
Scanned 4 files: 2 findings (2 critical)

Use a placeholder query, or wrap the value in int(), and the finding goes away.

For dependencies (advisories come from lambdasec/frame-advisories, cached once, then offline):

frame kb pull --advisories            # cache the advisories once (then everything runs offline)
frame deps --vulns                    # vulnerable dependencies, and whether your code calls the vulnerable function
frame deps --vulns --apply --relock   # upgrade, re-lock, report what is left
frame scan . --sca                    # attacker data reaching a vulnerable function, at the call site

For secrets, infrastructure and a repo inventory:

frame scan . --verify-secrets         # credentials in code, checked live against the provider
frame history .                        # credentials anywhere in the git history
frame iac .                            # Kubernetes, Dockerfiles, Terraform, CloudFormation (or frame scan . --iac)
frame inventory .                      # languages, frameworks, dependencies, IaC, containers, AI SDKs, MCP tools

With a model (any OpenAI-compatible endpoint, local or hosted; AI layer):

export FRAME_LLM_BASE_URL=http://localhost:47317/v1  FRAME_LLM_MODEL=<model>   # or [llm] in .frame.toml
frame scan src/ --ai                  # LLM detection and triage on top of the engine
frame scan . --hunt-authz             # hunt for broken access control, a verdict on every handler
frame fix app.py --guidance findings.json --diff   # patch, re-scan, confirm

Benchmarks

OWASP score by language: Frame 80.9 Python, 81.5 Java, 80.3 C#, 54.4 C/C++, 43.0 JavaScript; Semgrep 4.5, 15.7, 14.2, -14.9, 10.0

Cross-file flows: Frame finds 10/10 in four real apps with 0 false alarms on 33 safe twins; CodeQL 7/10 with 5 false alarms; Semgrep stock packs 7/10 with 21

BAC-Bench, 30 real broken-access-control advisories: Frame detects 22/30 and pairs 11/30; ABSENTIA 19/30 and 17/30; a single agent 3/30; CodeQL and Semgrep 0/30

Benchmark What it measures Frame Comparison
XBOW / ZeroPath AI-SAST on 39 web-vuln apps detect 78.8%, FP 26.3% ZeroPath 80% / 25%, Semgrep 54% / 45%
Endor Labs corpus 193 vulns in 5 production apps recall 0.67, precision 0.51 Semgrep 0.52 / 0.40
BAC-Bench Broken access control, 30 real advisories 22/30 found, 11 paired ABSENTIA 19 / 17, CodeQL and Semgrep 0
RealVuln IDOR/BOLA Broken authorization, 4 real apps 6/8 found, precision 1.00 0 false positives on safe controls
CVE-Bench Detect, exploit, fix on 10 live CVEs 5 / 4 / 4 of 10 each stage verified on a live target
SusVibes 181 real-CVE Python pairs recall 0.14, precision 0.56 Semgrep 0.06 / 0.55
Cross-file exemplars Hand-labelled precision on 4 real apps 98% CodeQL 95%

Methods and every suite, including SL-COMP for the engine, are in benchmarks/README.md.

Documentation

The documentation index lists every guide.

Usage Scanning, baselines and verify, the GitHub Action, pre-commit hook, MCP server and agent skill, suppressions, configuration, the knowledge base, every command and flag, environment variables, Python API
Dependencies Supported ecosystems, advisories, reachability, upgrade plans, code mitigation, licences, SBOM, VEX, container images, CI
Coverage Cross-file resolution per language, supported frameworks, writing a pack, every vulnerability class
Secrets Hardcoded credentials by name and by provider format, git-history scanning, live verification with each provider and exactly what it sends
AI app security Prompt injection, model output as taint, MCP tools and tool-metadata attacks, the OWASP LLM Top 10
Infrastructure as code Kubernetes, Dockerfiles, Terraform and CloudFormation, how close they are to Kubernetes, BuildKit and HCL, writing policies, how Z3 decides them
AI layer Detect, triage, the authorization hunt, exploit, fix, and proof-carrying reproductions, with any OpenAI-compatible model, including on-device
Separation logic engine The prover under the scanner: capabilities, syntax, CLI, Python API, SL-COMP results
Roadmap What is built, and what is next: data growth, and widening reproduction to sinks that are not injected interfaces
Examples Runnable walkthroughs with real output: dependencies end to end, mitigations, adapting to a breaking upgrade, secrets, Kubernetes, AI apps and MCP servers, configuration files
Exemplars The quickstart app, a vulnerable and safe app per framework, and the cross-file comparison
Open datasets Framework packs and spec tables, lambdasec/frame-kb; the OSV advisory database rebuilt daily, lambdasec/frame-advisories

Community

  • Ask a question or share an idea in Discussions.
  • Report a false positive or a missed vulnerability with the issue forms: they are the most useful reports a scanner gets.
  • Report a vulnerability in Frame itself privately, as described in the security policy, which also lists exactly what Frame runs and sends (by default: no project code executed, nothing fetched during a scan, no telemetry).
  • What changed in each release is in the changelog.

Contributing

Contributions are welcome, and most of what Frame knows is data anyone can extend: a framework is one TOML pack plus a vulnerable and safe app pair. CONTRIBUTING.md covers setup, the principles every change follows, and how to add a pack, a source or sink, a flag or a parser.

pip install -e ".[dev]"
python -m pytest tests/ -n auto
ruff check frame tests benchmarks

License

Apache 2.0