Skip to content

Custom Rules

gus edited this page Feb 27, 2026 · 1 revision

Custom Rules

Aguara supports custom detection rules written in YAML. Custom rules use the same engine as built-in rules and can use regex or literal string matching.

Rule Schema

rules:
  - id: CUSTOM_001              # Unique ID (convention: CUSTOM_NNN or YOUR_PREFIX_NNN)
    name: "Short descriptive name"
    description: "What this rule detects and why it matters"
    severity: HIGH               # CRITICAL, HIGH, MEDIUM, LOW, INFO
    category: custom             # Any string — used for grouping
    target: "*.md"               # Glob pattern for file matching
    match_mode: any              # "any" = match ANY pattern (OR), "all" = match ALL (AND)
    patterns:
      - type: regex              # "regex" or "contains"
        value: "pattern here"
      - type: contains
        value: "literal string"
    exclude_patterns:            # Optional: suppress match in context
      - type: contains
        value: "documentation"
    examples:
      true_positive:             # Must trigger the rule (used in self-tests)
        - "Example text that should match"
      false_positive:            # Must NOT trigger (used in self-tests)
        - "Example text that should not match"

Field Reference

Field Required Description
id Yes Unique rule identifier. Convention: CUSTOM_NNN or YOURPREFIX_NNN
name Yes Short human-readable name
description Yes What the rule detects and why
severity Yes CRITICAL, HIGH, MEDIUM, LOW, or INFO
category Yes Grouping label (e.g., custom, internal-policy)
target Yes File glob pattern (e.g., *.md, *.json, *.txt)
match_mode Yes any (OR across patterns) or all (AND — all must match)
patterns Yes List of pattern matchers
patterns[].type Yes regex or contains
patterns[].value Yes The pattern string
exclude_patterns No Patterns that suppress a match when found in context (matched line or up to 3 lines before)
examples.true_positive Yes Sample strings that must trigger the rule
examples.false_positive Yes Sample strings that must NOT trigger

Pattern Types

contains

Case-insensitive literal string match. Fast and simple.

patterns:
  - type: contains
    value: "internal.mycompany.com"

regex

Regular expression match using Go's regexp package.

patterns:
  - type: regex
    value: "https?://internal\\.mycompany\\.com/api"

Important: Go's regexp does NOT support Perl-style lookaheads ((?!...)) or lookbehinds ((?<=...)). Use character class restrictions or match_mode: all with multiple patterns instead.

Tip: Test your regex at regex101.com using the Go (RE2) flavor.

JSON pattern tips

When matching JSON keys that may or may not be quoted:

- type: regex
  value: "[\"']?api_key[\"']?\\s*[:=]"

Match Modes

any (OR logic)

The rule triggers if any one pattern matches:

match_mode: any
patterns:
  - type: contains
    value: "internal-api.company.com"
  - type: contains
    value: "staging.company.com"

all (AND logic)

The rule triggers only if all patterns match (useful for multi-condition detection):

match_mode: all
patterns:
  - type: contains
    value: "curl"
  - type: regex
    value: "\\$\\(cat\\s+/etc/"

Exclude Patterns

Reduce false positives by suppressing matches in specific contexts:

exclude_patterns:
  - type: contains
    value: "## Installation"
  - type: contains
    value: "documentation"

When a match is found, Aguara checks the matched line and up to 3 lines before it. If any exclude pattern matches that context, the finding is suppressed.

Using Custom Rules

CLI flag

aguara scan . --rules ./my-rules/

Configuration file

In .aguara.yml:

rules_dir: ./my-rules

Directory structure

Custom rules are YAML files in a directory. Each file can contain one or more rules:

my-rules/
  internal-apis.yaml
  compliance.yaml
  team-policies.yaml

Example: Internal API Detection

rules:
  - id: INTERNAL_001
    name: "Internal API endpoint"
    description: "Detects references to internal APIs that should not appear in agent skills"
    severity: HIGH
    category: internal-policy
    target: "*.md"
    match_mode: any
    patterns:
      - type: regex
        value: "https?://internal\\.mycompany\\.com"
      - type: contains
        value: "api.internal"
    exclude_patterns:
      - type: contains
        value: "## API Documentation"
    examples:
      true_positive:
        - "Fetch data from https://internal.mycompany.com/api/users"
      false_positive:
        - "Our public API is at https://api.mycompany.com"

Self-Testing

Every rule must include true_positive and false_positive examples. The test suite validates these automatically when you run:

make test

If a true_positive doesn't trigger the rule or a false_positive does, the test fails. This ensures rules work correctly as the engine evolves.

Clone this wiki locally