Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f89c0c5
fix(strix): make provider fallback capability-aware
seonghobae Aug 23, 2026
b05edc0
fix(strix): track shared routing quality paths
seonghobae Aug 23, 2026
4fc6a24
fix(strix): harden provider fallback boundaries
seonghobae Aug 23, 2026
1fd718f
fix(strix): align console advisory filter
seonghobae Aug 23, 2026
de3abcd
fix(strix): keep privileged dependencies trusted
seonghobae Aug 23, 2026
975a9e4
fix(strix): preserve bootstrap smoke marker
seonghobae Aug 23, 2026
02f43ee
test(strix): retrigger on NIM doctoring changes
seonghobae Aug 23, 2026
af55904
fix(strix): bind privileged install to trusted lock
seonghobae Aug 23, 2026
9ca02e8
merge: preserve concurrent Strix trust repair
seonghobae Aug 23, 2026
71afa06
test(strix): retrigger trusted-lock doctoring
seonghobae Aug 23, 2026
5c28166
Merge branch 'main' into codex/strix-provider-failover-main-20260823
seonghobae Aug 23, 2026
6b569a5
fix(strix): fail closed on unverifiable evidence
seonghobae Aug 23, 2026
f5c3f7e
fix(strix): require structured finding evidence
seonghobae Aug 23, 2026
40ba02d
fix(strix): isolate privileged evidence boundaries
seonghobae Aug 23, 2026
7be1e60
fix(strix): drop retired fallback credentials
seonghobae Aug 23, 2026
667db5a
fix(strix): satisfy protected main's frozen smoke contract at check time
seonghobae Aug 23, 2026
cd6d2e5
fix(strix): reject severity identifier suffixes
seonghobae Aug 24, 2026
50a6ad9
test(strix): isolate severity boundary regression
seonghobae Aug 24, 2026
2f15aba
fix(strix): canonicalize direct fallback provider
seonghobae Aug 24, 2026
844cef4
Merge protected main into Strix provider repair
seonghobae Aug 24, 2026
05feeb1
fix(strix): restore complete owner tree after main sync
seonghobae Aug 24, 2026
847ad99
fix(strix): preserve frozen smoke alias during provider repair
seonghobae Aug 24, 2026
f428b3e
Merge protected main after Strix owner-tree recovery
seonghobae Aug 24, 2026
0445447
docs(strix): name direct OpenAI fallback accurately
seonghobae Aug 24, 2026
3669bce
Merge branch 'main' into codex/strix-provider-failover-main-20260823
seonghobae Aug 24, 2026
ddaca1b
fix: restore base-merged strix work reverted by prior merge
seonghobae Aug 24, 2026
7333818
fix(strix): restore verified owner tree after semantic replay regression
seonghobae Aug 24, 2026
b851a16
fix(strix): normalize provider fallback before dispatch
seonghobae Aug 24, 2026
43e7f21
merge(main): absorb direct-OpenAI fallback hotfix
seonghobae Aug 24, 2026
026c26a
fix(strix): avoid duplicate direct fallback
seonghobae Aug 24, 2026
14cd0e8
docs: qualify contextual-orchestrator reference
seonghobae Aug 24, 2026
7011fee
test(strix): make empty fallback explicit
seonghobae Aug 24, 2026
94f56fd
fix(strix): pin direct OpenAI fallback endpoint
seonghobae Aug 24, 2026
d6c34c5
fix(strix): authenticate provider failure words
seonghobae Aug 24, 2026
a73831f
fix(strix): preserve altered advisory failure
seonghobae Aug 24, 2026
4fb737a
fix(strix): retrigger quality for contract inputs
seonghobae Aug 24, 2026
ab3d764
Merge protected main into Strix provider failover repair
seonghobae Aug 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/strix-changed-path-quality-ci.yml
Comment thread
seonghobae marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@ on:
- "CHANGELOG.md"
- "docs/doctoring/strix-legal-git-paths.md"
- "docs/doctoring/strix-model-behavior-error.md"
- "docs/doctoring/strix-nvidia-nim-not-found-fallback.md"
- "docs/doctoring/strix-unsupported-sampling-fallback.md"
- "docs/doctoring/strix-quality-timeout-fixtures.md"
- "docs/doctoring/strix-trusted-dependency-lock.md"
- "scripts/ci/strix_model_utils.sh"
Comment thread
seonghobae marked this conversation as resolved.
- "scripts/ci/strix_quick_gate.sh"
- "scripts/ci/test_strix_quick_gate.sh"
- "requirements-strix-ci.txt"
- "requirements-strix-ci-hashes.txt"
- "tests/test_strix_changed_path_policy.py"
- "tests/test_strix_model_behavior_error.py"
- "tests/test_strix_nvidia_nim_not_found_fallback.py"
- "tests/test_strix_severity_identifier_boundary.py"
- "tests/test_strix_workflow_dependency_hashes.py"
- "tests/test_strix_quality_timeout_fixture_budget.py"

