Open-Source Wikis

/

Gitleaks

/

Features

/

Composite (multi-part / required) rules

gitleaks/gitleaks

Composite (multi-part / required) rules

Introduced in v8.28.0. A composite rule is a primary rule that only fires when one or more auxiliary rules also produce findings within a configurable proximity. Useful for "AWS access key paired with a secret access key on the same line" style patterns.

Per the README, this is an experimental feature: "It's subject to change so don't go sellin' a new B2B SaaS feature built on top of this feature."

TOML shape

[[rules]]
id = "aws-keypair"
description = "AWS access key + secret key on the same line"
regex = '''AKIA[0-9A-Z]{16}'''
keywords = ["AKIA"]

  [[rules.required]]
  id = "aws-secret-access-key"
  withinLines = 0
  withinColumns = 80

The required entry references another rule by ID. withinLines and withinColumns constrain the proximity of the auxiliary match to the primary match.

Proximity semantics

withinLines withinColumns Behavior
unset unset Fragment-level match: required finding can be anywhere in the same fragment
N unset Within N lines vertically
unset N Within N columns horizontally
N M Both (rectangular search area, both must be satisfied)

The README has ASCII-art diagrams for each case. Implementation is Detector.withinProximity in detect/detect.go:

if requiredRule.WithinLines == nil && requiredRule.WithinColumns == nil {
    return true   // fragment-level
}
if requiredRule.WithinLines != nil && abs(primary.StartLine - required.StartLine) > *requiredRule.WithinLines {
    return false
}
if requiredRule.WithinColumns != nil && abs(primary.StartColumn - required.StartColumn) > *requiredRule.WithinColumns {
    return false
}
return true

The proximity uses StartLine / StartColumn for both findings — i.e., the upper-left corner of each match's location.

Implementation flow

graph TD
    P[primary findings from rule R] --> RR[for each rule R.RequiredRules]
    RR --> Recurse[detectRule on auxiliary rule<br/>fragment.InheritedFromFinding=true]
    Recurse --> Coll[collect all auxiliary findings]
    Coll --> Loop[for each primary finding]
    Loop --> Prox[filter aux findings by withinProximity]
    Prox --> Has{at least one aux<br/>per required rule?}
    Has -->|no| Drop[drop primary finding]
    Has -->|yes| Attach[attach aux findings,<br/>emit primary]

processRequiredRules in detect/detect.go does this:

  1. Pre-collect all auxiliary findings once per required rule (so an N×M loop becomes N+M).
  2. Mark the fragment as InheritedFromFinding = true before recursing into detectRule for the auxiliary, which prevents an auxiliary that is itself composite from re-recursing.
  3. For each primary finding, filter pre-collected auxiliaries by withinProximity.
  4. hasAllRequiredRules checks that we have at least one auxiliary for every entry in R.RequiredRules. If any required rule yielded zero in-proximity auxiliaries, the primary is dropped.
  5. Surviving primary findings get the auxiliary findings attached via Finding.AddRequiredFindings.

SkipReport

Auxiliary rules often only exist to validate a primary rule and shouldn't produce standalone findings. Set skipReport = true on a rule to keep it out of the main findings list:

[[rules]]
id = "aws-secret-access-key"
description = "(used only as auxiliary)"
regex = '''(?i)aws.{0,20}(secret|access).{0,20}[A-Za-z0-9/+=]{40}'''
skipReport = true
keywords = ["aws"]

Inside detectRule, the very first guard is if r.SkipReport && !fragment.InheritedFromFinding { return findings } — so the rule still runs when called from processRequiredRules (where InheritedFromFinding is true), but is silent for top-level scanning.

Output

When a composite rule fires, the primary finding's requiredFindings slice is populated. In verbose terminal output, Finding.PrintRequiredFindings (report/finding.go) prints:

Required:    aws-secret-access-key:42:wJalrXU...truncated...

In structured output formats, RequiredFinding is a report type that's currently kept private (requiredFindings is unexported on Finding) per the comment "keeping private for now to during experimental phase". Library consumers can call f.AddRequiredFindings(...) but cannot read them back yet.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Composite (multi-part / required) rules – Gitleaks wiki | Factory