Static analysis matches patterns against your application’s own source code — a SQL statement built from string concatenation, eval() on untrusted input, TLS verification disabled in code — rather than against a package list (vulnerability scanning) or a declared resource (infrastructure scanning). It runs as part of a repository scan, and it is off until you configure it.

Enabling it

Setting SAST_RULES alone is not enough: the analyser this feature runs is a separate program, and it is deliberately not installed in the published trustowl-backend image (see below). With no working analyser, the worker reports static analysis as disabled at startup and in /system/status rather than failing every repository scan — see Troubleshooting scans.
/app/rules/sast is TrustOwl’s own vendored ruleset, already present in the published image (just YAML pattern files — see below for why those ship even though the analyser does not). Point SAST_RULES at your own path instead, or a directory, to run additional or different rules.

Why the analyser is not in the published image

The static-analysis engine (Semgrep) is licensed LGPL-2.1-or-later, and this product’s licence gate treats that as strong copyleft — the published trustowl-backend image carries none, by policy, and that stays true here. Instead, backend/Dockerfile.sast is a build recipe: the published image, plus a pinned Semgrep and git, that you build yourself. Building it is an explicit choice about the licence terms you are accepting for your own deployment, rather than a decision made silently on your behalf:
Run the worker from trustowl-backend:sast with SAST_RULES set, and repository scans that request sast will run it. The API image can stay the published one — only the worker needs the analyser.

Language coverage

The vendored ruleset ships one rule per language today, each proven against a real vulnerable fixture and a real clean fixture with the real analyser (backend/internal/e2e/sast_language_matrix_e2e_test.go): This is a starting point, not a comprehensive scan of any language’s vulnerability classes. See What this does not cover.

The ruleset version

Every static-analysis finding carries a ruleset_version — a content digest of the rule files that produced it, visible on the finding’s evidence in the dashboard and the API. It answers “was this checked against the current rules” without naming the analyser. It changes only when a rule’s content changes, never on an ordinary rescan, and it is evidence rather than identity: editing a rule does not re-open or duplicate findings it already produced.

Suppressing a finding

Two ways, at different scopes:
  • Inline, at the match. Add a // nosemgrep: <rule-id> (or the language’s own comment syntax) on the matched line, or a bare // nosemgrep to suppress every rule there. The analyser drops the match before it ever reaches TrustOwl, and the comment itself — reviewed in the same commit that introduced it — is the audit trail.
  • After the fact, in TrustOwl. Suppress the finding from its detail page or the findings list, with a required reason and an optional expiry. This works the same way for every finding kind; see Findings and their lifecycle.

What this does not cover

Said explicitly, because a scanner that is silent about its own gaps reads as having none:
  • No per-tenant custom rules. SAST_RULES is one deployment-wide configuration; there is no UI or API to add a rule per organisation.
  • No SARIF import or export.
  • No autofix and no pull-request annotations. A finding is reported to TrustOwl; nothing comments on or edits your pull request.
  • No taint tracking or cross-file dataflow in the vendored ruleset — each rule is a single-pattern match. Semgrep OSS supports more than this; the vendored rules do not yet use it.
  • Registry rule packs stay off by default (SAST_REGISTRY_ENABLED=false). Semgrep’s own hosted packs carry licence terms of their own to evaluate before enabling them, and a registry fetch makes a scan’s ruleset depend on what a third party served that day — the opposite of a reproducible verdict.

Next

  • Scanning — worker placement, concurrency, and the registry policy that governs every scan target.
  • Troubleshooting scans — what /system/status says when the analyser is configured but not installed.