Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 29 additions & 1 deletion .github/workflows/codeql-pr.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Runs CodeQL on both the PR head and merge preview. Medium+ security results
# fail locally with rule/path/line/message evidence, while SARIF is preserved
# as an artifact. This keeps real findings blocking even when GitHub's
# installation API quota prevents code-scanning uploads.
# installation API quota prevents code-scanning uploads. github/codeql-action
# init can 503 while asking GitHub for feature enablement; retry that step
# once after a short wait. The Medium+ SARIF gate is unchanged.
name: CodeQL PR

on:
Expand Down Expand Up @@ -90,6 +92,19 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}

- name: Initialize CodeQL
id: codeql-init
continue-on-error: true
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Wait before CodeQL init retry
if: steps.codeql-init.outcome == 'failure'
run: sleep 20

- name: Retry Initialize CodeQL after GitHub API brownout
if: steps.codeql-init.outcome == 'failure'
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
Expand Down Expand Up @@ -197,6 +212,19 @@ jobs:
ref: ${{ format('refs/pull/{0}/merge', github.event.pull_request.number) }}

- name: Initialize CodeQL
id: codeql-init
continue-on-error: true
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Wait before CodeQL init retry
if: steps.codeql-init.outcome == 'failure'
run: sleep 20

- name: Retry Initialize CodeQL after GitHub API brownout
if: steps.codeql-init.outcome == 'failure'
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/python-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,22 @@ jobs:
# Audit every discovered requirements file.
while IFS= read -r req; do
echo "::group::pip-audit -r ${req}"
pip-audit --strict --desc=on -r "${req}" || status=1
# The Strix 1.5.3 lock keeps cryptography==50.0.0. pip-audit's
# resolver re-applies the stale upstream cryptography<49 bound and
# labels that ResolutionImpossible as a vulnerability. The
# unhashed compile input is not an audit target. The hashed lock
# is a URL pin; --disable-pip cannot read that form, so rewrite
# it to name==version from the PEP 427 filename first.
if [ "$(basename "${req}")" = "requirements-strix-ci.txt" ]; then
echo "Skipping unhashed Strix compile input; hashed sibling is the audit target."
elif [ "$(basename "${req}")" = "requirements-strix-ci-hashes.txt" ]; then
prepared="${RUNNER_TEMP}/strix-pip-audit.txt"
python3 scripts/ci/prepare_strix_lock_for_pip_audit.py \
--input "${req}" --output "${prepared}"
pip-audit --strict --desc=on --disable-pip -r "${prepared}" || status=1
else
pip-audit --strict --desc=on -r "${req}" || status=1
fi
echo "::endgroup::"
done < <(find . -type f -name 'requirements*.txt' -not -path './.git/*')

Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/strix-changed-path-quality-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@ on:
branches: [main]
paths:
- ".github/workflows/strix-changed-path-quality-ci.yml"
- ".github/workflows/strix.yml"
- "CHANGELOG.md"
- "docs/doctoring/strix-agent-cryptography-override.md"
- "docs/doctoring/strix-legal-git-paths.md"
- "docs/doctoring/strix-quality-timeout-fixtures.md"
- "requirements-strix-ci-overrides.txt"
- "scripts/ci/compile_strix_ci_lock.sh"
- "scripts/ci/prepare_strix_lock_for_pip_audit.py"
- "scripts/ci/rewrite_strix_agent_cryptography_bound.py"
- "scripts/ci/strix_quick_gate.sh"
- "scripts/ci/test_strix_quick_gate.sh"
- "tests/test_prepare_strix_lock_for_pip_audit.py"
- "tests/test_rewrite_strix_agent_cryptography_bound.py"
- "tests/test_strix_agent_cryptography_override.py"
- "tests/test_strix_changed_path_policy.py"
- "vendor/strix/"
- "tests/test_strix_workflow_dependency_hashes.py"
- "tests/test_strix_quality_timeout_fixture_budget.py"

