Pattern

AST and symbolic matching

any/all

FieldDescription
anyMatch when at least one condition is satisfied
allRequire every listed condition

Example 1: match a call to either method_1 or method_2.

yaml
any:
  - pattern: method_1($$$)
  - pattern: method_2($$$)

Example 2:

yaml
all:
  - pattern: method_1($$$)
  - inside:
      pattern: $F(async ($REQ, $RES) => {$$$})
  - inside:
      pattern: for($IN = $S; $$$; $$$) {$$$}

not

Use not to exclude a pattern.

yaml
pattern: $REQ.META
not:
  inside:
    any:
      - pattern: $REQ.META.CONTENT_LENGTH
      - pattern: $REQ.META.CONTENT_TYPE

regex

Use a regular expression for matching.

Example: find a polyfill.io URL by applying a regular expression to the string captured in STR.

yaml
pattern: |
  "$STR"
metavar:
  name: STR
  eq:
    regex: '(?:https?:)?//(?:[^/]*\.)?polyfill\.io'

The following code matches:

javascript
async function loadPolyfill() {
  await import("https://polyfill.io/v3/polyfill.min.js"); // Matched
}

async function loadPolyfillWithQuote() {
  await import('https://polyfill.io/v3/polyfill.min.js'); // Matched
}

Inside

Use inside to match a pattern within another pattern.

Example: find a target call within the someMethod method.

yaml
inside:
  pattern: public void someMethod($$$){$$$}
pattern: target($$$)

The following code matches:

java
public class Example {
    public void someMethod(String arg) {
        target("something"); // Matched
    }
}

Metavariable

Prefix metavariables with $.

Metavariable type Description
$VAR Store a matched AST node as VAR
$$$VARS Capture multiple AST nodes
$$$ Match multiple nodes, including multiline content

Use $$$ in a multiline pattern:

yaml
pattern: |
  public void someMethod($$$) {$$$}

You can also apply patterns to captured metavariable values. The following rule matches when NOVERIFY is a hardcoded string or true.

yaml
pattern: $JWT.decode($TOKEN, $SECRET, $NOVERIFY, $$$)
metavar:
  name: NOVERIFY
  eq:
    any:
      - pattern: |
          "$$$_STR"
      - pattern: "true"

matcher

matcher provides built-in classification of common sensitive names. It avoids repeating large expressions such as password|token|api_key|client_secret... in multiple rules.

Supported values:

  • password
  • secret
  • pii
  • sensitive

Example:

yaml
metavar:
  name: FIELD
  eq:
    matcher: secret

For name/key-shaped nodes, matcher removes quotes and splits camelCase, snake_case, kebab-case, dotted names, and numeric suffixes into tokens. It does not classify an entire large expression as a sensitive name. It classifies names and keys, rather than literal PII values such as actual email addresses or phone numbers.

It can also be used in regex_pair.left.

yaml
regex_pair:
  left:
    matcher: secret
  right: "[0-9a-zA-Z\\-_.=\\~@]{10,150}"

constantValue

Use constantValue in JavaScript, TypeScript, and TSX to apply a nested rule to a local constant value. It is opt-in: existing pattern, metavar, resolvedName, and taint behavior do not change unless the rule explicitly uses constantValue.

Basic form:

yaml
constantValue:
  matches: unsafe-origin-value

The same form can be used under metavar.

Behavior:

  • Apply the nested rule directly to the current node first.
  • For an identifier, find the nearest value binding in lexical scope and apply the nested rule to its initializer.
  • Support const, typed const, and initialized let/var. A let or var reassigned in the same scope is not treated as constant.
  • Support string, number, Boolean, and regex literals; new RegExp(...) with literal arguments; arrays/objects composed of supported constant expressions; and bounded identifier alias chains.
  • This feature is limited to JavaScript, TypeScript, and TSX.

Example: identify a CORS origin that is an unsafe regex directly or through a local constant.

yaml
utils:
  unsafe-origin-value:
    any:
      - kind: regex
        regex: "[a-zA-Z0-9\\-]\\."
      - all:
          - pattern: new RegExp($PATTERN, $$$)
          - has:
              kind: string
              regex: "[a-zA-Z0-9\\-]\\."

rule:
  pattern: "cors({ origin: $ORIGIN, $$$ })"
  metavar:
    name: ORIGIN
    eq:
      constantValue:
        matches: unsafe-origin-value

This matches by following the regex literal that initializes origin:

javascript
const origin = /example\./;
cors({ origin });

This does not treat origin as constant because it is reassigned:

javascript
let origin = /example\./;
origin = safeOrigin;
cors({ origin });

Use resolvedName to check the package identity of an imported or required function/object. Use constantValue alongside it when checking a local constant initializer used as an argument or configuration value.

compare

Use compare for calculations and conditions on metavariable values.

  • Boolean
  • Number
    • Hexadecimal, binary, and octal forms, such as 0x, 0b, and 0o

Example: a permission-value check. The expression tests whether BIT falls within the specified numeric ranges.

yaml
any:
  - pattern: os.chmod($FILE, $BIT, $$$)
  - pattern: os.fchmod($FILE, $BIT, $$$)
  - pattern: os.lchmod($FILE, $BIT, $$$)
compare: ( $BIT >= 0o650 && $BIT < 0o100000 ) || $BIT >= 0o100650