Expand Down
294 changes: 150 additions & 144 deletions .github/workflows/strix.yml

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ Semantic Versioning where the repository publishes a release.

### Changed

- Keep Strix's hash-verified dependency lock on the trusted workflow source;
privileged PR scans no longer replace it with a same-repository PR-head lock
before provider credentials reach the installed scanner.
- Route the exact single-line LiteLLM/Azure unsupported-temperature failure to
an already-configured distinct Strix fallback without accepting split-line
imitations. The workflow's `openai-direct/` alias now normalizes to the
canonical `openai_direct/` selector, while LiteLLM dispatch uses its `openai/`
provider form. Cross-provider
attempts now switch to the trusted OpenAI credential and explicit
`https://api.openai.com/v1` fallback endpoint, without turning an incomplete
provider scan into passing evidence. Exact clean model-quality and Hugging
Face advisories are filtered
consistently from console and report logs, while any appended warning text
remains fail closed. The incident and fail-closed boundary are recorded in
`docs/doctoring/strix-unsupported-sampling-fallback.md`; changes to that
record or the shared model normalizer now rerun the exact-head path gate.
- Emit completed repository pull-list requests as they finish in the five-minute
agent-mention sweep, while retaining the four-worker ceiling, rotation, and
exact-name dispatch ledger, so one slow repository cannot hide ready sibling
Expand All @@ -70,6 +86,13 @@ Semantic Versioning where the repository publishes a release.

### Fixed

- Keep Strix target commands inside the pinned Docker sandbox environment,
omit `GITHUB_TOKEN` and `GITHUB_STATUS_TOKEN` from the scanner child even
while the scan job retains protected-main-compatible `statuses: write`, use
only an exchanged app token in the status-incapable follow-up job, reject
nonzero low-severity and symlinked report evidence, classify JSON reports,
and fail closed when reported paths escape the active PR scan target.

- Publish only the sanitized cumulative Strix report tree, avoiding a later
copy of relative scanner output that could reintroduce known internal warning
text into uploaded security evidence.
Expand Down Expand Up @@ -141,6 +164,7 @@ Semantic Versioning where the repository publishes a release.

### Security

- Prevented privileged Strix pull-request scans from installing a PR-selected dependency lock; the workflow now verifies the trusted checkout's Git blob immediately before a hash-enforced, binary-only install and pins the first compatible LiteLLM release that supplies the required Python 3.13 manylinux wheel.
- Keep the Quarantine Sandbox Runtime caller read-only and model-secret-free, grant only job-scoped OIDC to the reusable scheduler, and preserve the product boundary in which the sandbox returns artifact-analysis evidence while hosts retain WAF/IDS, admission, final verdict, incident, and retention authority.
- Reject `.github/` and `scripts/ci/` from review-thread-derived autofix path authority so an untrusted inline reviewer cannot authorize the write-capable repair agent to modify workflows, CODEOWNERS, actions, scheduler code, or CI helpers that govern its own control plane.
- Require the model-write snapshot and exact-path allowlist to remain outside the pull-request worktree, checking both absolute and resolved locations so repository-local controls and outside-looking symlinks resolving into the repository fail closed before they can authorize or verify model changes.
Expand Down
13 changes: 12 additions & 1 deletion docs/doctoring/strix-nvidia-nim-not-found-fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ combining with an unrelated application `404` to spoof infrastructure fallback.
Provider-side failure also remains a fail-closed incomplete scan until a distinct
fallback produces complete evidence.

A completed zero-vulnerability fallback may emit Strix's model-quality banner
and Hugging Face's exact unauthenticated-download advisory while loading public
scanner assets. The console allowlist removes only those two complete lines and
the exact optional-web-search-key advisory. Structured report logs additionally
allow Strix's bounded lifecycle-continuation warning. A suffix, prefix, or any
other warning text remains fail-closed provider-failure evidence.

Exhausted provider infrastructure remains fail-closed even when the trusted
gate has classified every observed threshold finding as outside the pull
request's changed files. That classification scopes authoritative findings; it
Expand All @@ -53,7 +60,11 @@ Regression evidence proves that:
8. provider exhaustion remains non-passing after unchanged baseline findings;
9. changed, unmapped, and changed-manifest findings also block after provider
exhaustion; and
10. the required-workflow smoke contract pins these properties.
10. the exact model-quality and Hugging Face download advisories do not reject
an otherwise complete zero-vulnerability fallback when they appear in
console or report logs;
11. appended warning text is not hidden by either exact advisory filter; and
12. the required-workflow smoke contract pins these properties.

## Limitations

Expand Down
126 changes: 126 additions & 0 deletions docs/doctoring/strix-trusted-dependency-lock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Strix privileged dependency-lock boundary

## Observed failure

Repository-dispatch run `32651685973` scanned pull request #1263 and reported a
high-severity supply-chain path in the protected `pull_request_target` Strix
workflow. The workflow copied `requirements-strix-ci-hashes.txt` from the pull
request head, installed the selected distributions, and later executed the
installed `strix` console script with provider credentials.

The hosted report overstated its proof as a demonstrated exploit: the dispatch
path did not take the same-repository `pull_request_target` copy step, and the
artifact contained no malicious package command or output. The source path was
nevertheless deterministic and security-relevant. Hashes selected by the same
untrusted pull request authenticate attacker-selected content; they do not make
that content trusted.

## Root cause and repair

The workflow treated a hash lock as trusted because every distribution was
pinned and hashed. That protects a reviewed lock from index tampering, but it
does not establish the provenance of a lock supplied by a pull request.
GitHub's privileged-trigger guidance requires pull-request content to remain
data and never become executed code. pip's secure-install guidance separately
requires hash checking and disallows source distributions.

The repair deletes PR-head lock materialization. The install step now:

1. reads only the lock from the trusted workflow checkout;
2. rejects a missing or symbolic-link lock;
3. compares the on-disk Git blob with `HEAD:requirements-strix-ci-hashes.txt`
immediately before installation; and
4. pins LiteLLM to the first compatible release with a Python 3.13 manylinux
wheel, then installs with `--require-hashes`, `--only-binary=:all:`, and
`--no-deps`.

Pull-request copies of the workflow and scheduler remain bounded self-test or
scan inputs; they do not select installed dependencies or receive provider
credentials.

## Scanner, credential, and status boundary

Default-branch dispatch run `32656142905` then tested the repaired branch with
the direct OpenAI provider and reported eight possible trust-boundary failures.
The credential-inheritance claim did not match the pinned `strix-agent==1.5.3`
runtime: its default backend is Docker, target commands run through a sandbox
manifest, and that manifest contains only the proxy, host identity, and Python
runtime variables required by Strix. The hosted proof used a fake scanner that
executed target code directly on the runner, which the pinned scanner does not
do.

The workflow now executes the installed Strix session-construction path before
loading provider credentials. It fails if the backend is not Docker or if the
sandbox manifest adds any host environment key outside the reviewed allowlist.
This proves only the target-command environment boundary. It does not claim
network isolation or read-only source mounts.

GitHub creates a distinct `GITHUB_TOKEN` for each job. The `strix` job currently
retains `statuses: write` only because protected main's trusted required-workflow
smoke pins that live permission layout. The gate constructs the scanner child
environment from an allowlist that omits both `GITHUB_TOKEN` and
`GITHUB_STATUS_TOKEN`, so the scanner process cannot exercise the job token's
status authority. The separate follow-up job has no `statuses: write`
permission; after the scan exports evidence that repository-dispatch inputs
matched live pull-request number, base SHA, and head SHA, it publishes with an
exchanged app token.

## Report evidence boundary

The remaining hosted findings exposed real fail-open behavior in the shared
gate. The repair applies one rule to every scanner attempt and report format:

- a nonzero scanner exit is incomplete evidence even when all emitted findings
are below the configured severity threshold;
- Markdown and JSON vulnerability reports enter the same severity and
changed-path mapping gate;
- report roots and every descendant must be ordinary non-symlink paths before
classification, copying, or publication;
- a finding in a changed file blocks regardless of its reported line range;
and
- a report path outside a narrowed scan target is unmappable failure evidence,
not an unchanged baseline exemption.

Absolute paths that identify a file actually materialized in the narrowed scan
target remain mappable. This preserves legitimate Strix output without allowing
an outside-target path to be normalized against the repository root.

## Verification

- A static regression rejects any PR-head materialization of the Strix lock and
requires the trusted Git-blob comparison and binary-only install.
- The short required-workflow smoke test enforces the same boundary.
- The workflow contract verifies Docker-backed sandbox construction, isolated
status permission, and live dispatch metadata evidence.
- Realistic regressions cover nonzero low-severity output, JSON findings,
symlinked report trees, changed-file line drift, narrowed-target escapes, and
absolute paths inside the active target.
- The complete Strix shell harness, Python suite, actionlint, Bash syntax, and
source-tree coverage run on the final exact head.

## References

GitHub. (n.d.). *GITHUB_TOKEN*. GitHub Docs. Retrieved August 24, 2026, from
https://docs.github.com/en/actions/concepts/security/github_token

GitHub. (n.d.). *Secure use reference*. GitHub Docs. Retrieved August 24, 2026,
from
https://docs.github.com/en/actions/reference/security/secure-use

GitHub. (n.d.). *Securely using pull_request_target*. GitHub Docs. Retrieved
August 24, 2026, from
https://docs.github.com/en/actions/reference/security/securely-using-pull_request_target

GitHub. (n.d.). *Workflow syntax for GitHub Actions*. GitHub Docs. Retrieved
August 24, 2026, from
https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax

Python Packaging Authority. (2026). *Secure installs (pip 26.2.1
documentation)*. https://pip.pypa.io/en/stable/topics/secure-installs/

Python Software Foundation. (n.d.). *subprocess—Subprocess management*. Python
3 documentation. Retrieved August 24, 2026, from
https://docs.python.org/3/library/subprocess.html

Strix. (2026, August 10). *Strix* (Version 1.5.3) [Computer software]. GitHub.
https://github.com/usestrix/strix/tree/v1.5.3
74 changes: 74 additions & 0 deletions docs/doctoring/strix-unsupported-sampling-fallback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Strix unsupported sampling-parameter fallback

## Observed failure

An Azure `gpt-5.6-sol` Strix run failed before vulnerability analysis because
LiteLLM sent `temperature=0.2`. Azure accepts only the model default of `1`,
and LiteLLM had no fallback group for the selected model. Microsoft documents
`temperature` as unsupported for GPT-5 reasoning models (Microsoft, 2026),
while the pinned Strix configuration surface exposes no generation-parameter
control (usestrix, n.d.).

## Root cause and repair

The preferred request-boundary repair is to omit a sampling parameter that a
caller did not explicitly provide. [ContextualWisdomLab/contextual-orchestrator](https://github.com/ContextualWisdomLab/contextual-orchestrator)
owns that provider
boundary for organization software. The pinned Strix integration cannot yet
express the omission through its documented configuration, so the trusted
quick gate recognizes only one physical error line containing all of these
signals:

- a LiteLLM `BadRequestError`;
- Azure or OpenAI exception context;
- the unsupported `temperature` value and supported default; and
- the missing LiteLLM fallback model group.

That exact capability failure is infrastructure evidence and may move directly
to an already-configured distinct outer fallback. It is not eligible for a
same-model retry. A direct-OpenAI primary has no second approved direct model
configured, so its bounded same-model retries are followed by a fail-closed
result rather than a duplicate fallback entry. The shared model normalizer translates the workflow's
accepted `openai-direct/` alias to the canonical `openai_direct/` selector;
the LiteLLM child dispatch then uses its provider-compatible `openai/` form. A
cross-provider direct OpenAI fallback reads the established OpenAI secret and
the explicit `https://api.openai.com/v1` endpoint from trusted runtime files;
otherwise a NVIDIA or OpenRouter run could send the fallback to the wrong
endpoint with the wrong credential. If either input is unavailable, the
attempted fallback fails configuration closed.
If no distinct fallback exists or every fallback fails, the required Strix
check remains non-passing. Existing changed, unmapped, manifest,
`ModelBehaviorError`, and vulnerability-report boundaries remain fail closed.

Cross-line signal assembly is deliberately rejected so unrelated target output
cannot manufacture a provider capability error from separate log lines.

## Verification

- The reproduced single-line Azure failure reaches the configured distinct
outer fallback exactly once and succeeds only when that scan completes.
- A direct-OpenAI primary does not attempt its normalized primary model again
as a fallback after bounded same-model retries.
- The configured `openai-direct/gpt-5.6-luna` alias normalizes to the canonical
`openai_direct/gpt-5.6-luna` selector, then dispatches through LiteLLM as
`openai/gpt-5.6-luna`.
- A NVIDIA-primary run dispatches that fallback with the OpenAI credential and
the explicit OpenAI API base, with no inherited NVIDIA API base.
- A split-line imitation is non-recoverable and never dispatches the fallback.
- The full Python suite, native workflow validation, Bash syntax checks, and
complete Strix shell regression suite run on the final tree.

## References

AkikoOrenji. (2026, June 4). *[Feature] Expose LLM generation parameters to
control local/OpenAI-compatible model behaviour and prevent runaway tool-call
loops* (Issue No. 514) [GitHub issue]. GitHub.
https://github.com/usestrix/strix/issues/514

Microsoft. (2026, August 20). *Azure OpenAI reasoning models—GPT-5 series,
o3-mini, o1, o1-mini*. Microsoft Learn.
https://learn.microsoft.com/en-us/azure/foundry/openai/how-to/reasoning

usestrix. (n.d.). *Configuration* [Computer software documentation]. GitHub.
Retrieved August 23, 2026, from
https://github.com/usestrix/strix/blob/main/docs/advanced/configuration.mdx
Loading
Loading