Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Taint rules (`mode: taint`):
- `pattern-sources`, `pattern-sinks`, `pattern-sanitizers` — each entry may be a single `pattern:` string, a `pattern-either:` list (nested `pattern-either:` is supported and flattens recursively), or a `patterns:` AND-block (see below)
- **`patterns:` AND-blocks inside source/sink/sanitizer entries** — foxguard extracts all `pattern:` and `pattern-either:` sub-items as expressible node-shape matchers. Sub-items that are constraint-only operators (`pattern-inside:`, `pattern-not-inside:`, `pattern-not:`, `pattern-not-regex:`, `focus-metavariable:`, `metavariable-regex:`, `metavariable-comparison:`, `metavariable-pattern:`, `metavariable-analysis:`, `metavariable-type:`) are **dropped with a per-key warning**. This makes the compiled matcher **slightly broader** than the original Semgrep rule (the AND narrowing is lost), so foxguard may report findings that Semgrep would suppress. This broadening is intentional — it is better to over-report than to silently drop the rule. A `patterns:` block that produces no expressible matcher (only constraint-only sub-items) is warn-skipped without aborting sibling entries. If all source or sink entries are warn-skipped and none survive, the whole rule is skipped.
- **Parameter-as-source shape (`focus-metavariable` + a function-signature `pattern-inside`/`pattern`)** — a `pattern-sources` `patterns:` block of the form "a metavariable `$X` that is a parameter of an enclosing function" (i.e. a `focus-metavariable: $X` or bare `pattern: $X` together with a function-definition context whose parameter list contains `$X`) is recognised and compiled to an **any-function-parameter** taint source. Every parameter of every function/method in the file is seeded as tainted (matching Semgrep's any-parameter semantics for this shape). Supported for Python, JavaScript/TypeScript, Go, Java, C, Kotlin, Ruby, and PHP; C# carries the source inertly (no parameter-scope seeding). The recognition is bounded: the seed metavariable must genuinely appear inside the first parameter list of a function-definition pattern in the same block, so an unrelated focus metavariable (e.g. `focus-metavariable: $X` over `pattern: get_input($X)`) is *not* treated as a parameter source and falls through to the normal graceful-degradation extraction.
- **Focus-on-call-argument sink shape (`focus-metavariable` / bare `pattern: $X` + a call-context `pattern-inside`/`pattern`)** — the sink-side analog of the parameter-as-source shape. A `pattern-sinks`/`pattern-sanitizers` `patterns:` block of the form "the focused metavariable `$X` is an argument of a named call" (i.e. a `focus-metavariable: $X` or bare `pattern: $X` together with a call-context pattern such as `pattern-inside: $POOL.query($X, ...)`, `pattern: assert($X, ...)`, or `pattern: $DC.$METHOD($X, ...)`) is recognised and compiled to the existing `Call`/`MethodName` sink matcher for the call's callee. A concrete callee (`assert`, `redirect_to`, `YAML.load`) compiles to one `Call`; a `$RECV.$METH(...)` callee whose method is pinned by an anchored-alternation `metavariable-regex` (`^(query|execute)$`, `\b(include|require)\b`) compiles to one `MethodName` (or `Call`, for a `$FUNC(...)` callee) **per listed name**. These reuse the existing taint-gated call sinks, which only fire when a tracked-tainted value reaches the call's arguments — so the compiled sink is bounded to the concrete callee/method name AND tainted data, never an over-broad bare-node sink. The recognition is bounded: the focused metavariable must appear in the call's argument list (or the call must have a wildcard `...`/metavariable argument list), and a call whose callee/method is a free metavariable with **no** pinning `metavariable-regex` produces no matcher (we never invent a name) — such a block falls through to the normal graceful-degradation extraction. Supported for all taint languages (Python, JavaScript/TypeScript, Go, Java, C, Kotlin, Ruby, PHP); non-call contexts (binops, dict/object literals, subscript/property assignments) are not recognised by this shape.
- Supported `pattern:` shapes:
- bare identifier (`request`) — a source-only shape compiled to a parameter-name match
- dotted attribute chain (`request.data`, `request.json`) — nested chains flatten to `leftmost root + outermost field` (matches the engine's one-level attribute propagation)
Expand Down
38 changes: 19 additions & 19 deletions docs/parity/registry-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@ Measures how well foxguard's existing Semgrep-compat YAML loader (`src/rules/sem
| Rule files scanned | 2070 |
| Files with YAML parse errors | 0 |
| Total rules | 2144 |
| Rules loaded OK | 2028 (94.6%) |
| Rules skipped | 116 (5.4%) |
| Rules loaded OK | 2051 (95.7%) |
| Rules skipped | 93 (4.3%) |

**Headline load rate: 94.6%** (2028 / 2144 rules).
**Headline load rate: 95.7%** (2051 / 2144 rules).

## Skip-reason histogram

Sorted by frequency. The reason names the operator/key that blocks the rule today.

| Skip reason | Rules | % of skipped | % of all rules |
|---|---:|---:|---:|
| `mode: taint (unsupported shape)` | 102 | 87.9% | 4.8% |
| `generic mode (languages: [generic])` | 5 | 4.3% | 0.2% |
| `taint: pattern-propagators` | 5 | 4.3% | 0.2% |
| `mode: taint (unsupported language: apex)` | 3 | 2.6% | 0.1% |
| `mode: taint (unsupported language: swift)` | 1 | 0.9% | 0.0% |
| `mode: taint (unsupported shape)` | 80 | 86.0% | 3.7% |
| `generic mode (languages: [generic])` | 5 | 5.4% | 0.2% |
| `taint: pattern-propagators` | 4 | 4.3% | 0.2% |
| `mode: taint (unsupported language: apex)` | 3 | 3.2% | 0.1% |
| `mode: taint (unsupported language: swift)` | 1 | 1.1% | 0.0% |

## Priority order — operator/feature backlog

Matcher capabilities (implementable in `semgrep_compat.rs` / `semgrep_taint.rs`) ranked by how many registry rules each would unlock. These are independent of adding new language grammars. Build top-down.

| Rank | Capability to add | Rules unlocked |
|---:|---|---:|
| 1 | `mode: taint (unsupported shape)` | 102 |
| 2 | `taint: pattern-propagators` | 5 |
| 1 | `mode: taint (unsupported shape)` | 80 |
| 2 | `taint: pattern-propagators` | 4 |

Operator/feature gaps account for **107 rules** (5.0% of all rules). Closing the top of this list is the highest-leverage parity work that does not require a new parser.
Operator/feature gaps account for **84 rules** (3.9% of all rules). Closing the top of this list is the highest-leverage parity work that does not require a new parser.

## Priority order — missing language grammars

Expand All @@ -58,16 +58,16 @@ Language is the rule's first declared language (js/ts/jsx/tsx collapsed to `java

| Language | Total | Loaded | Skipped | Load rate |
|---|---:|---:|---:|---:|
| python | 423 | 402 | 21 | 95.0% |
| python | 423 | 406 | 17 | 96.0% |
| hcl | 359 | 359 | 0 | 100.0% |
| javascript | 243 | 221 | 22 | 90.9% |
| javascript | 243 | 229 | 14 | 94.2% |
| regex | 237 | 237 | 0 | 100.0% |
| java | 131 | 115 | 16 | 87.8% |
| generic | 103 | 98 | 5 | 95.1% |
| yaml | 100 | 100 | 0 | 100.0% |
| go | 97 | 86 | 11 | 88.7% |
| ruby | 92 | 76 | 16 | 82.6% |
| php | 63 | 49 | 14 | 77.8% |
| ruby | 92 | 83 | 9 | 90.2% |
| php | 63 | 53 | 10 | 84.1% |
| solidity | 50 | 49 | 1 | 98.0% |
| csharp | 48 | 42 | 6 | 87.5% |
| dockerfile | 39 | 39 | 0 | 100.0% |
Expand All @@ -94,10 +94,10 @@ Language is the rule's first declared language (js/ts/jsx/tsx collapsed to `java
- **generic**: `generic mode (languages: [generic])` (5)
- **go**: `mode: taint (unsupported shape)` (11)
- **java**: `mode: taint (unsupported shape)` (13), `taint: pattern-propagators` (3)
- **javascript**: `mode: taint (unsupported shape)` (22)
- **php**: `mode: taint (unsupported shape)` (14)
- **python**: `mode: taint (unsupported shape)` (21)
- **ruby**: `mode: taint (unsupported shape)` (15), `taint: pattern-propagators` (1)
- **javascript**: `mode: taint (unsupported shape)` (14)
- **php**: `mode: taint (unsupported shape)` (10)
- **python**: `mode: taint (unsupported shape)` (17)
- **ruby**: `mode: taint (unsupported shape)` (9)
- **solidity**: `mode: taint (unsupported shape)` (1)
- **swift**: `mode: taint (unsupported language: swift)` (1)

Expand Down
Loading