-
Notifications
You must be signed in to change notification settings - Fork 15
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.
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 | 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 |
Case-insensitive literal string match. Fast and simple.
patterns:
- type: contains
value: "internal.mycompany.com"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.
When matching JSON keys that may or may not be quoted:
- type: regex
value: "[\"']?api_key[\"']?\\s*[:=]"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"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/"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.
aguara scan . --rules ./my-rules/In .aguara.yml:
rules_dir: ./my-rulesCustom 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
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"Every rule must include true_positive and false_positive examples. The test suite validates these automatically when you run:
make testIf 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.
GitHub | Releases | Aguara Watch | Go Docs
Getting Started
Usage
Rules
Developer
Reference