Skip to content

Rules Overview

209 rules. 16 categories. All open-source YAML you can read, extend, or override. Built-in rules ship with the npm package and run on every scan automatically. Custom rules load from your project and run alongside them.

Each rule describes a single threat pattern. At scan time, the rule engine evaluates every rule against every file in a detected component. When the computed confidence score meets or exceeds the rule’s threshold, a finding is emitted.

Rules live in YAML files under a top-level rules: list. A single YAML file can contain many rules of the same or different categories.

rules/tool-poisoning.yaml (excerpt)
rules:
- id: tp-001
name: Hidden Instructions in Tool Descriptions
description: Detects invisible Unicode characters used to hide instructions
category: tool-poisoning
severity: critical
version: "1.0.0"
enabled: true
confidenceThreshold: 50
patterns:
- type: regex
pattern: '[\u200B\u200C\u200D\uFEFF]'
weight: 95
description: Zero-width space or BOM character
remediation: |
Remove all invisible Unicode characters from tool descriptions.
references:
- https://atlas.mitre.org/techniques/AML.T0051

FieldTypeRequiredDescription
idstringYesUnique rule identifier (e.g., tp-001, cred-042)
namestringYesShort human-readable name shown in scan output
descriptionstringYesWhat the rule detects and why it matters
categorystringYesOne of the 16 threat categories (e.g., tool-poisoning, secret-detection)
severityenumYescritical, high, medium, or low
versionstringNoRule version for change tracking (e.g., "1.0.0")
enabledbooleanNoSet to false to disable a rule globally. Defaults to true
confidenceThresholdnumberNoMinimum confidence (0–100) required to emit a finding. Defaults to 50
platformsstring[]NoRestrict the rule to specific platforms. Omit to apply to all
patternsarrayYesOne or more pattern objects (see below)
remediationstringNoFix guidance shown in reports and terminal output
referencesstring[]NoURLs to MITRE, OWASP, or other reference material

Each item in patterns has the following fields:

FieldTypeRequiredDescription
typeenumYesMatcher type — one of 7 values (see below)
patternstringYesThe pattern expression to match against file content
weightnumberYesContribution to the confidence score (0–100)
descriptionstringNoHuman label for this pattern, shown in verbose output
flagsstringNoRegex flags for regex type patterns (e.g., "i" for case-insensitive)

Applies a JavaScript regular expression to raw file content. The most common and flexible matcher.

- type: regex
pattern: 'AKIA[0-9A-Z]{16}'
weight: 100
description: AWS Access Key ID format

Applies a YARA-style string match (not the YARA binary). Supports case-insensitive strings, hex strings, and simple conditions.

- type: yara
pattern: '"bitcoin" nocase'
weight: 70
description: Reference to bitcoin wallet operations

Matches when the file content contains a reference to a specific file path — typically a sensitive credential or system file. Tilde expansion (~ → home directory) is applied before matching.

- type: file-access
pattern: "~/.aws/credentials"
weight: 90
description: Direct reference to AWS credentials file

Matches when a specific module or package import appears in the file. Handles Python import/from and JavaScript/TypeScript require/import statements.

- type: import
pattern: "paramiko"
weight: 60
description: SSH library — check for unauthorized tunnel creation

Matches URL or hostname patterns in file content. Used to detect requests to suspicious TLDs, tunneling services, or known malicious domains.

- type: network
pattern: "https?://[^/]*\\.(tk|ml|ga|cf|gq|xyz)/"
weight: 85
description: Request to suspicious top-level domain

Matches an exact string literal including surrounding quotes. Used for known-bad package names and exact-match indicators.

- type: string-literal
pattern: '"event-stream"'
weight: 90
description: event-stream — compromised to steal bitcoin wallets

Plain substring search against file content. No regex syntax. Fastest matcher — use it for simple keyword matches where regex overhead is not needed.

- type: text
pattern: "DISABLE_AUTH=true"
weight: 80
description: Authentication bypass flag set in config

SeverityMeaningTypical examples
criticalImmediate exploitable risk — block CIHidden instructions, hardcoded root credentials, auth bypass
highSignificant vulnerability — fix before mergeAPI key exposure, data exfiltration, unsigned package installs
mediumNoteworthy risk — fix in current sprintOverly broad permissions, weak JWT configuration
lowInformational — investigate when convenientDebug logging left enabled, overly verbose error messages

Use --severity to filter output to a minimum level:

Terminal
# Only critical and high findings
npx firmis scan --severity high
# All findings including low
npx firmis scan --severity low

Built-in rules ship inside the npm package at node_modules/firmis/rules/. They are loaded automatically on every scan. You do not need to reference them in config.

Custom rules are loaded from one of three places, in priority order:

  1. A path passed via --rules CLI flag:

    Terminal
    npx firmis scan --rules ./rules/custom/
  2. The rules key in your .firmis.config.yaml (or .firmis.config.json):

    .firmis.config.yaml
    rules:
    - ./rules/custom/my-rules.yaml
    - ./rules/custom/network-rules.yaml
  3. A rules/ directory at the project root — Firmis loads any *.yaml files found there automatically.

Custom rules are merged with built-in rules. Custom rule IDs that collide with built-in IDs override the built-in rule.