Expand Down Expand Up @@ -66,6 +76,6 @@ jobs:
test "$(git rev-parse HEAD)" = "${{ github.event.pull_request.head.sha || github.sha }}"
python -m coverage run -m pytest tests -q
bash scripts/ci/test_strix_quick_gate.sh
python -m compileall -q tests/test_strix_changed_path_policy.py tests/test_strix_workflow_dependency_hashes.py tests/test_strix_quality_timeout_fixture_budget.py
python -m compileall -q scripts/ci/prepare_strix_lock_for_pip_audit.py tests/test_prepare_strix_lock_for_pip_audit.py tests/test_rewrite_strix_agent_cryptography_bound.py tests/test_strix_agent_cryptography_override.py tests/test_strix_changed_path_policy.py tests/test_strix_workflow_dependency_hashes.py tests/test_strix_quality_timeout_fixture_budget.py
bash -n scripts/ci/strix_quick_gate.sh
git diff --exit-code
19 changes: 18 additions & 1 deletion .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,24 @@ jobs:
# private install umask before creating the credential-bearing Strix
# entry point; the runtime gate still rejects any later relaxation.
umask 022
python3 -m pip install --disable-pip-version-check --no-cache-dir --require-hashes -r requirements-strix-ci-hashes.txt
# The compiled lock is the complete closed set. --no-deps is required
# so pip does not re-apply strix-agent's stale cryptography<49 bound
# after the CVE-50 override was resolved at compile time.
python3 -m pip install --disable-pip-version-check --no-cache-dir --require-hashes --no-deps -r requirements-strix-ci-hashes.txt
python3 - <<'PY'
import importlib.metadata as metadata
import sys

