Notes. Measured on one Loki-backed pipeline after a process-exec logger added a parent-command field. Single live-window measurements; the double-count is exact and reproducible. Corrections welcome.

At 10,000 feet

Setting: a Loki + LogQL pipeline whose detection rules match process-exec log lines by substring, e.g. |~ "comm=runc ".

Problem: a new parent-command field pcomm= shipped, and since comm= is a substring of pcomm=, every pre-existing bare comm= filter silently doubled its match set — no rule was edited.

What this note establishes: the exact double-count on a live window; the fix is a word boundary (\b), which RE2 (Loki’s regex engine) supports.

Takeaway: a bare key= substring filter is unsafe once any other field name ends in that string — anchor key/value matchers with \b (or an explicit line start).

The measurement (measured)

Same live 10-minute window:

Filter Lines matched
|~ "comm=runc " (bare substring) 1002
\bcomm=runc (word-boundary anchored) 502
\bpcomm=runc (the parent field) 1005

The bare 1002 is essentially the real 502 plus parent-field matches it was never meant to see (the parent field roughly mirrors the command field here); \b recovers the intended 502.

The fix, and why this bites

Every key=value matcher in the rule set was regenerated with the boundary. The same hazard hits any prefix collision (pid= inside ppid=), invisibly — rules keep “working” while counting twice and tripping count-based thresholds. Treat log record format as an interface: audit substring filters whenever a field name is added.

Prior art, and what is new

The general pitfall is the Scunthorpe problem (a substring matching inside a larger token); credit goes there. New: this specific auditd/exec comm= vs pcomm= double-count in LogQL, measured, with the word-boundary fix — no public documentation of it was found.

Licensed under the site footer’s CC BY 4.0. If this saved you a silent double-count, the optional thanks link in the footer is appreciated, no obligation.

Validation (reproduced on Loki 3.4.1, 2026-08-31)

Throwaway single-binary Loki 3.4.1 in Docker, 1,000 synthetic auditd-style lines: 300 with comm=runc , 200 with pcomm=runc (their own comm is containerd-shim), 500 noise. Full-window query_range:

Filter Matches
\|~ comm=runc `` (bare) 500 (inflated: comm + pcomm lines)
\|~ \bcomm=runc `` 300 (comm lines only)
\|~ \bpcomm=runc `` 200 (pcomm lines only)

Verdict: reproduced. 500 = 300 + 200 — bare comm= matches pcomm= lines as a substring — and RE2’s \b works in Loki line filters (pc is not a word boundary).