fix(security): code scanner RE2 lookahead panics server at startup (#552) #742

Merged
jmiller merged 1 commits from fix/code-scanner-re2-panic into dev 2026-07-05 20:07:57 +00:00
Owner

Critical — server crash-loops at startup

Deploying the current code to the dev host surfaced a hard panic on boot:

panic: regexp: Compile(`yaml\.load…(?!\s*#)`): invalid or unsupported Perl syntax: `(?!`
  services/security/code_scanner.go:163  (services/security.init)

The deserialize-yaml-py scanner rule used a negative lookahead (?!\s*#) in regexp.MustCompile. Go's regexp engine is RE2, which has no lookahead/lookbehind — so MustCompile panics during the package init(), crash-looping the whole server before it can serve a request.

Why it wasn't caught

go build and go vet don't execute init(), and CI never boots the binary, so this shipped to main via #552 (#717) undetected. The live instances survive only because they run an older image built before #552. The dev deploy is the first time this code actually ran — and it crash-looped (healthy → unhealthy → 502).

Fix

  • Replace the pattern with an RE2-safe equivalent (?i)yaml\.load\s*\(, matching the rule's stated intent (flag yaml.load() without SafeLoader, CWE-502).
  • Add a regression test (code_scanner_test.go) that forces the package init() and asserts every DefaultCodeRules pattern compiled — so a future RE2-incompatible regexp fails in CI here, not on a live deploy.
  • Repo-wide scan confirmed this was the only lookahead/lookbehind/backref in a MustCompile.

Verification (local, Go 1.26.3)

  • go test ./services/security/...ok (the test executes init(); previously it panicked).
  • gofmt clean on both files.

Note: this bug is also on main (via #552). This PR fixes dev; a companion PR targets main directly so the release branch is deployable independent of the #733 release.

https://claude.ai/code/session_01Wsno14cxE49MstXFs9G5KT

## Critical — server crash-loops at startup Deploying the current code to the dev host surfaced a hard panic on boot: ``` panic: regexp: Compile(`yaml\.load…(?!\s*#)`): invalid or unsupported Perl syntax: `(?!` services/security/code_scanner.go:163 (services/security.init) ``` The `deserialize-yaml-py` scanner rule used a **negative lookahead** `(?!\s*#)` in `regexp.MustCompile`. Go's regexp engine is **RE2**, which has no lookahead/lookbehind — so `MustCompile` panics during the package `init()`, crash-looping the whole server before it can serve a request. ### Why it wasn't caught `go build` and `go vet` don't execute `init()`, and CI never boots the binary, so this shipped to `main` via #552 (#717) undetected. The live instances survive only because they run an **older image built before #552**. The dev deploy is the first time this code actually ran — and it crash-looped (healthy → unhealthy → 502). ## Fix - Replace the pattern with an RE2-safe equivalent `(?i)yaml\.load\s*\(`, matching the rule's stated intent (flag `yaml.load()` without `SafeLoader`, CWE-502). - Add a regression test (`code_scanner_test.go`) that forces the package `init()` and asserts every `DefaultCodeRules` pattern compiled — so a future RE2-incompatible regexp fails in CI here, not on a live deploy. - Repo-wide scan confirmed this was the **only** lookahead/lookbehind/backref in a `MustCompile`. ## Verification (local, Go 1.26.3) - `go test ./services/security/...` → **ok** (the test executes `init()`; previously it panicked). - gofmt clean on both files. > Note: this bug is **also on `main`** (via #552). This PR fixes `dev`; a companion PR targets `main` directly so the release branch is deployable independent of the #733 release. https://claude.ai/code/session_01Wsno14cxE49MstXFs9G5KT
jmiller added 1 commit 2026-07-05 20:07:27 +00:00
fix(security): code scanner panics at startup on RE2-incompatible regexp
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Successful in 16s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Generic: Project CI / Lint & Validate (pull_request) Successful in 44s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m29s
Universal: PR Check / Secret Scan (pull_request) Successful in 3m49s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2f119fbd95
The "deserialize-yaml-py" rule in services/security/code_scanner.go used a
negative lookahead `(?!\s*#)` in regexp.MustCompile. Go's regexp engine is
RE2, which has no lookahead/lookbehind, so MustCompile panics during the
package init() — crash-looping the entire server at startup. `go build` and
`go vet` do not execute init(), and CI never boots the binary, so this
shipped to main via #552 undetected; the running instances survived only
because they predate that image.

Replace the pattern with an RE2-safe equivalent `(?i)yaml\.load\s*\(`, which
matches the rule's stated intent (flag yaml.load() without SafeLoader,
CWE-502). Add a regression test that forces the package init and asserts
every DefaultCodeRules pattern compiled, so a future RE2-incompatible
pattern fails in CI here instead of on a live deploy.

Claude-Session: https://claude.ai/code/session_01Wsno14cxE49MstXFs9G5KT
jmiller merged commit ccfc9a604b into dev 2026-07-05 20:07:57 +00:00
jmiller deleted branch fix/code-scanner-re2-panic 2026-07-05 20:07:58 +00:00
Sign in to join this conversation.