expected = {"strix-agent": "1.5.3", "cryptography": "50.0.0"}
for name, version in expected.items():
loaded = metadata.version(name)
if loaded != version:
print(
f"::error::Installed {name}=={loaded}, expected {version}.",
file=sys.stderr,
)
sys.exit(1)
PY
strix_executable="$(command -v strix || true)"
if [ -z "$strix_executable" ] || [[ "$strix_executable" != /* ]] \
|| [ ! -f "$strix_executable" ] || [ -L "$strix_executable" ] \
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
> **Agents: read the master context FIRST.** Before any work, read [`docs/CWL-MASTER-CONTEXT.md`](docs/CWL-MASTER-CONTEXT.md) (mission · naruon-as-platform + inter-component UML · cross-cutting disciplines · conventions · roadmap · current state), the live **GitHub Project #1** <https://github.com/orgs/ContextualWisdomLab/projects/1> (work/roadmap source of truth), the full spec **ContextualWisdomLab/naruon#974**, and operate the Project per [`docs/agent-github-project-protocol.md`](docs/agent-github-project-protocol.md). The repo/Project — not any private agent memory — is the source of truth.

Materialize accepts only exact SHA-256 pins or a bounded relative `-r` include (no `.`/`..`); a lone `--require-hashes` directive is not trust evidence. See [`docs/doctoring/hourly-nvidia-nim-autofix.md`](docs/doctoring/hourly-nvidia-nim-autofix.md).
The Strix CI lock keeps `strix-agent==1.5.3` with `cryptography==50.0.0` through `requirements-strix-ci-overrides.txt` and `./scripts/ci/compile_strix_ci_lock.sh`; install that complete hashed lock with `--no-deps`. The lock also prefers a METADATA-patched official 1.5.3 wheel so current `main`'s resolver-based installer can still resolve both pins. See [`docs/doctoring/strix-agent-cryptography-override.md`](docs/doctoring/strix-agent-cryptography-override.md).
Conflict-scope roots fail closed when the immediate parent directory is a symbolic link.
13 changes: 13 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ sequenceDiagram
- Rust remains the psychometric arithmetic owner. Repair never substitutes
Python for scoring math.

## Required Strix lock

The org-required Strix workflow installs a complete hashed lock. Upstream
`strix-agent==1.5.3` still declares `cryptography<49`, so compile-time
override keeps `cryptography==50.0.0` (CVE-2026-69247 PKCS#7 timing
oracle; also above CVE-2026-39892). CI then installs with
`pip install --require-hashes --no-deps` and fail-closes unless
`importlib.metadata` reports both pins. The missing-artifact gate is
unchanged: console severity markers are not a passing report. See
[`docs/doctoring/strix-agent-cryptography-override.md`](docs/doctoring/strix-agent-cryptography-override.md).

## Quality gates

`scripts/ci/` ships with 100% statement/branch coverage and 100% docstrings.
Expand All @@ -106,5 +117,7 @@ tests pin workflow structure and governance prose so drift fails closed.
contract.
- [`docs/doctoring/hourly-nvidia-nim-autofix.md`](docs/doctoring/hourly-nvidia-nim-autofix.md)
— current increment's repair-worker decision and APA 7th citations.
- [`docs/doctoring/strix-agent-cryptography-override.md`](docs/doctoring/strix-agent-cryptography-override.md)
— Strix 1.5.3 report persist with cryptography 50.0.0 override.
- [`docs/doctoring/fast-mlsirm-hourly-review-caller.md`](docs/doctoring/fast-mlsirm-hourly-review-caller.md)
— product-specific psychometric repair heartbeat and scientific gates.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Semantic Versioning where the repository publishes a release.

### Fixed

- Retry CodeQL `init` once after a 20-second wait when GitHub's feature-enablement API returns 503, so a brownout during `codeql-action/init` does not fail the Python head or merge-preview jobs. The Medium+ SARIF gate, `upload: false` contract, and action pin are unchanged.
- Pin required Strix to `strix-agent==1.5.3` so a completed scan writes a durable report artifact, keep `cryptography==50.0.0` (CVE-2026-69247 / CVE-2026-39892) via a compile-time override, and install the complete hashed lock with `--no-deps` so pip cannot re-apply the stale `cryptography<49` bound. Until that installer is on protected `main`, the lock also prefers a METADATA-patched official 1.5.3 wheel so `pip install --require-hashes` without `--no-deps` can resolve both pins. pip-audit skips the unhashed compile input and audits a prepared `name==version` copy of the hashed lock with `--disable-pip`, so it neither re-resolves `strix-agent==1.5.3` against cryptography 50 nor rejects the install-time URL pin. The fail-closed missing-artifact gate is unchanged.
- Materialized base Python locks only when every package line is an exact SHA-256 pin or a bounded relative `-r`/`--requirement` include. A lone `--require-hashes` directive, a dotted include such as `./lock.txt`, or `-r other-hashes.txt` no longer enters the trusted build context.
- Refused a conflict-scope repository root whose immediate parent is a symbolic link, so a swapped parent cannot redirect the canonical worktree after the last-component check (CWE-367).
- Bounded the Strix quality self-test's deterministic timeout fixtures to 3-second process and 5-second fake-sleep budgets so exact-head policy evidence completes inside the existing job limit without changing production Strix scanner timeouts, providers, credentials, or review semantics.
Expand Down
12 changes: 8 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,18 @@ e.g.:
```bash
uv pip compile --generate-hashes --python-version 3.12 --python-platform x86_64-manylinux_2_28 requirements-bandit-ci.txt -o requirements-bandit-ci-hashes.txt
uv pip compile --generate-hashes --python-version 3.12 --python-platform x86_64-manylinux_2_28 requirements-pip-audit-ci.txt -o requirements-pip-audit-ci-hashes.txt
uv pip compile --generate-hashes --python-version 3.13 --python-platform x86_64-manylinux_2_28 --output-file requirements-strix-ci-hashes.txt requirements-strix-ci.txt
./scripts/ci/compile_strix_ci_lock.sh
./scripts/ci/compile_opencode_review_lock.sh
```

Note the per-file Python versions differ (bandit/pip-audit: 3.12; strix: 3.13; OpenCode
review: 3.14). The OpenCode review generator always passes `--upgrade` so an existing output
file cannot preserve hashes from the previous Python target, and records itself as the lock's
repeatable compile command.
review: 3.14). The Strix generator records itself as the lock's repeatable compile command
and applies `requirements-strix-ci-overrides.txt` so `strix-agent==1.5.3` can keep
`cryptography==50.0.0`. After compile it rewrites the official 1.5.3 manylinux
wheel metadata and lock `--find-links` so a resolver-based `pip install
--require-hashes` can still install cryptography 50.0.0. The OpenCode review generator always passes `--upgrade` so an
existing output file cannot preserve hashes from the previous Python target, and records
itself as the lock's repeatable compile command.

## Conventions and gotchas specific to this repo

Expand Down
Loading
Loading