← Back to PR Bug Fix Database
5
Medium
PR-gitleaks-2122

Fix: withinColumns Should Not Compare Columns Across Different Lines

MediumRepo: gitleaks/gitleaksDate: July 6, 2026
PR FixgitleaksBug FixEdge CaseSecret Scanning

// The Bug

Fixed gitleaks/gitleaks#2122 — a 4-line fix resolving a column comparison bug in gitleaks secret scanning where withinColumns incorrectly compared column positions across different code lines.

Repository
gitleaks/gitleaks
Issue
Status
PR submitted
Fix Scope
4 lines changed in the secret detection logic
Description
The `withinColumns` function in gitleaks's secret detection engine incorrectly compares column positions across different scan lines rather than restricting comparison to the same scan line. This causes false positive matches when separate but similar secrets appear on adjacent lines — the scanner conflates their column ranges.

// Root Cause

The edge case occurs in the column-range comparison logic when gitleaks processes multi-line output. The `withinColumns` utility is designed to check whether two detected secrets overlap within the same source line. The bug: when comparing secret A on line 1 (columns 5-20) with secret B on line 2 (columns 3-15), the function returned `true` because the column ranges overlapped — ignoring that they belong to different lines entirely.

In a codebase like gitleaks that processes thousands of lines per scan, this pattern is easy to miss because standard test suites use single-line fixtures. The fix adds an explicit line-number equality check before comparing column ranges.

**Impact**: Users scanning files with multiple similar secrets on consecutive lines see deduplication happening incorrectly — secrets that should be reported separately are merged into one, or a legitimate secret is suppressed because a different-line match was (incorrectly) considered a duplicate.

// The Fix

Diff showing the exact changes made to fix the bug.

if a.StartLine != b.StartLine {
    return false
}

// Pattern & Takeaways

### How to Apply This Fix

When reviewing your own codebase for similar cross-dimensional comparison bugs, follow this checklist:

1. **Audit comparison functions** — Search for functions that compare sub-ranges (columns, indices, offsets) without validating their parent coordinate (line, row, record).
2. **Add guard clauses on all dimensions** — Before comparing inner values, verify the outer context matches. A one-line `if a.Line != b.Line { return false }` prevents the entire class of cross-line comparison bugs.
3. **Test with multi-line fixtures** — Standard test fixtures rarely span multiple lines. Add test cases where identical sub-ranges appear on different lines to ensure the comparison correctly distinguishes them.
4. **Use property-based testing** — Generate random (line, column) pairs to verify the comparison function never returns true for values on different lines. Hypothesis (Python) or rapidcheck (Go) can generate these automatically.

**Key insight:** The most predictable bugs are boundary conditions at the edges of multi-dimensional comparison functions. Code review should verify that comparison functions validate all coordinates, not just the innermost range. For secret scanners specifically, false negatives from incorrect deduplication are more dangerous than false positives because they mean a secret was silently ignored.

**Transfer potential**: High — the pattern of comparing a sub-range without validating the parent coordinate applies to any nested data structure comparison. Applying the fix principle (guard clause on the outer dimension before comparing the inner one) generalizes to JSON path matching, AST node comparison, and log line deduplication.