Skip to content

fix(strix): bare Fatal/Denied/Warn/Warning match lacks provider-context guard, causing false-positive fail-closed on clean scans #1291

Description

@seonghobae

Problem

While triaging why the required strix check was failing on essentially every open PR across fast-mlsirm (including a trivial Dependabot Actions-version bump, PR #1311, where no plausible real finding exists), I traced one concrete failure to its root cause in scripts/ci/strix_quick_gate.sh.

has_detected_infrastructure_error() (around line 2946) starts with:

has_detected_infrastructure_error() {
	if grep -Eiq '(^|[^[:alpha:]])(Fatal|Denied|Warn|Warning)([^[:alpha:]]|$)' "$STRIX_LOG"; then
		return 0
	fi
	...

Unlike every other branch in the same function (is_timeout_error, is_rate_limit_error, is_llm_token_limit_error, is_llm_api_connection_error, is_llm_service_unavailable_error, is_nvidia_nim_not_found_error, and the generic ConnectionError|... branch at the bottom), this first branch has no requirement that the match occur in an LLM-provider context (no LLM_PROVIDER_ONLY_REGEX / PROVIDER_CONTEXT_REGEX co-requirement). It fires on the bare words Fatal, Denied, Warn, or Warning appearing anywhere in the full Strix log — including inside Strix's own narrative/report text about the scanned target, which very plausibly contains these exact words as ordinary vocabulary (e.g. many CWL repos' own CLAUDE.md/AGENTS.md literally instruct treating Timeout, Fatal, Warn, or Denied output as a hard failure — a convention Strix would naturally quote or reference while analyzing those repos; or Strix simply describing an access-control check as "Denied" or a log level as "Warn").

Evidence

PR fast-mlsirm#1311 (a pure bump rust-toolchain/CodeQL-action-version Dependabot PR — no plausible real finding):

  • Run: https://github.com/ContextualWisdomLab/fast-mlsirm/actions/runs/32691078281/job/97324789969
  • The primary-model Strix run completed cleanly:
    ╭─ STRIX ──────────────────────────────────────────────────────────────────────╮
    │  Penetration test completed                                                  │
    │  Vulnerabilities  0 (No exploitable vulnerabilities detected)                │
    ╰──────────────────────────────────────────────────────────────────────────────╯
    
  • Immediately after, the gate logged: Strix run emitted provider infrastructure or failure-signal output; failing closed. — with rc=0 and a genuine 0-vulnerability report already produced, this can only be the bare-word branch (none of the other, provider-context-gated branches would plausibly fire on a report that already completed with no LLM/provider errors visible in the summary box).
  • This forced a full model-fallback cascade: nvidia_nim/nvidia/llama-3.3-nemotron-super-49b-v1.5 (also flagged the same way) → openai-direct/gpt-5.6-luna, which then hit a second, independent bug: litellm rejected it outright (litellm.BadRequestError: LLM Provider NOT provided ... You passed model=openai-direct/gpt-5.6-luna). The final fallback exhausted, and the gate correctly failed closed on "provider infrastructure failures are not clean scan evidence" — but only because the cascade was triggered unnecessarily by the first false positive.

I did not have time to fully trace the second bug (hyphen- vs. underscore-normalized openai-direct/openai_direct model-string handling differs between strix.yml:757-758 and strix_quick_gate.sh:2311-2312, and whichever code path fed openai-direct/gpt-5.6-luna — hyphenated — into this particular fallback attempt evidently skipped the hyphen→underscore conversion that the other path applies). Flagging it here since it compounds the same incident, but the bare-word false positive is the primary, reproducible finding and worth fixing independently.

Why this matters

This repeats across nearly every open fast-mlsirm PR I sampled (confirmed failing on 1237, 1194, 1311; same blocked/no-fresh-review pattern strongly suggestive of the same cause on 1181, 1172, 1156, 1074, 1056, 1302, 1299, 1196) — i.e., it is very likely the single largest current source of required-check failures blocking merges org-wide, not a per-repo code issue.

Suggested fix (not attempted here — this touches fail-closed security logic and the existing multi-thousand-line test_strix_quick_gate.sh suite, and per this repo's own policy that deserves a dedicated, test-first change, not a drive-by patch)

Require the bare Fatal|Denied|Warn|Warning branch to co-occur with an LLM/provider-context marker (mirroring LLM_PROVIDER_ONLY_REGEX/PROVIDER_CONTEXT_REGEX used by the other branches in the same function), or scope it to text that appears after the log's own completion marker is absent (i.e., don't apply it once a Penetration test completed + Vulnerabilities N block with no in-band provider-error marker has already been observed for that attempt). Add regression fixtures using real Strix report narrative text that legitimately contains these words in a non-infrastructure sense, alongside the existing genuine-infrastructure-failure fixtures, so the fix is provably narrowing false positives without reopening the fail-closed gap that #891 tracks.

Related

Agent: Claude
Recorded: 2026-08-24T07:xx (see issue creation timestamp)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: securitySecurity boundary, hardening, or vulnerability preventionbugSomething isn't workingpriority: highHigh-priority or P1 worktype: bugDefect or incorrect behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions