segrep-sast scanner
Opt-in native Tree-sitter SAST engine and rule system
Native static analysis engine for Segrep, built in Go with Tree-sitter parsing, YAML AST rules, and optional dataflow/taint analysis.
segrep-sast is an opt-in scanner alongside the default core set (Trivy, Semgrep, Syft, Gitleaks, Checkov). Semgrep remains the default SAST source; enable segrep-sast when you want Tree-sitter–based rules, structural dataflow paths, and per-finding AI enrichment.
Architecture
Repository
│
▼
File discovery (Go worker pool)
│
▼
Tree-sitter parsers (Go, JS, TS, Python)
│
▼
Normalized AST
├──────────────────┐
▼ ▼
Pattern engine Dataflow engine
│ │
└────────┬─────────┘
▼
Findings (JSON)
│
▼
packages/scanner-segrep-sast → scanner-core → CLI / worker / dashboard| Component | Location |
|---|---|
| Go engine | engines/sast/ |
| TypeScript adapter | packages/scanner-segrep-sast/ |
| Built-in rules | engines/sast/rules/ |
| Example config | docs/segrep.example.yaml |
| Vulnerable fixtures | apps/cli/fixtures/sast-vulnerable/ |
Quick start
Via Segrep CLI (recommended)
The Docker image and local dev builds include the segrep-sast binary.
# Opt-in scan (Semgrep is not run unless also listed)
pnpm segrep scan . --scanners segrep-sast
# Combine with other scanners
pnpm segrep scan . --scanners semgrep,segrep-sast
# JSON output for CI
pnpm segrep scan . --scanners segrep-sast --format jsonDocker:
docker run --rm -v "$(pwd):/repo:ro" security-scanner:local \
scan /repo --scanners segrep-sastStandalone engine
segrep-sast scan /path/to/repo \
--format json \
--rules ./engines/sast/rules \
--baseline=falseConfiguration
Engine-specific settings live in segrep.yaml at the repo root (or .segrep/sast.yaml). Scan policy (fail_on, allowlists, ignore paths) stays in .segrep/policy.yml — same as other scanners.
Copy the example:
cp docs/segrep.example.yaml segrep.yamlsegrep.yaml reference
| Field | Description |
|---|---|
languages | Languages to scan: go, javascript, typescript, python |
rules | Rule packs: builtin://owasp, builtin://secrets, builtin://injection, or paths to custom YAML |
exclude | Glob patterns skipped during file discovery |
dataflow.enabled | Enable taint analysis (default: true) |
dataflow.max_call_depth | Interprocedural call depth (default: 1) |
baseline.path | SQLite DB for baselines and suppressions |
workers | Parallel parse workers (default: CPU count) |
Policy integration
To run only segrep-sast in CI, add to .segrep/policy.yml:
scanners:
- segrep-sast
fail_on: highAllowlist SAST rule IDs by ruleId or fingerprint, same as Semgrep findings.
CLI reference (segrep-sast)
segrep-sast scan <root> [flags]
segrep-sast version| Flag | Description |
|---|---|
--config | Path to segrep.yaml (auto-detected if omitted) |
--rules | Built-in rules directory (default: next to binary or engines/sast/rules) |
--format | Output format (json only) |
--output | Write JSON to file instead of stdout |
--languages | Comma-separated language override |
--exclude | Additional exclude globs |
--workers | Worker pool size |
--changed-files | Comma-separated paths for incremental scan |
--no-dataflow | Disable taint analysis |
--baseline | Apply baseline filtering (true/false, default: true) |
--scan-id | Scan ID recorded in baseline DB |
Rule format
Rules are YAML files under engines/sast/rules/ or custom directories.
Pattern mode
Matches AST nodes directly (secrets, dangerous APIs):
id: eval-js
language: javascript
mode: pattern
pattern:
kind: call_expression
callee: eval
message: Use of eval() can lead to code injection
severity: HIGH
cwe: CWE-94Taint mode
Tracks user input from sources to sinks:
id: sql-injection-js
language: javascript
mode: taint
taint:
sources:
- kind: member_expression
name: req.body
- kind: member_expression
name: req.query
sinks:
- kind: call_expression
callee: query
sanitizers:
- kind: call_expression
callee: escape
message: User input reaches SQL query without sanitization
severity: HIGH
cwe: CWE-89Pattern constraints
| Field | Description |
|---|---|
kind | Tree-sitter node type (e.g. call_expression, identifier) |
name | Identifier or member path (e.g. req.body) |
text | Substring match on node text |
callee | Callee name for call expressions |
parent | Nested pattern for parent node |
child | Nested pattern for a child node |
ancestor | Nested pattern for any ancestor |
where | Field constraints (e.g. callee: query) |
Built-in rule packs
| Pack | Examples |
|---|---|
secrets | Hardcoded passwords, API key patterns |
owasp | SQL injection (taint), XSS sinks, path traversal |
injection | eval, exec, os.system, dangerouslySetInnerHTML |
Dataflow analysis
Phase 1 capabilities:
- Per-function control-flow from AST
- Intraprocedural taint propagation (assignments, direct data dependencies)
- Source / sink / sanitizer matching from YAML
taintrules - Same-file call graph
- One-level interprocedural taint (caller → callee → sink)
Limits (Phase 1): no pointer/alias analysis, closure capture across scopes, cross-package resolution, or reflection handling.
Taint findings include a dataflowPath in the JSON report:
{
"dataflowPath": [
{ "file": "src/api.js", "line": 10, "symbol": "req.body", "role": "source" },
{ "file": "src/api.js", "line": 12, "symbol": "query", "role": "sink" }
]
}JSON output schema
Version 1.0.0 — consumed by packages/scanner-segrep-sast:
{
"schemaVersion": "1.0.0",
"scanner": "segrep-sast",
"version": "0.1.0",
"root": "/repo",
"scannedAt": "2026-06-28T12:00:00Z",
"filesScanned": 42,
"rulesApplied": 18,
"findings": [
{
"id": "abc123...",
"ruleId": "sql-injection-js",
"title": "User input reaches SQL query without sanitization",
"severity": "high",
"filePath": "src/api.js",
"line": 12,
"snippet": "db.query('SELECT ...' + req.body.id)",
"cweId": "CWE-89",
"fingerprint": "...",
"category": "sast",
"dataflowPath": []
}
]
}AI enrichment
When segrep-sast findings are present and OPENAI_API_KEY is set, Segrep runs per-finding enrichment (explanation, exploit path, confidence, suggested fix). Results are stored in findings.raw_json.ai and shown in the dashboard on expandable rows.
Scan-level AI summaries (all scanners) still run via @segrep/ai-remediation.
SQLite storage (engine-local)
The Go engine uses SQLite for:
| Table | Purpose |
|---|---|
baselines | Suppress findings seen in prior scans |
suppressions | Rule/file/line ignore entries |
parse_cache | File content hash for incremental optimization |
Default path: .segrep/sast-baseline.db (per repo).
Platform scan history remains in PostgreSQL for the hosted dashboard — SQLite is not a replacement.
Development
Build the Go engine
Requires Go 1.22+ and CGO (Tree-sitter bindings):
cd engines/sast
CGO_ENABLED=1 go build -o segrep-sast ./cmd/segrep-sastWithout local Go, build via Docker:
docker run --rm -v "$(pwd)/engines/sast:/src" -w /src golang:1.23-bookworm \
bash -c "apt-get update -qq && apt-get install -y -qq gcc libc6-dev && \
CGO_ENABLED=1 go build -o segrep-sast ./cmd/segrep-sast"Run tests
# Go matcher tests
cd engines/sast && CGO_ENABLED=1 go test ./...
# TypeScript parser tests
pnpm nx run scanner-segrep-sast:testScan fixtures
./engines/sast/segrep-sast scan ./apps/cli/fixtures/sast-vulnerable \
--rules ./engines/sast/rules --baseline=falseDocker image
The multi-stage infrastructure/docker/Dockerfile builds segrep-sast and installs:
- Binary:
/usr/local/bin/segrep-sast - Rules:
/usr/local/share/segrep-sast/rules
Build arg: SEGREP_SAST_VERSION (default 0.1.0).
Dashboard
For segrep-sast findings, the scan detail page shows:
- Rule ID and line number
- Expandable dataflow path
- AI enrichment (explanation, confidence, suggested fix)
No database migration is required — fields are read from raw_json.
Comparison with Semgrep
| Semgrep (core) | segrep-sast (opt-in) | |
|---|---|---|
| Default scan | Yes (--scanners all) | No — explicit opt-in |
| Rule format | Semgrep YAML | Segrep YAML (AST/taint) |
| Parser | Semgrep (OCaml) | Tree-sitter (in-process Go) |
| Dataflow paths | Limited in unified model | Native dataflowPath |
| AI per-finding | No | Yes (when API key set) |
| Best for | Broad rule ecosystem | Custom rules, dataflow, AI UX |
Use both together when you want Semgrep's rule corpus plus Segrep-native dataflow and enrichment:
pnpm segrep scan . --scanners semgrep,segrep-sastRelated docs
- scan-product.md — CLI flags and CI integration
- add-scanner.md — how scanner packages plug into Segrep
- docker.md — image build and worker mode
- segrep.example.yaml — example engine config
- segrep-license.md — license compliance for dependencies
- segrep-secrets.md — native secret detection