Skip to content

fix(security): Strix provider 장애를 fail-closed로 유지#587

Open
seonghobae wants to merge 1 commit into
mainfrom
fix/strix-provider-unavailable-fail-closed
Open

fix(security): Strix provider 장애를 fail-closed로 유지#587
seonghobae wants to merge 1 commit into
mainfrom
fix/strix-provider-unavailable-fail-closed

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

요약

  • Strix 게이트가 429/403/쿼터 고갈로 보고서를 만들지 못했을 때 exit 1을 성공으로 바꾸던 우회 분기를 제거합니다.
  • 게이트 종료 코드를 그대로 전파하면서 always() 아티팩트 수집과 gate-console.log 보존은 유지합니다.
  • 실제 workflow run 블록을 추출해 quota exhaustion fake gate로 실행하는 회귀 테스트를 추가합니다.

보안 불변식

완전한 취약점 보고서가 없는 provider 장애는 통과가 아니라 불완전한 보안 증거입니다. 이 경우 required check와 repository_dispatch strix 상태는 실패로 남아야 합니다.

검증

  • pytest -q tests/test_required_workflow_queue_contract.py -k strix_provider_outage_without_findings_fails_closed — 1 passed
  • pytest -q — 634 passed
  • actionlint -shellcheck= -pyflakes= .github/workflows/strix.yml — passed
  • YAML safe-load / bash -n / git diff --check — passed
  • Codex Security diff scan — reportable finding 0건; 변경 핵심 경로 완전 검토

기준선 참고

전체 scripts/ci/test_strix_quick_gate.sh 실행에서는 이번 diff가 건드리지 않은 gate 시나리오들의 기존 기대값 불일치가 별도로 드러났습니다(nonrecoverable 문구, explicit-empty Vertex provider, fallback baseline report 판정). 이번 PR은 false-success 종료 코드 전파만 좁게 수정하며 해당 별도 기준선 문제를 숨기거나 성공으로 표시하지 않습니다.

@seonghobae

Copy link
Copy Markdown
Contributor Author

검증 메모: 이 PR의 pull_request_target Strix 실행은 아직 기본 브랜치의 기존 래퍼를 사용하므로 녹색 결론 자체를 유효한 보안 증거로 보지 않았습니다.

  • 실행: https://github.com/ContextualWisdomLab/.github/actions/runs/29581946009
  • 산출물의 취약점 보고서 파일: 0개
  • 실제 게이트 로그: OpenAI 429 insufficient_quota, GitHub Models 403/rate-limit, 모든 구성 모델 불가, 보고서 미생성으로 gate exit 1
  • 기존 기본 브랜치 래퍼 결과: backend-unavailable 정규식이 이를 감지해 Treating as a neutral skip 후 exit 0

이 PR은 바로 그 중화 분기를 제거하고 모든 비정상 gate 종료 코드를 그대로 반환합니다. 추가된 실행형 회귀 테스트는 quota/unavailable 출력을 내고 exit 1인 가짜 게이트를 실제 래퍼에 통과시켜, 래퍼도 exit 1이며 로그가 보존되는지 검증합니다. 로컬 전체 pytest 634개와 별도 보안 diff scan은 통과했습니다.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

This PR ensures Strix provider outages remain fail-closed by removing the workflow logic that downgraded certain provider/LLM failures to a successful check, while preserving always-run artifact/log collection and adding a regression test that executes the actual workflow run: block against a fake quota-exhaustion gate.

Changes:

  • Remove the “neutral skip” downgrade path for provider/LLM outage signals in .github/workflows/strix.yml and always propagate the gate exit code.
  • Add a regression test that extracts and executes the Strix workflow step script with a fake failing gate and asserts fail-closed behavior + log preservation.
  • Update CI contract assertions to require the new fail-closed messaging and forbid the removed downgrade signals.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/test_required_workflow_queue_contract.py Adds a regression test that runs the extracted Strix workflow script and asserts provider outage remains failing while preserving logs.
scripts/ci/test_strix_quick_gate.sh Updates hardening assertions to require fail-closed messaging and forbid the removed neutral-skip mechanism.
.github/workflows/strix.yml Removes provider-outage neutralization and prints a single error annotation before exiting with the gate’s code.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +891 to +896
run_step = workflow_step(workflow, "Run Strix (quick)")
run_marker = " run: |\n"
run_body = run_step.split(run_marker, 1)[1]
script = textwrap.dedent(
"\n".join(line[10:] for line in run_body.splitlines())
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants