Skip to content

Custom Rules

codescan supports user-defined rules via JSON files. Custom rules use the same engine as built-in rules and appear alongside them in output.

Loading Custom Rules

bash
# Single file
codescan --rules-file ./rules/my-rules.json .

# Multiple files
codescan --rules-file ./rules/secrets.json --rules-file ./rules/compliance.json .

You can also specify files in codescan.toml:

toml
[rules]
extra_files = ["./rules/internal.json", "./rules/compliance.json"]

JSON Format

Custom rules files accept two formats:

Array Format

json
[
  {
    "id": "CUSTOM001",
    "category": "CUSTOM",
    "severity": "error",
    "pattern": "(?i)\\binternal_secret\\b",
    "message": "Internal secret string found",
    "help": "Remove this before committing"
  }
]

Object Format

json
{
  "rules": [
    {
      "id": "CUSTOM001",
      "category": "CUSTOM",
      "severity": "error",
      "pattern": "(?i)\\binternal_secret\\b",
      "message": "Internal secret string found",
      "help": "Remove this before committing"
    }
  ]
}

Rule Fields

FieldRequiredDescription
idYesUnique rule identifier (e.g. COMPANY001)
categoryYesCategory name (e.g. SECRET, CUSTOM, COMPLIANCE)
severityYes"error", "warning", or "info"
patternYesRegular expression (Rust regex crate syntax)
messageYesHuman-readable finding description
helpNoOptional remediation hint

Pattern Syntax

Patterns use the Rust regex crate, which is linear-time and does not support:

  • Lookaheads / lookbehinds ((?=...), (?!...), (?<=...), (?<!...))
  • Backreferences (\1)

Useful Features

(?i)          Case-insensitive flag
\b            Word boundary
(?:...)       Non-capturing group
[^abc]        Negated character class
\w \d \s      Character classes
{3,8}         Quantifier range

Escaping in JSON

In JSON strings, backslashes must be doubled:

RegexJSON string
\b"\\b"
\d+"\\d+"
\("\\("

Examples

Compliance Rules

json
[
  {
    "id": "COMPLIANCE001",
    "category": "COMPLIANCE",
    "severity": "error",
    "pattern": "(?i)\\b(ssn|social.?security.?number)\\b",
    "message": "Potential Social Security Number reference",
    "help": "PII data must not appear in source code"
  },
  {
    "id": "COMPLIANCE002",
    "category": "COMPLIANCE",
    "severity": "warning",
    "pattern": "(?i)\\b(credit.?card|card.?number|cvv|ccv)\\b",
    "message": "Potential credit card data reference",
    "help": "Handle cardholder data according to PCI-DSS requirements"
  }
]

Organization-Specific Secrets

json
[
  {
    "id": "ORG001",
    "category": "SECRET",
    "severity": "error",
    "pattern": "ACME_[A-Z0-9_]{16,}",
    "message": "ACME internal token pattern detected",
    "help": "Rotate this token and store it in the secrets vault"
  }
]

Infrastructure Rules

json
[
  {
    "id": "INFRA010",
    "category": "INFRA",
    "severity": "warning",
    "pattern": "(?i)10\\.internal\\.corp",
    "message": "Internal hostname hardcoded",
    "help": "Use service discovery or environment variables"
  }
]

Listing All Rules

To see all built-in and custom rules:

bash
codescan --list-rules
codescan --list-rules --rules-file ./my-rules.json

Overriding Built-in Severity

Custom rules cannot override built-in rule severity directly, but you can use codescan.toml:

toml
[rules.severity_overrides]
CUSTOM001 = "warning"