Skip to content
Merged
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
12 changes: 12 additions & 0 deletions .github/osv-scanner-frozen-wsl-retrieval.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Dedicated OSV-Scanner v2.6.0 configuration for the retired historical WSL retrieval lock only.
# The explicit --config applies to every input of its invocation, not to a path encoded in this file:
# https://github.com/google/osv-scanner/blob/v2.6.0/docs/configuration.md
# https://github.com/google/osv-scanner/blob/v2.6.0/internal/config/manager.go (Manager.Get).
# The workflow's three disjoint input lists and preflight policy tests enforce the exact caller scope,
# reviewed digest, evidence, retirement guard and expiry. No ordinary or active QMD input receives this config.
# Its native bare-date syntax matches the unchanged main564 macOS archive pattern and the retained root control.

[[IgnoredVulns]]
id = "GHSA-vfj7-8cjw-p6xm"
ignoreUntil = 2026-10-17
reason = "2026-10-03 bounded retirement review: this config is assigned only to blueprints/convergence-practice/wsl-retrieval/package-lock.json at SHA256 5c51ee65cc477f2c1488a38ff5cad1c0a737f81a5b61bbd70d5edc4d15bfc3bb. It preserves the original lock as historical evidence; braces 3.0.3 remains affected by GHSA-vfj7-8cjw-p6xm/CVE-2026-93687. Both old source/QMD runner modes stop before subprocess or output creation, and a dependency-free private manifest uses npm 11.19.0 devEngines.runtime.name=retired-wsl-retrieval/onFail=error to reject supported install/ci entry points. Original manifest/recording-aid bytes are archived and original receipts, failure facts and prior runner archives remain unchanged. This is a supported-entry-point guard, not an installation sandbox: explicit --force, other package managers and restored historical files are outside its claim. Source disposition and exact artifact bindings: blueprints/convergence-practice/wsl-retrieval/retirement-assessment.json. Independent native controls and retained failures: evidence/receipts/wsl-retrieval-retirement-20261003.json. Owner handoff: https://github.com/seathatflowsinourveins/native-agent-stack/pull/608#issuecomment-5963764481. The workflow and inventory tests constrain this one input; OSV itself does not constrain an explicit config to that path. Active QMD remains separately unresolved and ordinary/macOS configs carry no exception for this advisory. This exception expires at the native TOML date 2026-10-17; retirement does not patch a dependency or qualify active QMD."
3 changes: 2 additions & 1 deletion .github/osv-scanner-lockfiles.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"path": "blueprints/convergence-practice/application-delivery/uv.lock"
},
{
"path": "blueprints/convergence-practice/wsl-retrieval/package-lock.json"
"path": "blueprints/convergence-practice/wsl-retrieval/package-lock.json",
"config": ".github/osv-scanner-frozen-wsl-retrieval.toml"
},
{
"path": "blueprints/memory-stack/native-qualification/uv.lock"
Expand Down
83 changes: 64 additions & 19 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ name: Dependency and workflow security scan
# .github/osv-scanner-lockfiles.json (tests/test_osv_lockfile_coverage.py fails
# when a tracked one is missing; its "excluded" list names deliberately vulnerable
# test fixtures, each with a reason) and fails on any vulnerability not ignored in
# .github/osv-scanner.toml, or, for the entries that name .github/osv-scanner-frozen-macos.toml, in that
# config (an explicit --config applies to every input of one invocation, so those entries are scanned on
# their own); its pull_request run is a required check (branch ruleset
# .github/osv-scanner.toml, or the dedicated frozen macOS and retired WSL configs named by those entries.
# An explicit --config applies to every input of one invocation; the workflow and policy preflight bind
# each dedicated config to its exact reviewed lock. Three exhaustive/disjoint groups are scanned separately;
# its pull_request run is a required check (branch ruleset
# 23739774). The scan jobs hold only a read token: on push, schedule and dispatch
# osv-sarif-upload and zizmor-sarif-upload, which run no installed tool, upload the SARIF.
# zizmor-online adds zizmor's online audits as SARIF for code scanning; since
Expand Down Expand Up @@ -64,47 +65,85 @@ jobs:
WRITE_SARIF: ${{ github.event_name != 'pull_request' }}
run: |
# `shell: bash` runs with -e; turn it off so a findings exit (1) is captured and
# the SARIF is still written, then fail the step with the worst status of the table runs.
# all three SARIF results are still written, then fail with the worst observed status.
set +e -u -o pipefail
inventory=.github/osv-scanner-lockfiles.json
frozen_config=.github/osv-scanner-frozen-macos.toml
frozen_wsl_config=.github/osv-scanner-frozen-wsl-retrieval.toml
# Scope comes from this caller, not OSV's explicit-config mechanism. Reject missing/duplicate inputs,
# config drift, changed lock digests, missing evidence, expired policy and restored replay/install routes.
python3 -m unittest \
tests.test_osv_lockfile_coverage.LockfileInventoryTests \
tests.test_osv_lockfile_coverage.FrozenScanTests \
tests.test_wsl_retrieval.RetiredRunnerTests || exit "$?"
# An entry without a parser lets OSV-Scanner infer it from the file name (":<path>").
# An explicit --config applies to every input of one invocation (OSV-Scanner docs/configuration.md),
# so the entries that name the frozen config are scanned in an invocation of their own under that
# config alone, and every other entry under .github/osv-scanner.toml, which holds no exception for them.
mapfile -t lockfiles < <(jq -r '.lockfiles[] | select(has("config") | not) | "--lockfile=\(.parser // ""):\(.path)"' "$inventory")
mapfile -t frozen < <(jq -r --arg config "$frozen_config" '.lockfiles[] | select(.config == $config) | "--lockfile=\(.parser // ""):\(.path)"' "$inventory")
# so each frozen group has its own invocation, and ordinary entries use the config with no archive exception.
# Read in the current shell without relying on mapfile, which older Bash lacks.
lockfiles=()
while IFS= read -r lockfile; do
lockfiles+=("$lockfile")
done < <(jq -r '.lockfiles[] | select(has("config") | not) | "--lockfile=\(.parser // ""):\(.path)"' "$inventory")
frozen=()
while IFS= read -r lockfile; do
frozen+=("$lockfile")
done < <(jq -r --arg config "$frozen_config" '.lockfiles[] | select(.config == $config) | "--lockfile=\(.parser // ""):\(.path)"' "$inventory")
frozen_wsl=()
while IFS= read -r lockfile; do
frozen_wsl+=("$lockfile")
done < <(jq -r --arg config "$frozen_wsl_config" '.lockfiles[] | select(.config == $config) | "--lockfile=\(.parser // ""):\(.path)"' "$inventory")
# Older Bash treats empty arrays as unset under -u; guard before expanding lengths.
test -n "${lockfiles[0]+set}" || exit 1
test -n "${frozen[0]+set}" || exit 1
test -n "${frozen_wsl[0]+set}" || exit 1
test "${#lockfiles[@]}" -gt 0 || exit 1
test "${#frozen[@]}" -gt 0 || exit 1
# Every entry is in exactly one scan: together the two lists are the inventory, so an entry that
test "${#frozen_wsl[@]}" -gt 0 || exit 1
# Every entry is in exactly one scan: together the three lists are the inventory, so an entry that
# names any other config is in neither and fails here.
test "$(( ${#lockfiles[@]} + ${#frozen[@]} ))" -eq "$(jq '.lockfiles | length' "$inventory")" || exit 1
test "$(( ${#lockfiles[@]} + ${#frozen[@]} + ${#frozen_wsl[@]} ))" -eq "$(jq '.lockfiles | length' "$inventory")" || exit 1
# Also enforce unique inputs and the two exact archive assignments in the shell caller itself.
jq -e --arg mac_config "$frozen_config" --arg wsl_config "$frozen_wsl_config" '
.lockfiles as $entries | ($entries | map(.path)) as $paths |
(($paths | length) == ($paths | unique | length)) and
([$entries[] | select(.config == $mac_config) | .path] ==
["evidence/artifacts/macos-application-20260924/variant/pnpm-lock.yaml"]) and
([$entries[] | select(.config == $wsl_config) | .path] ==
["blueprints/convergence-practice/wsl-retrieval/package-lock.json"])
' "$inventory" > /dev/null || exit 1
# --no-resolve: scan the versions each file pins. Transitive resolution of the
# unlocked manifests reported versions no lockfile installs (decision record).
scan=("$RUNNER_TEMP/osv-scanner/osv-scanner" scan source --config .github/osv-scanner.toml
--no-resolve "${lockfiles[@]}")
scan_frozen=("$RUNNER_TEMP/osv-scanner/osv-scanner" scan source --config "$frozen_config"
--no-resolve "${frozen[@]}")
scan_frozen_wsl=("$RUNNER_TEMP/osv-scanner/osv-scanner" scan source --config "$frozen_wsl_config"
--no-resolve "${frozen_wsl[@]}")
"${scan[@]}"
status=$?
"${scan_frozen[@]}"
frozen_status=$?
"${scan_frozen_wsl[@]}"
frozen_wsl_status=$?
statuses=("$status" "$frozen_status" "$frozen_wsl_status")
printf 'OSV primary exit codes: ordinary=%s frozen-macos=%s frozen-wsl=%s\n' "$status" "$frozen_status" "$frozen_wsl_status"
if [ "$WRITE_SARIF" = true ]; then
"${scan[@]}" --format sarif --output-file "$RUNNER_TEMP/osv-scanner/osv-scanner.sarif"
sarif_status=$?
"${scan_frozen[@]}" --format sarif --output-file "$RUNNER_TEMP/osv-scanner/osv-scanner-frozen-macos.sarif"
frozen_sarif_status=$?
"${scan_frozen_wsl[@]}" --format sarif --output-file "$RUNNER_TEMP/osv-scanner/osv-scanner-frozen-wsl-retrieval.sarif"
frozen_wsl_sarif_status=$?
statuses+=("$sarif_status" "$frozen_sarif_status" "$frozen_wsl_sarif_status")
printf 'OSV SARIF exit codes: ordinary=%s frozen-macos=%s frozen-wsl=%s\n' "$sarif_status" "$frozen_sarif_status" "$frozen_wsl_sarif_status"
# 0: no vulnerabilities; 1: vulnerabilities (already reported above); other codes are scanner errors.
for code in "$sarif_status" "$frozen_sarif_status"; do
if [ "$code" -gt 1 ]; then
exit "$code"
fi
done
fi
# The worst status of the two scans wins: 0 clean, 1 vulnerabilities, more a scanner error.
if [ "$frozen_status" -gt "$status" ]; then
status=$frozen_status
fi
# Preserve the worst status from every primary and SARIF invocation, including findings and scanner errors.
for code in "${statuses[@]}"; do
if [ "$code" -gt "$status" ]; then
status=$code
fi
done
exit "$status"
- name: Keep the OSV-Scanner SARIF for the upload job
# !cancelled(): a findings exit fails the scan step, and its SARIF must still reach
Expand All @@ -116,6 +155,7 @@ jobs:
path: |
${{ runner.temp }}/osv-scanner/osv-scanner.sarif
${{ runner.temp }}/osv-scanner/osv-scanner-frozen-macos.sarif
${{ runner.temp }}/osv-scanner/osv-scanner-frozen-wsl-retrieval.sarif
if-no-files-found: error
retention-days: 1

Expand Down Expand Up @@ -152,6 +192,11 @@ jobs:
with:
sarif_file: ${{ runner.temp }}/osv-scanner/osv-scanner-frozen-macos.sarif
category: osv-scanner-frozen-macos
- name: Upload the retired WSL artifact OSV-Scanner SARIF to code scanning
uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
with:
sarif_file: ${{ runner.temp }}/osv-scanner/osv-scanner-frozen-wsl-retrieval.sarif
category: osv-scanner-frozen-wsl-retrieval

zizmor-online:
if: github.event_name != 'pull_request'
Expand Down
86 changes: 53 additions & 33 deletions blueprints/convergence-practice/wsl-retrieval/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# Incomplete historical WSL retrieval reference
# Retired historical WSL retrieval reference

This directory is retired for installation and source/QMD replay. [run.py](run.py)
fails both old modes before launching a subprocess or creating an output directory.
The dependency-free [package.json](package.json) is a retirement guard; the original
manifest and recording aid are preserved as text artifacts. The retained lock
stays at its original path and remains in scanner inventory. Retirement neither
patches the dependency nor establishes a scanner exception.

The separate current QMD recipe is in [recipes/README.md](../../../recipes/README.md#component-catalog-install-and-check),
with current native fixture guidance in [docs/native-token-ci.md](../../../docs/native-token-ci.md).
Active QMD's [GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm)
advisory remains unresolved; this historical retirement does not qualify or change
that setup. [retirement-assessment.json](retirement-assessment.json) records the
current source disposition separately from the original receipts.

The retained September 20, 2026 receipts are an **incomplete historical fixture
reference**. They do not establish native E2E or adoption acceptance. Per-command
Expand Down Expand Up @@ -45,6 +59,17 @@ The successful QMD receipt originally mapped `run.py` directly; the offline audi
now resolves that historical name to the archived bytes. Neither receipt was
rewritten to pretend it recorded today's file or missing invocation metadata.

[package-original.json.txt](package-original.json.txt) preserves the original
174-byte manifest with SHA-256
`7bbf63c5eafd347ae5ae56c684be06ef2589d38f2aab580ca7986ca4122bc6a8`.
Every historical `package.json` binding resolves to that archive without rewriting
the receipts' frozen-input names or declared runner mappings.
[run-recording-aid.py.txt](run-recording-aid.py.txt) preserves the later 16,427-byte
recording aid with SHA-256
`be852ce99501f5bc4567b846b90fb0e91d91de77b0eafbd3b72bb4484a2f7d12`.
It was a future recording aid, and is not attributed to the original execution.
All original receipts, source review and earlier runner archives remain unchanged.

The [install receipt](install-receipt.json) still records the actual historical
`npm ci --ignore-scripts --omit=optional` action. Its contents and digest are
unchanged. The [inventory](install-inventory.json) reports no optional llama
Expand Down Expand Up @@ -78,35 +103,30 @@ omitted inputs and same-count replacement checks as well as incorrect spans,
source bodies, URI scope, stale updates, erased failures and unsupported claims.
A zero audit exit means retained facts are consistent; its result explicitly
reports `native_acceptance_established: false`. It cannot repair missing evidence.

## Future command capture and supported installation

[run.py](run.py) is a future recording aid. It now retains each attempted command's
sanitized argument vector and working directory before launch, preserves argument
boundaries, and records failed launches and timeouts. Private path roots become
scope markers such as `<RUN>` and `<NODE>`; original historical facts receive no
fabricated fields. Mocked regressions exercise this recording without invoking
native retrieval. Both previously executed runner versions remain archived.

For a separately authorized fresh QMD trial, follow the maintained
[QMD native recipe](../../../recipes/README.md#component-catalog-install-and-check) and
[native token fixture guidance](../../../docs/native-token-ci.md). The supported
installation control is:

```sh
NODE_LLAMA_CPP_SKIP_DOWNLOAD=true npm install --global \
--prefix "$NEW_OWNED_QMD_PREFIX" @tobilu/qmd@2.8.3
```

Required npm dependency lifecycle scripts remain enabled. Do not reuse the
historical blanket `--ignore-scripts` command as a fresh-host recipe. The retained
lock and optional-backend assertions describe the historical prefix; they do not
prove compatibility of a newly installed prefix. Use the maintained native fixture
for current supported installation acceptance, retaining its actual install and
runtime commands and outputs. This review performs no install or native rerun.

Acceptance requires recovered verifiable historical invocation evidence or a
separately authorized reachable-host trial with supported installation and complete
command capture. Preserve native accounts, model/effort settings, caching and
compaction. No automatic history capture is introduced. Whole-task provider,
parent/child/retry/cache usage remains unknown; no savings claim is made.
The companion `current_retirement_assessment` checks the exact new archives,
retained lock, retirement manifest and current entrypoint hashes. Regressions reject
changed recording-aid or manifest archives, restored dependencies/scripts and a
missing runtime guard. Both old modes must stop before output or subprocess work.
These are local integration and artifact checks; they do not establish native npm
guard acceptance or a scanner exception.

## Supported entrypoint retirement

The retained private manifest has no dependencies or lifecycle/replay scripts. Its
`devEngines.runtime` names `retired-wsl-retrieval` with `onFail: error`. In the reviewed
[npm 11.19.0 supported behavior](https://github.com/npm/cli/blob/v11.19.0/lib/base-cmd.js#L201),
that runtime name is rejected before ordinary `install` and `ci`, including
`--ignore-scripts`. The [tagged manifest documentation](https://github.com/npm/cli/blob/v11.19.0/docs/lib/content/configuring-npm/package-json.md#L1117)
describes the check. Independent native controls belong to the separate retirement
acceptance record; the offline audit checks the guard's artifacts only.

Removing a manifest alone would leave [npm Arborist's root-lock fallback](https://github.com/npm/cli/blob/v11.19.0/workspaces/arborist/lib/arborist/load-virtual.js#L50).
The guard protects supported npm entry points. It is not an installation sandbox:
explicit `--force`, other package managers and restored historical files are
outside its claim. The text archives are evidence for offline review; this
directory provides no supported replay or installation route.

Recovered historical invocation evidence could reopen the incomplete acceptance
assessment. A current QMD trial belongs to the separate maintained recipe and
current status, with supported installation and complete command capture. Whole-task
provider, parent/child/retry/cache usage remains unknown; no savings claim is made.
Loading
Loading