diff --git a/.github/workflows/openshell-targeted-tests.yml b/.github/workflows/openshell-targeted-tests.yml new file mode 100644 index 0000000..49f8e30 --- /dev/null +++ b/.github/workflows/openshell-targeted-tests.yml @@ -0,0 +1,214 @@ +name: OpenShell targeted regression tests + +on: + workflow_dispatch: + push: + branches: + - audit/openshell-sentry-2026-10 + paths: + - .github/workflows/openshell-targeted-tests.yml + +concurrency: + group: openshell-targeted-tests-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + +jobs: + targeted-regressions: + name: Run named tests at pinned OpenShell SHA + runs-on: ubuntu-24.04 + timeout-minutes: 60 + env: + OPEN_SHELL_SHA: b58e24c9dabd6d4bcf2b7186592d3ad50646541b + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 + steps: + - name: Checkout audit repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Checkout exact OpenShell commit + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + repository: NVIDIA/OpenShell + ref: b58e24c9dabd6d4bcf2b7186592d3ad50646541b + path: OpenShell + persist-credentials: false + + - name: Verify exact source SHA + shell: bash + run: | + set -euo pipefail + cd OpenShell + actual="$(git rev-parse HEAD)" + echo "expected_sha=$OPEN_SHELL_SHA" + echo "actual_sha=$actual" + test "$actual" = "$OPEN_SHELL_SHA" + mkdir -p ../artifacts + { + echo "audit_repository=omwei-org/eabc-agentrust-interoperability" + echo "audit_repository_sha=$GITHUB_SHA" + echo "workflow_ref=$GITHUB_WORKFLOW_REF" + echo "target_repository=NVIDIA/OpenShell" + echo "target_sha=$actual" + echo "checkout_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)" + } > ../artifacts/source-checkout.txt + + - name: Install Rust toolchain from pinned OpenShell source + uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # pinned Rust toolchain action + with: + toolchain: 1.95.0 + + - name: Install system build dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential clang cmake pkg-config libz3-dev + + - name: Install pinned cargo-nextest + run: cargo install cargo-nextest --version 0.9.143 --locked + + - name: List and run each named regression test + shell: bash + run: | + set -uo pipefail + cd OpenShell + mkdir -p ../artifacts + overall_rc=0 + + run_one() { + name="$1" + filter="$2" + junit="$GITHUB_WORKSPACE/artifacts/$name.junit.xml" + log="../artifacts/$name.log" + meta="../artifacts/$name.meta.txt" + listed="../artifacts/$name.list.txt" + tool_config="/tmp/nextest-$name.toml" + + { + echo "test_name=$filter" + echo "audit_repository=omwei-org/eabc-agentrust-interoperability" + echo "audit_repository_sha=$GITHUB_SHA" + echo "workflow_ref=$GITHUB_WORKFLOW_REF" + echo "target_sha=$(git rev-parse HEAD)" + echo "cargo_nextest_version=$(cargo nextest --version)" + echo "started_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)" + } > "$meta" + + set +e + cargo nextest list --locked --profile ci --workspace --features openshell-server/test-support > "$listed" 2>&1 + list_rc=$? + set -e + cat "$listed" + + if [ "$list_rc" -ne 0 ]; then + echo "result=HARNESS ERROR" | tee -a "$meta" + echo "nextest_list_exit_code=$list_rc" | tee -a "$meta" + overall_rc=1 + return + fi + + if ! grep -F -- "$filter" "$listed" >/dev/null; then + echo "result=NOT FOUND" | tee -a "$meta" + echo "nextest_list_exit_code=0" | tee -a "$meta" + overall_rc=1 + return + fi + + # Nextest writes JUnit via profile configuration, not a --junit CLI flag. + # Use a tool-specific overlay so upstream OpenShell files remain untouched. + printf '[profile.ci.junit]\npath = "%s"\nstore-success-output = true\n' "$junit" > "$tool_config" + + command="cargo nextest run --locked --profile ci --workspace --features openshell-server/test-support -E 'test(/(^|::)${filter}$/)' --tool-config-file openshell-audit:$tool_config" + { + echo "listed_test_match=$(grep -F -- "$filter" "$listed" | head -n 1)" + echo "command=$command" + } >> "$meta" + + set +e + cargo nextest run --locked --profile ci --workspace --features openshell-server/test-support -E "test(/(^|::)${filter}$/)" --tool-config-file "openshell-audit:$tool_config" > "$log" 2>&1 + rc=$? + set -e + cat "$log" + echo "cargo_nextest_exit_code=$rc" | tee -a "$meta" + + if [ ! -s "$junit" ]; then + echo "result=HARNESS ERROR" | tee -a "$meta" + echo "reason=JUnit report missing or empty" | tee -a "$meta" + overall_rc=1 + return + fi + + set +e + python3 - "$junit" "$filter" "$rc" >> "$meta" <<'PY' + import sys + import xml.etree.ElementTree as ET + + report, target, run_rc = sys.argv[1], sys.argv[2], int(sys.argv[3]) + try: + root = ET.parse(report).getroot() + except Exception as exc: + print("result=HARNESS ERROR") + print(f"junit_parse_error={exc}") + raise SystemExit(2) + + cases = list(root.iter("testcase")) + selected = [ + case for case in cases + if target == case.attrib.get("name", "") + or target in case.attrib.get("name", "") + or target in case.attrib.get("classname", "") + ] + print(f"junit_testcases_total={len(cases)}") + print(f"junit_matching_testcases={len(selected)}") + if len(cases) != 1 or len(selected) != 1: + print("result=HARNESS ERROR") + print("reason=Expected exactly one JUnit testcase for the exact named-test filter") + raise SystemExit(2) + + failures = [node for case in selected for node in list(case.findall("failure")) + list(case.findall("error"))] + skipped = [node for case in selected for node in case.findall("skipped")] + if failures: + print("result=FAIL") + print(f"junit_failures_or_errors={len(failures)}") + raise SystemExit(1) + if skipped: + print("result=NOT TESTED") + print(f"junit_skipped={len(skipped)}") + raise SystemExit(2) + if run_rc != 0: + print("result=HARNESS ERROR") + print("reason=nextest returned nonzero but matching JUnit testcase has no failure/error") + raise SystemExit(2) + print("result=PASS") + PY + junit_rc=$? + set -e + if [ "$junit_rc" -ne 0 ]; then overall_rc=1; fi + } + + run_one stale_generation_fails_before_relay_context_is_created stale_generation_fails_before_relay_context_is_created + run_one test_forward_relay_guard_blocks_stale_generation_before_upstream_write test_forward_relay_guard_blocks_stale_generation_before_upstream_write + run_one credential_guard_does_not_shadow_inspected_endpoint_config credential_guard_does_not_shadow_inspected_endpoint_config + + { + echo "audit_repository=omwei-org/eabc-agentrust-interoperability" + echo "audit_repository_sha=$GITHUB_SHA" + echo "workflow_ref=$GITHUB_WORKFLOW_REF" + echo "target_repository=NVIDIA/OpenShell" + echo "target_sha=$(git rev-parse HEAD)" + echo "toolchain=$(rustc --version)" + echo "cargo_nextest=$(cargo nextest --version)" + echo "finished_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)" + } > ../artifacts/run-summary.txt + for f in ../artifacts/*.meta.txt; do cat "$f" >> ../artifacts/run-summary.txt; done + exit "$overall_rc" + + - name: Upload logs, metadata, test listings and JUnit results + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: openshell-targeted-regressions-${{ github.run_id }}-${{ github.run_attempt }} + path: artifacts/ + if-no-files-found: error + retention-days: 30 diff --git a/audits/nvidia-openshell-sentry/README.md b/audits/nvidia-openshell-sentry/README.md new file mode 100644 index 0000000..9b34ab3 --- /dev/null +++ b/audits/nvidia-openshell-sentry/README.md @@ -0,0 +1,55 @@ +# NVIDIA OpenShell / Sentry — EABC audit + +## Purpose + +Track an evidence-based review of NVIDIA OpenShell and NVIDIA Sentry against the EABC execution-boundary model. This audit is separate from the repository's AgenTrust/cMCP interoperability experiment; it does not change that experiment's scope or conclusions. + +## Scope + +1. OpenShell standalone. +2. Sentry standalone. +3. OpenShell + Sentry composition, where supported and evidenced. +4. EABC-relevant properties: non-bypassability, boundary integrity, integrity of state/context, and exclusivity; record enforcement-substrate assumptions separately as EBP assurance constraints. + +## Evidence discipline + +Use the following status labels consistently: + +- **DOC-CLAIM**: a vendor/upstream documentation statement; not independently verified by runtime testing. +- **SOURCE**: behavior or control observed in pinned implementation source. +- **TEST-CONTRACT**: a test exists and asserts the stated behavior; this does not mean it was run. +- **RUNTIME**: evidence from an executed test in a recorded environment with commands, versions, observed results and artifacts. +- **NOT ASSESSED**: evidence has not yet been collected to evaluate the claim. + +Keep evidence class separate from test result. Runtime result vocabulary: **NOT TESTED**, **INCONCLUSIVE**, **PASS**, **FAIL**. Use **NOT REPRODUCED** only after an actual reproduction attempt was executed and its conditions/results recorded. + +Do not convert a source-level test into a claim of runtime validation. Do not report a vulnerability solely because a control was not found in the files reviewed. Record pinned commits and platform/driver scope for every conclusion. Every finding must include its evidence class, an explicit EABC criterion mapping (or state that mapping is not yet assessed), and permalink(s) to the pinned source/documentation with line ranges wherever available. A candidate EABC mapping is not a conformance result. + +## Current documents + +- [Findings register](findings.md) +- [Runtime test matrix](test-matrix.md) +- [OpenShell pinned-source evidence — original baseline `a4c848a`](evidence/openshell-a4c848a.md) +- [OpenShell follow-up source review — newer commit `b58e24c`](evidence/openshell-b58e24c.md) + +## Initial baseline + +OpenShell source review is pinned to [`a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`](https://github.com/NVIDIA/OpenShell/commit/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317). The review environment could not resolve GitHub/raw GitHub hosts for local checkout/runtime testing. Source/documentation inspection was performed through repository connector access; no runtime tests were executed. Therefore, runtime status remains NOT TESTED unless a later dated execution record is added. + +## Upstream drift — separate review required + +The initial findings and original matrix remain scoped to `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`. A later comparison checked upstream commit `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` (13 commits ahead at the time of comparison). That range materially changed the isolation interface, provisioning-evidence contract, RPC runtime and conformance tests. See [BASELINE-01 and BASELINE-02 in the findings register](findings.md) and the [baseline-drift gate and added tests](test-matrix.md). + +The source review found that the older common contract explicitly required four outer-fence guarantees, while the newer common contract binds native evidence to a generation and explicitly warns that the digest is not independent proof of enforcement. This is an **assurance-contract difference, not a confirmed vulnerability**. Partial counter-evidence has now been inspected: Docker and Podman verify actual container network configuration, while the VM source uses QEMU `-nic none` and configures libkrun with vsock/virtiofs rather than an IP NIC. These source-level controls reduce the basis for a claim of a direct-egress defect, but they do not replace runtime evidence or settle revocation/controller-loss behavior, all platform variants, or delegated-backend assurance. + +Do not silently replace the original pinned baseline. For any new runtime result, state the exact commit, driver, environment and evidence artifacts. A newer-upstream review should use a distinct execution record and revise scope only after examining the new validation paths. + +## Follow-up source review + +A targeted follow-up review was recorded for OpenShell commit `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. It adds source counter-evidence for generation guards, credential guard behavior, driver-level isolation checks and delegated-backend admission. It is **not** a complete re-audit of the newer commit, and no runtime tests were executed. The original findings and runtime matrix remain pinned to `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`; do not transfer findings or test results across commits without a commit-specific review and execution record. + +The current policy schema documents `allow_uninspected_credentials` as a security-sensitive explicit opt-in for credentialed traffic that cannot be inspected. See [NVIDIA policy schema](https://docs.nvidia.com/openshell/latest/reference/policy-schema). Documentation is `DOC-CLAIM`, not runtime evidence. + +## Working rule + +Every finding must state: claim, EABC relevance, evidence and pinned reference, counter-evidence/limits, status, and next falsification test. Keep vendor-specific features distinct from EABC conformance claims. \ No newline at end of file diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-a4c848a.md b/audits/nvidia-openshell-sentry/evidence/openshell-a4c848a.md new file mode 100644 index 0000000..7a4332b --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-a4c848a.md @@ -0,0 +1,105 @@ +# OpenShell source and documentation evidence baseline + +- Repository: `NVIDIA/OpenShell` +- Pinned commit: `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` +- Commit permalink: https://github.com/NVIDIA/OpenShell/commit/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 +- Review method: inspection of pinned source, repository documentation and source test contracts through GitHub repository access. +- Runtime status: **NOT TESTED**. Local checkout/runtime testing was not performed because GitHub host resolution failed in the review environment. +- Evidence-class rule: documentation statements are `DOC-CLAIM`; implementation observations are `SOURCE`; named test assertions are `TEST-CONTRACT`; only executed tests with reproducible artifacts are `RUNTIME`. + +These references document what was inspected. They do not establish that a test ran, that the control is effective under an adversarial runtime, or that OpenShell conforms to EABC. + +## OS-01 — Network mediation + +### Documentation claims (`DOC-CLAIM`) + +- Docker driver README, networking discussion: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-docker/README.md#L35-L49 +- Podman networking documentation: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-podman/NETWORKING.md#L1-L25 +- VM driver README, architecture/networking context: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/README.md#L1-L65 + +### Implementation and test-contract references (`SOURCE` / `TEST-CONTRACT`) + +- Socket confinement implementation: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-sandbox/src/linux/socket_confinement.rs#L150-L210 +- Network broker tests for non-loopback binding, explicit relay decision and denied connection: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-sandbox/src/network_broker.rs#L2880-L3010 + +**Interpretation:** Driver documentation and source test contracts were inspected. No runtime bypass test was performed. Docker, Podman and VM must be assessed independently; do not generalize a result across drivers. + +## OS-02 — Credential binding, rotation and revocation + +- Pinned E2E source test (`TEST-CONTRACT`): https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/e2e/rust/tests/stable_external_placeholders.rs#L1020-L1105 +- Named tests include `persistent_external_placeholder_rotation_and_revocation` and `ordinary_external_placeholder_keeps_revoked_assertion_after_rotation`. + +The test file is feature-gated for Docker E2E. The source contract uses synthetic endpoint behavior and generation/counter assertions. It is not a full MCP session or full agent-runtime test. Source presence is not a run record. + +## OS-06 — Authorization generation and credential guard + +### Implementation (`SOURCE`) + +- Proxy generation handling: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy.rs#L730-L770 +- OPA generation-guard definitions: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/opa.rs#L180-L225 +- Relay generation validation: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy/relay.rs#L95-L145 + +### Tests and documentation (`TEST-CONTRACT` / `DOC-CLAIM`) + +- Compatibility tests: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy/tests/compatibility.rs#L270-L345 +- RFC 0005 current-shape: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/rfc/0005-sandbox-proxy-egress-adapter/current-shape.md#L221-L240 +- RFC 0005 implementation plan: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/rfc/0005-sandbox-proxy-egress-adapter/implementation-plan.md#L66-L82 + +**Unresolved documentation/implementation discrepancy:** current-shape describes sibling metadata queries not all being asserted against the L4 decision generation; the implementation plan describes generation-consistent authorization cutover. These statements must be reconciled against the pinned implementation. Do not label the RFC stale until that comparison is completed. This discrepancy alone is not proof of a vulnerability. + +A credential-guard query without its own generation is a race-test lead, not a confirmed vulnerability by itself. Runtime race tests have not been performed. + +## OS-07 — Evaluation error versus missing L7 metadata + +- Pinned compatibility tests (`TEST-CONTRACT`): https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy/tests/compatibility.rs#L270-L345 +- `missing_authorized_l7_metadata_preserves_l4_only_fallback` +- `authoritative_evaluation_error_denies_without_metadata_fallback` + +The source tests distinguish a missing-metadata compatibility fallback from an authoritative evaluation error. Runtime status is **NOT TESTED**. The safety of L4-only fallback needs separate assessment for credential-injection endpoints: determine whether the weaker decision can permit a protected request or expose injected credentials. + +## OS-08 — VM bind mounts and virtiofs + +### Implementation and test contract (`SOURCE` / `TEST-CONTRACT`) + +- VM mount configuration and `read_only` defaults: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/src/driver.rs#L120-L160 +- Guest virtiofs target checks: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/scripts/openshell-vm-sandbox-init.sh#L520-L565 +- libkrun FFI surface: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/src/ffi.rs#L25-L75 +- VM bind-mount E2E test: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/e2e/rust/tests/vm_bind_mount.rs#L1-L100 +- VM driver documentation, mount configuration: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/README.md#L165-L200 + +### Upstream documentation claim (`DOC-CLAIM`) + +- libkrun repository/security notes: https://github.com/libkrun/libkrun + +The upstream documentation raises a host-side isolation question for paths visible to the VMM process. The exact reviewed upstream revision should be pinned before using it as a reproducible evidence artifact. This is not proof that OpenShell is vulnerable. + +The current E2E source contract does not cover in-share symlinks/hardlinks targeting outside paths, `..` traversal, or already-open file descriptors. Runtime host-path isolation remains unverified. Add harmless canary-file tests outside the permitted share and capture both guest behavior and host/VMM-side evidence. + +## SG-01 — Sentry standalone + +Evidence collection is pending. No Sentry version has yet been pinned. Before making claims, record the exact software/firmware version, device/model, deployment mode and configuration. Then establish the protected effect, all commit paths, attacker model, fail-closed behavior and relevant EABC criteria. Status: **NOT TESTED**. + +## COM-01 — OpenShell + Sentry composition + +Integration evidence collection is pending. Pin the OpenShell commit plus exact Sentry software/firmware version, device/model, deployment mode and configuration. Establish the actual commit path for the protected effect and test failure, policy change, alternate path and downgrade cases. Do not infer composition guarantees from individual component claims. Status: **NOT TESTED**. + + +## Sentry and composition — public claims only + +- Official NVIDIA announcement, published 28 September 2026: https://investor.nvidia.com/news/press-release-details/2026/NVIDIA-Launches-Open-Agent-Safety-Platform-to-Secure-Agents-From-Testing-to-Deployment/ +- Relevant announcement passage: https://investor.nvidia.com/news/press-release-details/2026/NVIDIA-Launches-Open-Agent-Safety-Platform-to-Secure-Agents-From-Testing-to-Deployment/ (description of OpenShell as software runtime boundary and Sentry/BlueField-4 as an out-of-band hardware layer; announcement lines 117–121). + +**Evidence class: `DOC-CLAIM` only.** This is NVIDIA's description of intended architecture and capabilities. It does not establish the behavior of a particular firmware/software release, prove all paths to a protected effect are mediated, or show conformance to EABC. + +### Candidate EABC mapping — unverified + +- `NON_BYPASSABILITY(B,E)`: must identify the concrete protected effect and enumerate every commit path, including local/alternate paths; vendor positioning does not prove complete mediation. +- `INTEGRITY_CTX(C,B,E)`: must demonstrate binding among requester/agent identity, policy decision, target, request context and the actual protected effect. +- `INTEGRITY_STATE(B,E)`: test stale authorization, policy update, reset, downgrade and component failure if these can affect boundary satisfaction. +- `ENFORCEMENT_INDEPENDENCE` is an EBP assurance constraint, not an EABC semantic property; it requires evidence about the enforcement path's independence from the compromised software under the declared adversary model. + +No exact Sentry firmware/software version, device configuration, or integrated runtime evidence has been pinned in this audit. Sentry standalone and OpenShell+Sentry composition remain `NOT TESTED`. + +## Evidence interpretation + +This file records pinned references and reviewer observations, not runtime logs. Add execution records separately with date, environment, exact commands, versions/configuration, observed client-side and effect-side results, artifacts, and status (`PASS`, `FAIL`, or `INCONCLUSIVE`). Keep failed and inconclusive attempts. Do not mark a test as run based on the presence of source code alone. diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-b58e24c.md b/audits/nvidia-openshell-sentry/evidence/openshell-b58e24c.md new file mode 100644 index 0000000..2aec482 --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-b58e24c.md @@ -0,0 +1,63 @@ +# OpenShell follow-up source review — b58e24c + +## Review identity + +- Repository: [NVIDIA/OpenShell](https://github.com/NVIDIA/OpenShell) +- Checked commit: [`b58e24c9dabd6d4bcf2b7186592d3ad50646541b`](https://github.com/NVIDIA/OpenShell/commit/b58e24c9dabd6d4bcf2b7186592d3ad50646541b) +- Commit message: `fix(supervisor): report plaintext scheme to middleware (#4397)` +- Committer timestamp: 2026-10-17T01:38:03Z +- Review type: targeted source/documentation inspection through GitHub repository access +- Runtime validation: **NOT TESTED**. No runtime commands, integration tests or bypass attempts were executed. +- Scope: targeted follow-up for OS-06, OS-09, BASELINE-02 through BASELINE-04. This is not a complete re-audit of all changed files or of every driver. + +## OS-06 — generation guards and stale relay + +**Evidence class: SOURCE + TEST-CONTRACT.** + +- [Generation guard implementation, `opa.rs` lines 206–249](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L206-L249): captures the expected generation, rejects a mismatch and exposes a current-generation check/wait path. +- [CONNECT setup checks, `proxy.rs` lines 2947–2999](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2947-L2999): checks staleness around upstream connection establishment and before returning CONNECT success. +- [Stale relay test, `proxy.rs` lines 14100–14150](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L14100-L14150): source test asserts a stale forward relay writes no bytes to upstream. + +**Limit:** these source controls/tests are not evidence that the tests were executed here, that all metadata was materialized from one generation, or that every race window is covered. Runtime status remains NOT TESTED. + +## OS-09 — L4 fallback and credential guard counter-evidence + +**Evidence class: SOURCE + TEST-CONTRACT + DOC-CLAIM.** + +- [CONNECT credential guard decision, `proxy.rs` lines 2899–2944](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2899-L2944): provider-credentialed endpoints are rejected when uninspected credentials are not explicitly allowed. +- [Credential-guard aggregation, `proxy.rs` lines 4008–4054](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L4008-L4054). +- [OPA regression test, `opa.rs` lines 9612–9690](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L9612-L9690): tests that an L4-only credentialed endpoint does not shadow the inspected endpoint's TLS/SSRF configuration. +- [Current provider profile documentation](https://docs.nvidia.com/openshell/latest/reference/policy-schema): documents host/port/path binding and separates credential binding from network-policy authorization. + +**Interpretation:** this is counter-evidence against treating L4 fallback alone as a confirmed vulnerability. It does not replace end-to-end testing for missing/malformed metadata, overlapping endpoints, policy reloads or the explicit opt-in path. Runtime status remains NOT TESTED. + +## BASELINE-02 / BASELINE-03 — native enforcement evidence + +- [Current common provisioning-evidence contract, `contract.rs` lines 219–293](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-isolation-interface/src/contract.rs#L219-L293): binds native evidence to a generation and warns that a digest is not independent proof of enforcement. +- [Docker isolation projection, `isolation.rs` lines 25–60](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-docker/src/isolation.rs#L25-L60) and [actual Docker outer-fence inspection, `lib.rs` lines 3082–3110](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-docker/src/lib.rs#L3082-L3110). +- [Podman fence verification, `client.rs` lines 564–595](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-podman/src/client.rs#L564-L595). +- [VM launch arguments, `runtime.rs` lines 121–150 and 188–190](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-vm/src/runtime.rs#L121-L150): QEMU launch includes `-nic none`. +- [libkrun launch, `runtime.rs` lines 320–354](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-vm/src/runtime.rs#L320-L354): describes the vsock/virtiofs device setup and no network helper. + +**Interpretation:** these are useful source-level controls, not runtime proof. A fixed evidence field or matching digest does not alone prove actual enforcement; conversely, the inspected launch/inspection code is counter-evidence against asserting a defect solely from the evidence representation. + +## BASELINE-04 — delegated backend trust boundary + +- [Backend selection and admission, `backend_setup.rs` lines 51–140](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/backend_setup.rs#L51-L140). +- [Registration tests, `backend_setup/tests.rs` lines 37–109](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/backend_setup/tests.rs#L37-L109) and [admission rejection test, lines 387–416](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/backend_setup/tests.rs#L387-L416). +- [Runtime confirmation binding, `runtime.rs` lines 357–375](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox-backend/src/runtime.rs#L357-L375). +- [Delegated test permitting null `backend_audit`, lines 81–107](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox-backend/src/runtime/tests/delegated.rs#L81-L107). + +**Interpretation:** source shows trusted backend selection and context binding. It does not independently prove that an admitted delegated backend truthfully enforces the boundary it claims. That is an operator/deployment trust question to verify, not a confirmed vulnerability. + +## EABC mapping (candidate criteria, not conformance results) + +- `NON_BYPASSABILITY(B,E)`: every path to the protected effect must traverse the declared enforcement boundary. +- `INTEGRITY_DEF(B)`: the declared boundary must be complete and stable. +- `INTEGRITY_STATE(B,E)`: policy/generation changes and revocation must be reflected in enforcement state. +- `INTEGRITY_CTX(C,B,E)`: identity, generation, endpoint/credential context and actual enforcement instance must correspond. +- EBP assurance constraints such as enforcement independence and temporal consistency remain separate from the EABC semantic properties. + +## Outstanding verification + +Run the matrix against this exact commit and record host, driver, configuration/policy hashes, commands, timestamps, upstream canary records, and artifacts. Until then, all runtime outcomes remain **NOT TESTED**. diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-gen01-coverage-inventory.md b/audits/nvidia-openshell-sentry/evidence/openshell-gen01-coverage-inventory.md new file mode 100644 index 0000000..744c161 --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-gen01-coverage-inventory.md @@ -0,0 +1,38 @@ +# GEN-01 coverage inventory — existing tests vs missing evidence + +Reviewed source: NVIDIA/OpenShell `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. +Status: **SOURCE/TEST INVENTORY ONLY — NO TESTS EXECUTED BY THIS AUDIT**. + +## Existing source-level coverage found + +1. `crates/openshell-supervisor-network/src/proxy/relay.rs` contains `stale_generation_fails_before_relay_context_is_created()`. It captures a decision generation, reloads policy, and asserts relay context is not created. This covers stale generation at relay-context preparation, not upstream receipt during CONNECT setup. +2. `PolicyGenerationGuard` exposes `is_stale()`, `ensure_current()`, and `wait_until_stale()`. The relay uses the watch-based stale signal to terminate inspected and passthrough streams. +3. CONNECT races upstream dialing against `wait_until_stale()` and calls `ensure_current()` after dialing, before sending `200 Connection Established`. +4. `authorize_egress()` captures the generation and evaluates the primary authorization result while holding the engine mutex. `query_endpoint_credential_guards()` also locks the same engine; reload replaces the engine and advances generation under the engine lock. +5. The credential-guard query does not return its own generation. Therefore callers cannot directly compare the guard query's generation to the captured authorization generation using that return value alone. This is a testability/explicit-evidence gap, not proof of a race: engine serialization plus the later CONNECT generation guard may already ensure safe behavior. + +Source links: +- [Stale generation relay-context regression test](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy/relay.rs) +- [Generation guard and credential query](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs) +- [CONNECT dial cancellation and final generation check](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs) + +## GEN-01 minimal test recommendation + +Do not start with a new broad integration harness. First run the existing targeted unit test in a local checkout of the exact pinned commit, then add a deterministic unit-level test for the credential-guard/reload ordering using a test-only barrier or lock-aware seam. + +Minimum assertions: +- If the guard query acquires the engine lock before reload, it observes the old engine; if reload acquires it first, it observes the new engine. +- After reload publication, the old `PolicyGenerationGuard` becomes stale and the CONNECT path rejects before returning success. +- No test should infer the credential query's generation from wall-clock order alone; record lock/barrier order and generation values explicitly. +- Add a canary-backed integration test only after the unit-level interleaving is deterministic. Canary must record request/credential presence without logging the secret itself. + +## Missing evidence / limitations + +- This audit did not build OpenShell or execute Cargo tests. +- The existing relay-context test is not a full CONNECT + upstream-canary test. +- No evidence reviewed here establishes whether the current test suite has a deterministic barrier exactly between credential-guard query completion and the final CONNECT generation check. +- The return type of `query_endpoint_credential_guards()` omits generation, which makes direct assertion of metadata-generation provenance less explicit than for APIs ending in `_with_generation`; do not label this a vulnerability without demonstrating a policy violation. + +## Status and disposition + +GEN-01 through GEN-04 remain **NOT TESTED** for this audit. The current source evidence reduces the original mixed-generation hypothesis. The next useful action is to execute the existing targeted test in a pinned checkout, then decide whether a new test seam is actually needed. \ No newline at end of file diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-gen01-regression-coverage.md b/audits/nvidia-openshell-sentry/evidence/openshell-gen01-regression-coverage.md new file mode 100644 index 0000000..a54713b --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-gen01-regression-coverage.md @@ -0,0 +1,44 @@ +# GEN-01 regression coverage review + +Reviewed against NVIDIA/OpenShell source commit `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. +Status: **SOURCE/TEST DISCOVERY ONLY — NOT EXECUTED HERE**. + +## Existing coverage found + +1. `crates/openshell-supervisor-network/src/proxy/relay.rs` contains `stale_generation_fails_before_relay_context_is_created()`. This is direct unit-test evidence that stale generations are rejected before an HTTP relay context is created. +2. `crates/openshell-supervisor-network/src/opa.rs` implements `authorize_egress()` by holding the engine mutex while capturing `current_generation()` and evaluating the combined `egress_authorization` rule. The authorization returns its generation and policy-derived endpoint metadata together. +3. `OpaEngine::reload()` acquires the same engine mutex before replacing the compiled engine and advancing the generation. The policy+middleware+credentials reload path also takes the engine mutex and advances generation as part of publication. +4. CONNECT uses a generation guard while dialing upstream, rejects if the guard becomes stale, and validates the L7 route generation before CONNECT success. The relay path retains a generation-pinned policy primitive. +5. Credential-guard aggregation has an OPA regression test for overlapping L4 and inspected endpoint definitions, and `query_endpoint_credential_guards()` is a distinct API called from the CONNECT setup path. + +Source pointers: +- [Stale relay-context regression](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy/relay.rs) +- [Authorization snapshot and reload lock](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L600-L830) +- [CONNECT credential guard and generation-gated dial](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2700-L2965) +- [Credential-guard aggregation](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L3990-L4055) +- [Overlapping-endpoint OPA regression](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L9612-L9690) + +## What the discovered tests do not establish by themselves + +- A unit test that rejects a stale relay context does not prove an independently observed upstream received no protected bytes in every CONNECT timing window. +- The overlap regression tests policy aggregation/precedence, not necessarily a reload interleaving at the credential-guard call boundary. +- Source-level mutex ordering supports serialization, but only a test exercising the pinned runtime/build can establish the end-to-end behavior of the full path. + +## Smallest useful GEN-01 extension + +Prefer extending the existing relay/OPA unit-test harness rather than adding sleeps or a new standalone harness first. + +1. Find the current test fixtures for `OpaEngine`, credentialed endpoint policy, and overlapping L4/L7 endpoints. +2. Add a test-only deterministic barrier immediately before and after `query_endpoint_credential_guards()` in CONNECT setup, without changing production behavior. +3. In the paused window, attempt a policy reload that changes the endpoint from explicit uninspected-credential allowance (P1) to inspected-only (P0), then reverse the direction in a separate case. +4. Assert the engine's lock/reload ordering and generation values explicitly. Do not deadlock by trying to reload while a test deliberately holds the engine mutex inside the query; place barriers outside the locked evaluation or coordinate the query and reload on separate tasks. +5. Assert the CONNECT result and generation guard outcome. For any claim about upstream receipt, run the isolated binary against a local canary that records request/body hashes and only a boolean for the synthetic credential; never log credential values. +6. Run the narrow Rust tests first, then the relevant crate suite. Capture exact commands, exit codes, commit SHA, and logs. + +## Decision criteria + +- If the barrier cannot expose a valid interleaving because the mutex serializes query and reload, record that as evidence against the hypothesized race, not as a security failure. +- If reload occurs after the credential query, the captured generation guard should make the connection stale before protected relay activity. Verify at the exact call path rather than assuming. +- A unit-test PASS is unit-level evidence only. Keep the upstream-canary scenario separate and NOT TESTED until actually run. + +**Current result:** existing source tests and synchronization make a simple mixed-generation race less plausible. No GEN-01 runtime test was executed as part of this audit update; all GEN statuses remain **NOT TESTED**. \ No newline at end of file diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-generation-runtime-protocol.md b/audits/nvidia-openshell-sentry/evidence/openshell-generation-runtime-protocol.md new file mode 100644 index 0000000..4c59e79 --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-generation-runtime-protocol.md @@ -0,0 +1,59 @@ +# Runtime protocol — GEN-01 through GEN-04 + +Date: 2026-10-17 +Status: **PLAN ONLY — NOT EXECUTED** + +## Preconditions +Run only in an isolated disposable lab against a pinned OpenShell build. Use synthetic, non-reusable credentials, harmless payloads, and a controlled canary upstream. Never use production credentials or customer data. + +Required: exact source/build/runtime versions; valid policy fixtures and hashes; deterministic barriers at the intended code seams; a client transcript; proxy/OPA logs with secrets redacted; and an independent canary that records connection time, path, body hash/length, and only a boolean indicating whether the synthetic credential was present. Never log the credential value. + +If a barrier cannot be placed at the intended seam, classify the scenario as INCONCLUSIVE rather than approximating with sleeps. + +## Policy fixtures +- **P0 — inspected-only:** credentialed endpoint requires L7 inspection; uninspected credential traffic is not allowed. +- **P1 — explicit exception:** only for testing the documented `allow_uninspected_credentials: true` exception, scoped to the exact test endpoint. +- **P2 — quarantine:** test endpoint denied. +- **P3 — overlap:** L4-only credentialed and inspected endpoint definitions match the same host/port and have distinguishable harmless metadata. + +Use the pinned version's actual supported schema. Archive effective parsed policies and hashes. If a fixture cannot be expressed, record the limitation and mark affected tests INCONCLUSIVE. + +## Procedure +1. Start the canary and verify its log is empty. +2. Load initial policy; record hash and generation. +3. Start the client and pause at the deterministic barrier. +4. Publish the next policy and confirm the new generation is active. +5. Release the barrier; capture client result and relay-close behavior. +6. Collect generation snapshots, OPA/proxy traces, client transcript, and independent canary records. +7. Repeat deterministic interleavings where practical. Repetition supplements, but does not replace, barrier control. + +## GEN-01 — L4 authorization vs credential guard +Place a barrier after the primary L4 decision and before the credential-guard query; add a second barrier after the query if possible. Test both P1 → P0 and P0 → P1. Record decision generation, guard query start/end, current generation, and endpoint identity. +**Expected:** setup is evaluated consistently under a valid pinned generation or rejected as stale. P1 → P0 must not deliver protected data or synthetic credentials under stale permission. The explicit exception must remain confined to the configured endpoint. + +## GEN-02 — final generation check vs CONNECT success +Place a barrier immediately after the final generation/staleness check and before CONNECT success or relay startup is committed; verify the exact seam for the pinned commit. Publish P0 or P2 while paused, confirm activation, then release. +**Expected:** stale CONNECT is rejected/closed according to the implementation contract. The canary receives no protected request or credential that the new policy denies. Record upstream TCP connection separately from accepted application bytes. + +## GEN-03 — active relay invalidation +Establish raw CONNECT, inspected HTTP/L7, and long-lived relay types supported by the pinned build. Publish P2 while idle, during a harmless in-flight request, and before a subsequent protected request. Record publication and close timestamps. +**Expected:** stale relay closes or becomes unusable at the documented invalidation point; the canary accepts no later protected request or synthetic credential. Distinguish pre-publication bytes from post-publication bytes; do not claim retroactive prevention. + +## GEN-04 — metadata materialization sequence +Place barriers at each available seam: (1) L4 authorization, (2) L7 route, (3) credential guard, (4) TLS mode, (5) destination constraints including allowed IPs/exact-host signals, (6) final generation check, and (7) route hydration/relay startup. Reload at each boundary. Include P3 overlapping endpoints. Test absent/malformed metadata and authoritative OPA errors as separate cases. +**Expected:** metadata influencing one authorization is consistent with its claimed generation, or the operation fails closed before forbidden protected bytes/credentials arrive. Endpoint precedence is deterministic. Missing/malformed metadata does not silently broaden access. + +## Result classification +- **PASS:** barrier and policy-generation transition are evidenced; behavior meets the safe expectation; the independent canary confirms no forbidden protected request/credential arrived. +- **FAIL:** the canary receives data/credentials denied by the active policy, stale CONNECT succeeds contrary to contract, or a stale relay continues protected activity beyond the required invalidation point. +- **INCONCLUSIVE:** barrier ordering or generation activation is unproven, logs are missing, or effect-side observation cannot distinguish pre- from post-reload traffic. + +A proxy denial log, unit test, or source inspection alone cannot earn PASS for an upstream-receipt claim. + +## Evidence manifest +For each run record scenario/run ID; source commit and build digest; platform/driver/runtime versions; policy hashes and generation values; barrier reach/release times; policy-publication acknowledgement; redacted OPA/proxy traces; client transcript; canary record with body hash/length and synthetic-credential-present boolean; relay-close timestamp; result, scope, deviations and reviewer. Never store raw credentials or reusable tokens. + +## Scope +Results apply only to the pinned build, driver and fixtures. A PASS does not establish behavior for every version or policy combination. A FAIL requires triage against the documented contract before assigning vulnerability severity. + +**Current status:** GEN-01 through GEN-04 remain **NOT TESTED**. This document is a protocol only; no runtime execution is claimed. \ No newline at end of file diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-generation-seam-map.md b/audits/nvidia-openshell-sentry/evidence/openshell-generation-seam-map.md new file mode 100644 index 0000000..61ea585 --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-generation-seam-map.md @@ -0,0 +1,48 @@ +# GEN test seam map — pinned source review + +Reviewed source: NVIDIA/OpenShell commit `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. +Status: **SOURCE REVIEW ONLY — NO RUNTIME TESTS EXECUTED**. + +## Confirmed code order for CONNECT + +1. L4 decision is produced in `proxy.rs` in the CONNECT handler. +2. `relay::pin_policy_generation(&opa_engine, decision.policy_generation)` captures a generation guard; failure rejects stale CONNECT. +3. `hydrate_tls_mode(&mut decision)` derives TLS mode from the decision snapshot. +4. `query_endpoint_credential_guard(&opa_engine, &decision, &host_lc, port)` separately queries credential guard using the decision's identity fields. +5. `hydrate_l7_route(&mut decision)` materializes the L7 route snapshot. +6. `hydrate_destination_plan(...)` and destination validation run before upstream dialing. +7. The code checks `credential_guard.blocks_connect()` and then validates the L7 route generation against the captured generation before `dial_upstream` and before returning CONNECT 200. + +Relevant source: +- [CONNECT authorization and generation pinning](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2700-L2855) +- [Credential guard and route generation checks](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2850-L2960) +- [Credential guard query implementation](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L3990-L4055) +- [Generation guard implementation](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L195-L240) +- [Route-generation validator](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy/relay.rs#L105-L135) + +## Test-seam requirements + +- **GEN-01:** the best seam is between generation pinning / TLS hydration and the credential guard query, plus one after the query. The current function is synchronous at the call site, but its underlying OPA query path may be sync; use a test-only hook/barrier inside a test harness rather than a sleep. Verify the policy engine reload semantics and generation update order before interpreting the race. +- **GEN-02:** place a hook after `validate_route_generation` and before `dial_upstream` / `200 Connection Established`. The source excerpt shows the validation precedes dialing; confirm the exact `200` write location at the pinned commit before adding a barrier. +- **GEN-03:** use the `PolicyGenerationGuard::wait_until_stale` relay select branch and existing close behavior. Test raw and inspected relays separately; if the raw path does not use this guard, document that fact and trace the raw relay shutdown branch. +- **GEN-04:** hooks are required around the full sequence above, especially the separate credential-guard query. For TLS and destination policy, distinguish fields read from the `EgressDecision` snapshot from independent engine queries; do not assume a race exists merely because helper functions are separate. + +## Important limitation + +The inspected CONNECT path already pins a generation, derives TLS mode from the decision snapshot, stamps the hydrated L7 route with `decision.policy_generation`, checks route-generation equality before dialing, and uses a generation guard for stale relay handling. This materially lowers the plausibility of a simple mixed-generation CONNECT race. The credential guard is a separate engine query, but its query implementation and engine locking/reload semantics must be inspected together before claiming it can observe a different policy generation. + +To proceed from source review to a genuine runtime result, obtain a runnable checkout/build environment for this exact commit, add deterministic test-only barriers, and run the canary-backed scenarios. GitHub source reads alone cannot establish runtime behavior. + +**Disposition:** all GEN scenarios remain **NOT TESTED**. + +## Revision after engine-lock inspection + +The pinned source shows that `authorize_egress()` materializes action, endpoint configs, matched endpoints, exact-host signal and generation in one OPA result under the engine mutex. TLS and L7 route are derived from that decision snapshot. The credential-guard query is separate but also serializes on the engine mutex, while reload uses that mutex. Therefore do **not** treat separate helper calls alone as proof of mixed-generation metadata. + +Refined runtime priorities: +1. GEN-01: prove generation publication and credential-guard query serialization at the real barrier; then verify the generation guard rejects the stale CONNECT before protected bytes can pass. +2. GEN-02: target the final `ensure_current()` / CONNECT-success / relay-startup boundary and observe upstream effects independently. +3. GEN-03: use existing reload invalidation tests as baseline and add canary evidence for relay shapes whose upstream effects are not already covered. +4. GEN-04: only instrument independently queried fields or alternate paths. Do not claim TLS/L7 are separate OPA reads in this CONNECT path. + +See the addendum in [openshell-os06-generation-review.md](openshell-os06-generation-review.md). Runtime remains NOT TESTED. diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-os06-generation-review.md b/audits/nvidia-openshell-sentry/evidence/openshell-os06-generation-review.md new file mode 100644 index 0000000..f6290a3 --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-os06-generation-review.md @@ -0,0 +1,78 @@ +# OS-06 follow-up — authorization generation and credential guard + +Review date: 2026-10-17 +Original audit baseline: `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` +Follow-up source commit: `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` +Runtime status: **NOT TESTED**. This is a source/RFC comparison and test-plan refinement, not a runtime test report. The two SHAs are separate evidence baselines; this follow-up does not silently rebase the original findings or test matrix. + +## Question + +Does the implementation ensure that the L4 authorization decision, endpoint metadata used for TLS/L7 and credential handling, and relay enforcement all refer to one policy generation? Does it fail closed when a policy reload occurs during connection setup or while a relay is active? + +## RFC comparison + +The RFC's `current-shape.md` at the pinned baseline explicitly states that L4 authorization, L7 route, TLS mode, `allowed_ips`, and exact-declared-host metadata were materialized through separate engine calls and that sibling metadata queries were not all asserted against the L4 decision generation. It identifies mixed-generation materialization as a risk and states the target: all policy-derived fields must come from one generation and stale decisions must be rejected before an upstream request is written. + +The RFC implementation plan's Phase 3 calls for one OPA result containing matched policy/source, endpoint, destination constraints, TLS, HTTP enforcement, credential plan and middleware selection; shadow-mode comparison; and reload-race tests. This is an explicit target/plan, not evidence that the full cutover was completed. + +References: +- [RFC current-shape at baseline](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/rfc/0005-sandbox-proxy-egress-adapter/current-shape.md#L221-L240) +- [RFC implementation plan at baseline](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/rfc/0005-sandbox-proxy-egress-adapter/implementation-plan.md#L66-L82) + +## Follow-up source evidence at `b58e24c` + +### Controls observed + +- CONNECT checks the captured connection generation against the L7 route generation before proceeding with upstream connection setup. A mismatch is rejected through the stale-policy path. + - [CONNECT credential guard and route-generation check](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2899-L2944) +- Relay setup validates that the route's `l7_policy_generation` equals the expected L4 decision generation. + - [`validate_route_generation`](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy/relay.rs#L110-L132) +- A `PolicyGenerationGuard` compares the captured generation with the current generation and can wait for a generation change, supporting closure of stale relays. + - [Generation guard](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L195-L240) +- Credential guard aggregation considers all matching credentialed endpoint guards and is conservative across them: uninspected credentials are allowed only if all relevant credentialed matches opt in; L7 protocol presence likewise must hold across the matches. CONNECT rejects credentialed raw-tunnel use unless explicitly permitted. + - [Credential guard aggregation](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L4008-L4054) + - [OPA overlapping-endpoint regression test](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L9612-L9690) + +### What this does and does not settle + +These are meaningful source-level controls. They narrow the hypothesis: it would be inaccurate to say that the implementation has no generation guard or that credentialed L4 fallback is always permitted. + +They do not, by themselves, establish that every sibling metadata field (credential guard, TLS mode, destination allowlist and exact-host signals) is materialized atomically from the same generation as the primary L4 decision. In the inspected source, the explicit equality check is visible for the L7 route generation; the separate credential-guard query is passed the already-created decision's identity fields but does not visibly take an expected-generation argument at its call boundary. This is a race-test lead, not proof of a defect: the engine may serialize or otherwise constrain the relevant state, and runtime ordering must be established before making a vulnerability claim. + +The source-level discrepancy is **partially narrowed, not fully closed**. Source shows route-generation rejection and stale-relay machinery, and TLS/L7/destination values in the inspected CONNECT path are projections of the original snapshot. The credential guard is a separate OPA evaluation; its API returns values without a paired generation, while CONNECT relies on its captured generation guard and later checks. The broad mixed-generation claim for TLS/L7/destination is not supported by this source trace. The remaining conformance question depends on whether Phase 3 was declared planned, in progress or complete for the exact commit; the RFC sources inspected describe it as a later cutover after shadow comparison but do not establish a commit-specific completion status. + +## GEN-01 through GEN-04 — runtime falsification plan + +Run only in an isolated lab with synthetic credentials, harmless canary payloads, deterministic barriers and a canary upstream that independently records accepted paths, request bodies and whether a synthetic credential was present. Do not log raw secrets. + +1. **GEN-01 — authorization versus credential guard:** pause after the main L4 decision and before/after credential-guard evaluation. Reload in both directions: raw/L4 allowed to inspected credential-constrained, and inspected to raw/L4. Record every captured/current generation and whether CONNECT is accepted. +2. **GEN-02 — final check versus CONNECT success:** pause after the final generation validation and before success is returned/relay setup completes. Publish a new policy generation. Determine whether any protected bytes or injected credential reach the canary. +3. **GEN-03 — active relay invalidation:** establish raw, REST/L7 and long-lived relays, then publish a new generation or fail-closed quarantine. Confirm stale relays close and no protected bytes/credentials are accepted after the applicable invalidation point. +4. **GEN-04 — metadata materialization sequence:** add barriers around L4 authorization, L7 route, credential guard, TLS mode, destination allowlist/exact-host metadata and relay startup. Reload at each boundary and repeat with overlapping L4/L7 endpoints, malformed/missing metadata and explicit opt-in. + +For each run, capture commit, driver/platform, effective policy hash, old/new generation, barrier schedule, OPA/proxy traces, client transcript, upstream canary records and relay-close timing. A supervisor denial log alone is insufficient to establish that the upstream received no protected data. + +**Expected safe result:** no mixed-generation decision may authorize a protected upstream request; stale CONNECT is rejected/closed before protected bytes or credentials arrive; active stale relays close; explicit `allow_uninspected_credentials: true` affects only the endpoint and scope represented by the effective policy. + +**Status:** all four rows remain **NOT TESTED**. No runtime attempt was performed as part of this follow-up. + + +## Addendum — deeper engine-lock and authorization-snapshot inspection + +Follow-up source inspection at the same pinned OpenShell commit materially narrows the remaining hypothesis: + +- `OpaEngine::authorize_egress()` holds the engine mutex while it captures `current_generation()` and evaluates `data.openshell.sandbox.egress_authorization`. The returned `EgressAuthorization` includes action, endpoint configs, matched endpoints, exact-declared-host signal, and the generation captured under that lock. +- TLS mode and L7 route are hydrated from the already materialized `EgressDecision` endpoint snapshot; they are not separate policy-engine reads in this CONNECT path. +- The credential-guard query is separate, but it also obtains the same engine mutex for its OPA evaluation. Reload paths take that mutex before replacing the engine and advancing generation. Therefore the query itself is serialized against reload; its result is not an unsynchronized read of a mutating engine. +- CONNECT later races upstream dialing against `connect_generation_guard.wait_until_stale()` and checks `ensure_current()` after dialing, before writing CONNECT success. Relay paths also carry generation guards. + +Source references: +- [Single-result authorization under engine mutex](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L600-L675) +- [Reload lock and generation publication](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L735-L830) +- [CONNECT generation guard, credential guard, route validation and dial guard](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2700-L2965) + +**Revised interpretation:** the broad claim that CONNECT's TLS, L7 route, destination metadata, and top-level authorization are independently queried and can therefore mix generations is not supported by this inspected path. Most of those fields come from one authorization snapshot. The remaining runtime question is narrower: whether a reload around the separate credential-guard query, upstream dial completion, CONNECT success, or relay startup can produce an externally observable policy violation despite the generation guard. The source indicates that the credential-guard OPA evaluation is serialized against reload by the engine mutex, but the guard result itself is not returned with a generation. The exact safety claim to test is therefore the handler's generation binding and protected-effect outcome, not an assumed concurrent mutation of the OPA engine. Source inspection is not a runtime falsification test. + +GEN-01 should now focus on proving the serialisation/guard behavior rather than assuming mixed-generation metadata. GEN-02 should test the final-check-to-CONNECT-success boundary and independently observe whether a stale relay can carry any protected bytes. GEN-03 should reuse existing relay-reload regression tests and add upstream-side observation only where missing. GEN-04 should not repeat the disproven premise that TLS and L7 are separate OPA queries in this CONNECT path; target only fields actually queried independently and paths not covered by the snapshot. + +**Status remains:** GEN-01 through GEN-04 **NOT TESTED**. diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-revocation-controller-loss-review.md b/audits/nvidia-openshell-sentry/evidence/openshell-revocation-controller-loss-review.md new file mode 100644 index 0000000..8f15d5f --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-revocation-controller-loss-review.md @@ -0,0 +1,111 @@ +# OpenShell revocation and controller-loss evidence review + +Review date: 2026-10-17 +Source commit: `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` +Original comparison baseline: `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` +Status: **SOURCE REVIEW ONLY — runtime tests NOT TESTED. No confirmed vulnerability claimed.** + +## Question + +The old isolation contract required `RevocationVerified` and `ControllerLossFailsClosed` in the common outer-fence guarantee set. The newer contract uses generation-bound `ProvisioningEvidence`. This review asks whether the corresponding guarantees can be traced to the new contract, common runtime, and concrete backend paths. + +## Evidence found + +**Evidence-class convention:** `DOC-CLAIM` identifies a normative/documentation statement; `SOURCE` identifies inspected implementation; `TEST-CONTRACT` identifies a test definition or named test in source; `RUNTIME` requires an executed test with recorded observations. No `RUNTIME` evidence was generated by this review. + +### 1. The new isolation-backend RFC retains a normative loss requirement + +`DOC-CLAIM` — RFC 0012, at the pinned source commit, states that if the logical supervisor or its transport is lost, enforcement must remain in force and supervisor-dependent operations fail closed. Network-mediation unavailability must deny outbound connections without enabling direct egress. If required enforcement cannot be maintained, a backend or trusted node/control-plane actor must stop workload execution within a documented bound. Each backend is expected to document its behavior and bound. Transport recovery is scoped to the same logical supervisor process; a replacement supervisor cannot resume an existing generation with launch credentials. + +Source: [RFC 0012 failure and loss invariants, lines 95–110](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0012-isolation-backend/README.md#L95-L110) and [failure semantics, lines 345–390](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0012-isolation-backend/README.md#L345-L390). + +**Interpretation:** controller/supervisor-loss semantics were not simply removed from the architecture-level requirements. The open issue is whether every admitted backend and deployment path implements and tests the normative requirement, with a concrete stopping bound. + +### 2. Credential revocation has implementation evidence, but it is narrower than whole-boundary revocation + +`SOURCE` — The supervisor runtime has an explicit failure path that revokes static provider credentials when the requested provider environment cannot be obtained or its bindings fail validation. The source comments explicitly say previous dynamic grants may remain active; therefore this must not be described as revocation of every credential class. + +Sources: +- [provider environment failure revocation, lines 791–812](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/config_runtime.rs#L791-L812) +- [binding validation/revocation, lines 818–840](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/config_runtime.rs#L818-L840) +- [provider expiry and stale-placeholder behavior, lines 786–800](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/docs/how-it-works/providers/profiles.mdx#L786-L800) + +This supports a narrower statement about static provider credential handling. It does **not** by itself establish that a sandbox's complete policy is revoked, that all active network connections are closed, or that an untrusted workload stops when required enforcement is lost. + +### 3. Boundary transport and mediation have lifecycle handling + +`SOURCE` — The sandbox boundary runtime tracks control connections and connection expiry. Its persistent mediation path terminates the mediation task when the reader, writer, or broker-accept task completes; this is source evidence that the mediation stream has a lifecycle, not proof that every backend prevents all network effects after transport loss. + +Sources: +- [boundary control connection lifecycle, lines 587–637](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox/src/boundary_server.rs#L587-L637) +- [persistent mediation task lifecycle, lines 1010–1105](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox/src/boundary_server.rs#L1010-L1105) + +The host-VM supervisor also supports parent-liveness stdin: the driver closing the liveness pipe or exiting causes the supervisor process to terminate. This is a process-lifecycle mechanism, but the full chain from supervisor termination to workload termination and outer-fence preservation must be traced and tested separately. + +Source: [supervisor README: parent-liveness stdin](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/README.md). + +## Evidence gap by claim + +| Claim | Evidence class | Source evidence currently found | Still needed | +|---|---|---| +| Static provider credential revocation on failed refresh/binding | SOURCE + DOC-CLAIM | Supervisor code revokes static provider environment; docs describe stale/expired placeholders failing closed | Exact-SHA test of old static placeholder after update/revocation; verify all request paths reject and no secret reaches a canary | +| General policy revocation for a running sandbox | SOURCE + TEST-CONTRACT | Policy generation and stale-state handling exist in the supervisor/network code; this review has not closed every affected operation and backend path | Trace policy update through generation change to active connection closure and protected-effect denial, per backend | +| Controller/supervisor transport loss | DOC-CLAIM + SOURCE | RFC 0012 normatively requires continued enforcement, fail-closed supervisor operations and bounded stop if enforcement cannot be maintained; boundary transport/mediation lifecycle code exists | Per-backend loss path, exact bound, recovery semantics, and effect-side test while workload is actively attempting egress | +| Trusted cleanup when backend cleanup is unavailable | DOC-CLAIM | RFC 0012 requires a trusted driver cleanup path | Evidence for each supported driver and a test that workload cannot continue after loss | +| Replacement supervisor / stale generation | DOC-CLAIM + SOURCE + TEST-CONTRACT | RFC 0012 says replacement process cannot resume the existing generation with launch credentials; runtime binds generation/session/evidence | Exact-SHA regression test covering replacement supervisor and old credentials against active and restarted resources | + + +## Backend stopping-bound documentation check + +**Evidence class: DOC-CLAIM + SOURCE (documentation/source inspection only).** RFC 0012 says each backend documents its behavior on supervisor/runtime loss and its bound for stopping execution when enforcement cannot be maintained ([RFC 0012, lines 102–105](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0012-isolation-backend/README.md#L102-L105)). I checked the pinned [runtime guide](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/docs/how-it-works/sandboxes/runtimes.mdx) and the RFC's backend contract. The runtime guide names Docker, Podman, MicroVM and Kubernetes, and lists a Podman `stop_timeout_secs` configuration option, but the inspected documentation does not provide a per-backend supervisor-loss scenario paired with a measured/guaranteed workload-stop bound. The Podman option alone is not evidence of a controller-loss bound. This is a **documentation evidence gap**, not proof that runtime enforcement is absent or unsafe. + +| Backend | Specific loss behavior + stop bound found in reviewed runtime docs? | Evidence class | Follow-up | +|---|---|---|---| +| Docker | Not located in the reviewed runtime guide | DOC-CLAIM review | Find driver-specific loss semantics and state the bound, or record why a stop bound is not required because enforcement remains active | +| Podman | `stop_timeout_secs` exists, but its connection to supervisor/boundary loss was not established | DOC-CLAIM review | Trace config use and document the exact loss trigger and stop bound | +| QEMU/libkrun MicroVM | Runtime guide documents no guest NIC and host supervisor path; no per-loss stop bound located | DOC-CLAIM review | Trace parent-liveness and workload termination end-to-end; document bound or persistent containment semantics | +| Kubernetes | No per-loss stop bound located in the reviewed runtime guide | DOC-CLAIM review | Trace pod/boundary/controller cleanup path and document bound or persistent containment semantics | + +The checked source ref is `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. This was a targeted documentation review, not an exhaustive repository-wide proof that no such bound exists. + +## Required next tests + +1. **Credential revocation:** create an endpoint-bound static credential, prove it works, revoke/change its binding, wait for the declared activation boundary, then attempt the old placeholder against an instrumented canary. Record policy generation, request decision and whether any protected bytes arrive. +2. **Controller/transport loss:** run a workload that repeatedly attempts harmless egress to a recording canary; sever the supervisor-to-boundary transport and separately terminate the logical supervisor. Record whether egress is denied immediately, whether the workload is paused/terminated/contained, and the measured bound until termination where applicable. +3. **Backend matrix:** repeat for Docker, Podman, QEMU/libkrun and Kubernetes where supported. Do not generalize one backend's behavior to another. +4. **Recovery/replacement:** reconnect the same logical supervisor, then separately try a replacement supervisor and old generation credentials. Confirm no prior generation resumes without fresh admission/binding. +5. Capture exact SHA, commands, test names, exit codes, logs and canary-side observations. Until then, status remains **NOT TESTED**. + +## EABC interpretation + +Candidate mapping only, pending comparison with the canonical EABC specification: +- `INTEGRITY_STATE(B,E)`: revocation and loss/recovery transitions. +- `INTEGRITY_CTX(C,B,E)`: binding the active generation/session to the enforcement instance. +- `NON_BYPASSABILITY(B,E)`: proving that network mediation or a trusted stop path remains effective during loss. + +No runtime PASS/FAIL is assigned in this source review. The overall audit verdict remains **INCONCLUSIVE**. + +## CI evidence checked after this review + +GitHub Actions run [38991707083](https://github.com/NVIDIA/OpenShell/actions/runs/38991707083) has successful Rust test jobs for x86_64 Linux and aarch64 Linux on the pinned follow-up commit. The inspected job logs show the command: + +```sh +cargo nextest run --locked --profile ci --workspace --features openshell-server/test-support +cargo nextest run --locked --config-file .config/nextest.toml --profile ci --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml +``` + +`TEST-CONTRACT` — source at `b58e24c` defines `test_forward_relay_guard_blocks_stale_generation_before_upstream_write` in `crates/openshell-supervisor-network/src/proxy.rs` and `credential_guard_does_not_shadow_inspected_endpoint_config` in `crates/openshell-supervisor-network/src/opa.rs`. The run's job conclusion is successful, but the downloaded successful-job logs did not expose individual passing test names under the configured nextest output. Thus this is evidence of broad upstream test execution and green job status, **not** independent confirmation that these two named tests ran and passed, and not a runtime controller-loss/revocation test. The audit's own runtime statuses remain `NOT TESTED`. + +## Targeted test execution and artifact check + +The GitHub Actions run exposes one artifact, `compatibility-review-run-38991707083-attempt-1`. I downloaded and inspected its contents. It contains `report.json`, `report.md`, and `comment.md` for an **advisory API/SDK compatibility review**, not JUnit results or Rust test output. It therefore cannot establish that either named Rust regression test executed or passed. No JUnit artifact was present in the run's artifact listing. + +The exact-SHA test workflow is now defined in [`.github/workflows/openshell-targeted-tests.yml`](../../../.github/workflows/openshell-targeted-tests.yml). It checks out `NVIDIA/OpenShell` at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`, verifies the checked-out SHA, and individually runs these three distinct source tests in package `openshell-supervisor-network`: + +```sh +cargo nextest run --locked --profile ci -p openshell-supervisor-network -E 'test(stale_generation_fails_before_relay_context_is_created)' --junit +cargo nextest run --locked --profile ci -p openshell-supervisor-network -E 'test(test_forward_relay_guard_blocks_stale_generation_before_upstream_write)' --junit +cargo nextest run --locked --profile ci -p openshell-supervisor-network -E 'test(credential_guard_does_not_shadow_inspected_endpoint_config)' --junit +``` + +The workflow records the command, source SHA, cargo-nextest exit code, JUnit test-case/failure counts, per-test logs and metadata, and uploads them as an artifact. **The workflow definition itself is not a test result.** The targeted tests remain `NOT TESTED` until a run finishes and its artifact is inspected. The earlier local attempt could not run because this environment lacks `cargo`; these unit/regression tests would still not substitute for separate runtime revocation/controller-loss tests. diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-rfc0005-conformance-review.md b/audits/nvidia-openshell-sentry/evidence/openshell-rfc0005-conformance-review.md new file mode 100644 index 0000000..96f3bcb --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-rfc0005-conformance-review.md @@ -0,0 +1,56 @@ +# OS-06 — RFC 0005 implementation conformance review + +Compared NVIDIA/OpenShell RFC 0005 (`b58e24c9dabd6d4bcf2b7186592d3ad50646541b`) with the pinned CONNECT implementation. +Status: **SOURCE REVIEW — NOT A CONFIRMED SECURITY VULNERABILITY; NO RUNTIME TEST EXECUTED**. + +## Finding + +RFC 0005 explicitly distinguishes the transitional EgressDecision envelope from the target generation-consistent authorization cutover. The README says the first milestone preserves separate queries and that generation-consistent materialization is a later cutover. The implementation plan's Phase 3 requires one OPA result for matched policy/source, matched endpoint, destination constraints, TLS, HTTP enforcement, credential plan, and middleware selection, plus reload-race tests before upstream request write. + +At the pinned source commit, CONNECT invokes helper functions for TLS mode, credential guard, L7 route and destination plan after the initial decision. Source inspection of those helper definitions refines what that means: TLS mode and L7 route are projected from `decision.endpoint.policy_configs`, and destination planning reads `allowed_ips` from that same decision snapshot. These are not independent OPA queries. The credential guard is the material separate OPA evaluation. `OpaEngine::authorize_egress()` returns the primary authorization fields under the engine mutex; the remaining Phase 3 question is whether credential-guard data and any other required fields must be part of the same result, and whether their behavior remains aligned across reload boundaries. The overlap regression `credential_guard_does_not_shadow_inspected_endpoint_config` provides counter-evidence to a simple endpoint-shadowing hypothesis. + +Sources: +- [RFC 0005 README: transitional decision and later cutover](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/README.md) +- [RFC 0005 Phase 3 acceptance requirements](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/implementation-plan.md) +- [CONNECT metadata hydration sequence](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2700-L2860) +- [Combined authorization snapshot](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L600-L675) +- [Overlapping L4/L7 credential guard regression](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L9612-L9705) + +## Assessment + +- This is a **conformance / milestone-status question**, not evidence by itself that a request bypasses enforcement. Existing mutex and generation guards materially mitigate the simple reload-race hypothesis. +- The combined query's existence alone does not prove Phase 3 is complete; the call path must show that all required connection-level fields come from that one result and that legacy query paths are no longer authoritative. +- Conversely, separate helpers do not establish a race if each query is serialized and stale generations are rejected before protected traffic can flow. +- The overlapping endpoint test confirms an intentional distinction: credential gating must aggregate across both L4 and inspected definitions, while endpoint TLS/SSRF metadata must not be shadowed by the L4 credential endpoint. A future single-result schema must preserve that distinction rather than blindly collapsing all endpoints to one record. + +## Recommended next verification + +1. Trace every caller of `authorize_egress()` and establish whether CONNECT and forward HTTP use it in the pinned revision. +2. Compare `EgressAuthorization` fields with the Phase 3 required materialization list; explicitly account for destination constraints, TLS, protocol, credential plan, and middleware selection. +3. Run existing overlap and stale-generation regression tests in a checkout at the exact SHA; record commands and exit codes. +4. If the repository is runnable, add a narrowly scoped test asserting the connection-level metadata's source generation and canary-observed no-write behavior on stale decisions. Do not add timing sleeps or claim a vulnerability from source shape alone. + +**Disposition:** keep OS-06 open as a bounded RFC-conformance / runtime-validation item. Do not label it exploitable. GEN-01 through GEN-04 remain **NOT TESTED**. + +## Follow-up: call-site and current-shape check + +A second targeted search for `authorize_egress` surfaced the API definition and test-oriented call sites, but did not surface a production CONNECT call site. The inspected CONNECT handler still performs this sequence on its `decision` object: + +1. `hydrate_tls_mode(&mut decision)` +2. `query_endpoint_credential_guard(...)` +3. `hydrate_l7_route(&mut decision)` +4. `hydrate_destination_plan(&mut decision, ...)` + +The RFC's own `current-shape.md` describes endpoint metadata lookup and policy evaluation as interleaved, and its implementation plan explicitly labels Phase 1's `EgressDecision` as transitional compatibility hydration—not an atomic OPA result. The inspected CONNECT code projects TLS/L7/destination fields from that decision snapshot but separately evaluates the credential guard. Phase 3 calls for one result to materialize matched policy/source, endpoint, destination constraints, TLS, HTTP enforcement, credential plan and middleware selection, plus shadow-mode mismatch telemetry before cutover. + +This strengthens the **conformance-status** concern: the combined API's presence must not be mistaken for evidence that the CONNECT path has completed the Phase 3 cutover. Search results are not a formal whole-repository call-graph proof, so the safe wording is that no production CONNECT call site was found in this targeted inspection, not that none can exist anywhere. + +Sources: +- [Current-shape appendix](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/current-shape.md) +- [Phase 1 transitional decision contract and Phase 3 cutover](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/implementation-plan.md) +- [Observed CONNECT hydration sequence](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2700-L2860) +- [Combined authorization API](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L600-L675) + +### Revised disposition + +Keep OS-06 as **RFC Phase 3 cutover not fully demonstrated in the inspected CONNECT call path**, pending complete call-graph verification and exact-SHA tests. The broad claim that TLS/L7/destination necessarily mix generations is not supported by this source trace. The narrower unresolved point is separate credential-guard materialization and its relationship to the initial decision across policy changes. This is an implementation-conformance/runtime-validation item, not a demonstrated policy bypass. Existing generation guards, engine locking and overlap regression coverage are meaningful counter-evidence. No audit-specific runtime test was executed; GEN-01 through GEN-04 remain **NOT TESTED**. See [the refined Phase 3 call-path audit](openshell-rfc0005-phase3-callpath-audit.md). diff --git a/audits/nvidia-openshell-sentry/evidence/openshell-rfc0005-phase3-callpath-audit.md b/audits/nvidia-openshell-sentry/evidence/openshell-rfc0005-phase3-callpath-audit.md new file mode 100644 index 0000000..0d5f2bb --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/openshell-rfc0005-phase3-callpath-audit.md @@ -0,0 +1,108 @@ +# Focused audit: RFC 0005 Phase 3 vs. CONNECT call path + +Date: 2026-10-17 +OpenShell source inspected: `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` +Audit repository branch: `audit/openshell-sentry-2026-10` +Scope: source-level conformance check for the generation-consistent authorization cutover. This is not a runtime test report. + +## Result + +**Disposition: PHASE 3 CUTOVER NOT DEMONSTRATED IN THE INSPECTED CONNECT PATH. NOT A CONFIRMED SECURITY VULNERABILITY.** + +The pinned source shows several helper calls after initial authorization, but they are not all independent policy queries. Source inspection of the helper definitions refines the interpretation: + +1. `hydrate_tls_mode(&mut decision)` projects TLS mode from the first policy config already present in `decision.endpoint.policy_configs`. +2. `hydrate_l7_route(&mut decision)` builds the L7 route from that same endpoint-config snapshot and tags it with `decision.policy_generation`. +3. `hydrate_destination_plan(&mut decision, ...)` reads `allowed_ips` from that same snapshot and combines it with the exact-declared-host signal and gateway settings. +4. `query_endpoint_credential_guard(...)` is the material independent OPA query among these steps; it calls `engine.query_endpoint_credential_guards(&input)` separately. + +The same handler pins `decision.policy_generation` before these calls. It rejects a stale generation, validates the materialized L7 route against the captured generation, races upstream dialing against `wait_until_stale()`, and checks the generation again before returning `200 Connection Established`. These are meaningful safeguards against a straightforward reload race. + +Separately, `OpaEngine::authorize_egress()` evaluates `data.openshell.sandbox.egress_authorization` under the engine mutex and returns an `EgressAuthorization` containing the action, endpoint configurations, matched endpoints, exact-declared-host signal and generation. Targeted repository search found call sites in test/supervisor-related code, but did not identify the combined API as the sole source for every Phase 3 field because credential-guard metadata is queried separately. TLS, L7 route and `allowed_ips`/destination planning in the inspected CONNECT path are projections of the initial `EgressDecision` snapshot, not separate OPA evaluations. This is a targeted call-site search, not a formal proof that no other production caller exists. + +Therefore, the defensible source finding is limited: **the Phase 3 single-result materialization is not demonstrated by the inspected CONNECT path**. This does not determine whether Phase 3 was planned, in progress, or declared complete for this exact commit. The README describes the single-result cutover as a later step after shadow comparison; the inspected RFC documents do not provide an unambiguous commit-specific phase-status declaration. Until that status is resolved, the separate guard query is a conformance question, not proof of a missed committed requirement. The code inspected also contains generation checks and fail-closed gates, so the source shape alone does not prove mixed-generation use, an authorization bypass, or protected bytes reaching an upstream. + +## Requirements from RFC 0005 Phase 3 + +The implementation plan calls for one OPA result from one policy generation to materialize: + +- matched policy/source and matched endpoint; +- destination constraints; +- TLS treatment; +- HTTP enforcement; +- credential plan; +- middleware selection. + +It also calls for a generation-pinned request-policy engine, shadow-mode mismatch telemetry, reload-race tests proving each field matches the top-level generation, and stale decisions stopping before upstream request write. + +The inspected CONNECT path uses helper steps for TLS, L7 route and destination, but those helpers project fields from the original authorization snapshot. The credential guard is a separate OPA evaluation. The specific Phase 3 gap is therefore not evidence that TLS/L7/destination necessarily mix generations; it is whether the separate credential-guard query and any remaining Phase 3 fields meet the RFC's single-result materialization requirement, and whether runtime behavior remains safe around reloads. Do not infer a runtime vulnerability from this difference. + +## Source evidence + +- [RFC 0005 implementation plan — Phase 1 and Phase 3](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/implementation-plan.md) +- [RFC 0005 current-shape appendix](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/current-shape.md) +- [CONNECT metadata hydration and generation guard](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2700-L2860) +- [CONNECT stale-generation, credential gate and pre-200 checks](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2860-L3030) +- [Combined authorization implementation](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L600-L675) + +## Required next verification + +### A. Close the RFC phase-status and source-baseline questions + +- Keep the original audit/matrix baseline `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` separate from this follow-up source review at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. +- Determine from a commit-specific RFC/change record whether Phase 3 is planned, in progress, or completed for `b58e24c`. The README describes it as a later cutover after shadow comparison, but the sources inspected here do not declare a definitive status for this commit. Until then, do not classify the transitional shape as a failure to meet a committed milestone. + +### B. Complete the source call graph + +- Enumerate all production and test call sites of `authorize_egress()`. +- Trace the implementation and result type of each CONNECT hydration helper. +- For each Phase 3 field, record its source, the generation attached to it, and the point at which that generation is checked. +- The current `query_endpoint_credential_guards()` signature returns `Result>`, not a `(result, generation)` pair. In the inspected CONNECT path, alignment is therefore enforced indirectly by the captured `connect_generation_guard` and later `ensure_current()` checks, not by a generation value returned with the guard result. Verify this assumption at both reload windows: reload before/during the guard query and reload after the query but before the final pre-200 check. +- Check whether forward HTTP and other egress paths have equivalent behavior; do not extrapolate CONNECT results to every adapter. + +### C. Run tests at the exact source commit + +No OpenShell runtime or Cargo tests were executed during this audit step. The audit environment used source inspection through GitHub; it did not run a checkout of OpenShell at the pinned SHA. Accordingly, all runtime and execution claims remain **NOT TESTED**. + +In a checkout at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`, first run the focused existing tests for: +- stale generation rejected before relay context/upstream traffic; +- `credential_guard_does_not_shadow_inspected_endpoint_config`; +- reload/generation guard behavior around CONNECT. + +Record the exact commands, toolchain/platform, exit status and relevant output. Do not mark a test PASS merely because a test exists in source. + +### D. Add one narrow effect-side race test + +Use a harmless canary upstream and synthetic credentials only. Coordinate a policy reload at deterministic barriers before/after the separate credential-guard query and in the upstream-dial window. Capture the authorization generation, guard result/configuration, and whether the canary received a request or protected marker. TLS/L7/destination fields should be checked as projections of the original authorization snapshot, not assumed to be independent OPA reads. + +Expected safe behavior: +- no upstream request is written when the decision or any required field is stale/inconsistent; +- no synthetic protected marker reaches the canary under a denied or stale decision; +- every accepted request has a single traceable policy generation and matching endpoint/TLS/credential/destination context. + +Avoid timing sleeps as the primary synchronization mechanism. Do not log real credentials. + +## Evidence classification + +| Claim | Evidence class | Status | +|---|---|---| +| CONNECT calls TLS/L7/destination helper functions; those project from the initial decision snapshot, while credential guard is a separate OPA query | SOURCE | Observed at pinned source | +| Combined `authorize_egress()` evaluates a combined OPA result under the engine mutex | SOURCE | Observed at pinned source | +| The combined API materializes the credential guard and every Phase 3 field in one OPA result | SOURCE | Not demonstrated; credential guard is separately queried | +| A reload can cause mixed-generation authorization to reach upstream | HYPOTHESIS | Not proven | +| A protected request/credential can bypass the intended boundary | RUNTIME | NOT TESTED | +| RFC 0005 Phase 3 is fully complete for all egress adapters | CONFORMANCE | Not demonstrated by this CONNECT inspection alone | + +## Decision + +Keep OS-06 open as a bounded RFC 0005 conformance and runtime-validation item. Do not label it an exploitable vulnerability unless the field/generation trace and an effect-side test demonstrate an unsafe outcome. The overall OpenShell/Sentry EABC verdict remains **INCONCLUSIVE** until the source baseline is explicitly selected and the relevant execution tests are performed. + + +## EABC mapping for OS-06 (provisional) + +- **INTEGRITY_STATE(B,E):** policy reload and stale-decision transitions must invalidate an in-flight CONNECT before its protected effect is authorized. +- **INTEGRITY_CTX(C,B,E):** credential-guard result must remain aligned with the policy generation and endpoint context used for the primary decision. The guard API currently does not return a generation alongside its values; the handler's captured-generation checks are the claimed binding mechanism and need exact-SHA test evidence. +- **NON_BYPASSABILITY(B,E):** the decisive observation is whether a denied/stale CONNECT can cause any protected request or synthetic credential to reach the upstream canary. The source-level shape alone cannot establish bypassability. +- **INTEGRITY_DEF(B):** the declared boundary is the inspected CONNECT authorization-to-upstream path, not every OpenShell adapter or every Sentry-composed deployment. + +This mapping follows the criterion labels used by the audit repository and is provisional until checked against the canonical EABC specification/version used for the wider project. diff --git a/audits/nvidia-openshell-sentry/evidence/sentry-public-claims-and-evidence-gap.md b/audits/nvidia-openshell-sentry/evidence/sentry-public-claims-and-evidence-gap.md new file mode 100644 index 0000000..77d18ec --- /dev/null +++ b/audits/nvidia-openshell-sentry/evidence/sentry-public-claims-and-evidence-gap.md @@ -0,0 +1,67 @@ +# Sentry and OpenShell composition — public claims vs. EABC evidence + +Date: 2026-10-17 +Scope: NVIDIA public descriptions of Sentry and the Open Agent Safety Platform, compared with the evidence needed for an EABC assessment. This is not an implementation audit or hardware validation. Public web pages were consulted on 2026-10-17; where a page is a rolling URL, the access date records the snapshot time, not a guarantee of immutable content. + +## Assessment + +**Sentry standalone enforcement: NOT TESTED (implementation/runtime evidence absent).** +**OpenShell + Sentry composition: NOT TESTED (integration evidence absent).** + +Official NVIDIA materials now describe Sentry as an optional, independent hardware security layer alongside OpenShell, running on BlueField-4 and using DOCA for out-of-band observation, identity governance and policy enforcement. NVIDIA describes the combined Open Agent Safety Platform as an open reference system design, not as a claim that every OpenShell deployment includes Sentry. + +Sources: +- [NVIDIA Open Agent Safety Platform press release, 2026-09-28](https://nvidianews.nvidia.com/news/open-agent-safety-platform) +- [NVIDIA technical blog: reference for continuous in-silicon agent monitoring, 2026-09-28](https://developer.nvidia.com/blog/nvidia-open-agent-safety-platform-a-reference-for-continuous-in-silicon-agent-monitoring) +- [NVIDIA Open Agent Safety Platform overview and FAQ](https://www.nvidia.com/en-us/solutions/ai/agent-safety/) +- [OpenShell architecture documentation](https://docs.nvidia.com/openshell/dev/about/architecture) — rolling `dev` documentation, accessed 2026-10-17. + +These materials are **vendor documentation/claims**. They are useful to define the intended trust model, but do not establish that the implementation has the described properties under a concrete deployment, nor that Sentry is EABC-conformant. + +## What the public materials claim + +- OpenShell enforces the software/runtime boundary: sandbox isolation, policy-controlled network access, filesystem/process controls, credential handling and a supervisor outside the agent process. +- Sentry is described as an independent, out-of-band watchdog on BlueField-4, using DOCA to observe agent activity and enforce policy in hardware. +- The combined design is described as able to quarantine/stop an agent in milliseconds when it attempts to leave its boundary. +- NVIDIA says Sentry is an optional security layer alongside OpenShell. OpenShell itself can run without BlueField-4/Sentry. + +These statements are not independently verified by this audit. In particular, marketing-level phrases such as “every request and response,” “attested telemetry,” “independent,” or “quarantine in milliseconds” need a precise technical scope and observable acceptance criteria. + +## Evidence required to assess Sentry by itself + +1. **Protected effect and boundary:** identify the exact paths Sentry mediates (model access, APIs/tools, data access, network egress, or a stated subset), and list paths it does not cover. +2. **Identity and context binding:** show how agent identity, tenant/sandbox identity, delegated authority, policy version and workload generation are authenticated and bound to each observed/enforced request. +3. **Independent enforcement:** demonstrate that a compromised host/workload cannot disable, spoof or bypass Sentry's enforcement path or its telemetry. +4. **Fail-safe behavior:** specify and test behavior on DOCA/Sentry service failure, DPU reset, policy delivery loss, stale identity, missing telemetry, link/path failover and restart. +5. **Effect-side proof:** run denied and allowed synthetic requests through the actual supported hardware path; capture Sentry decision/telemetry and independent destination-side records. A log entry alone is not proof that the protected effect was blocked. +6. **Scope of the claim:** pin firmware, DOCA/Sentry software, BlueField model, host topology, policy and versions; state whether the result is specific to BlueField-4/Vera reference topology. + +## Evidence required for OpenShell + Sentry composition + +The composition must be assessed as a single boundary, not by adding together component claims. + +- Define the policy source of truth and how OpenShell policy is translated, versioned, authenticated and delivered to Sentry. +- Define which layer is authoritative for each protected effect and how conflicts/updates are handled. +- Bind OpenShell sandbox/session/runtime generation and process or agent identity to Sentry's identity and telemetry context. +- Prove that every claimed path to the protected effect crosses at least one enforcing layer, including alternate NICs, host routes, alternate model endpoints, tool/API paths, recovery paths and administrative channels. +- Test policy update/revocation races, host compromise assumptions, Sentry outage/restart, stale policy and quarantine completion. +- Observe the protected effect at an independent destination and show that a forbidden request does not arrive, or that an already active path is cut within a measured bound. +- State residual trust in firmware, DPU, host BIOS/IOMMU, management plane and operator configuration. + +## EABC mapping + +| EABC question | Evidence needed | +|---|---| +| `INTEGRITY_DEF(B)` | Complete and versioned definition of the Sentry boundary, protected effects and excluded paths. | +| `INTEGRITY_STATE(B,E)` | Demonstrated state transitions for policy update, revocation, DPU/service failure and quarantine. | +| `INTEGRITY_CTX(C,B,E)` | Authenticated binding of agent/sandbox identity, generation, policy version and observed effect. | +| `NON_BYPASSABILITY(B,E)` | Effect-side proof that all relevant paths are mediated or denied, including alternate/failure paths. | +| `EXCLUSIVITY` | Evidence that only the intended authority can approve or perform the protected effect and that Sentry/host cannot silently expand authority. | + +## Current disposition + +- Public documentation supports the intended architectural role of Sentry as an optional independent hardware layer. +- No Sentry implementation source, pinned firmware/software build, deployment configuration, hardware lab output, failure-injection result or independent effect-side trace was collected for this audit. +- Therefore, neither Sentry's standalone enforcement nor the OpenShell+Sentry composition can currently receive PASS/FAIL under EABC from this evidence. +- Keep `SG-01` and `COM-01` **NOT TESTED** at implementation/runtime level. `NOT TESTED` is the test-status vocabulary; `VENDOR DOC-CLAIM only` is an evidence classification, not a second result state. Overall EABC verdict remains **INCONCLUSIVE**. + diff --git a/audits/nvidia-openshell-sentry/findings.md b/audits/nvidia-openshell-sentry/findings.md new file mode 100644 index 0000000..e4e4b32 --- /dev/null +++ b/audits/nvidia-openshell-sentry/findings.md @@ -0,0 +1,192 @@ +# Findings register — OpenShell / Sentry + +Date opened: 2026-10-17 +OpenShell source baseline: `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` +Runtime validation: **NOT TESTED**. No runtime reproduction attempts were performed in this audit. This register's original findings assess only `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`; follow-up source review at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` is separate evidence and does not replace the baseline. + +## Summary + +| ID | Commit(s) reviewed | Area | Evidence class | EABC criterion | Current assessment | Test status | +|---|---|---|---|---|---|---| +| BASELINE-01 | `a4c848a` → `b58e24c` comparison | Upstream source baseline drift | SOURCE | NON_BYPASSABILITY(B,E); INTEGRITY_DEF(B); INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E) | Material isolation-interface and conformance-harness changes; selected areas partially reviewed below, not a complete newer-baseline audit. No claim that changes are vulnerabilities or regressions. | NOT TESTED — selected source areas only | +| BASELINE-02 | `a4c848a` vs `b58e24c` | Explicit outer-fence guarantee contract replaced by provisioning evidence | SOURCE | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E) | Common contract no longer requires four normalized guarantees. Docker/Podman source evidence supports default-deny/no-unmanaged-egress checks. RFC 0012 retains normative controller-loss requirements, and supervisor code shows static-provider-credential revocation paths; per-backend implementation proof and effect-side tests for whole-policy revocation/controller-loss remain incomplete. | NOT TESTED — runtime effect unknown | +| VM-FENCE-01 | `b58e24c` | VM outer-fence evidence and launch binding | SOURCE | INTEGRITY_DEF(B); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | Evidence constructor sets a fixed zero-NIC count, while QEMU `-nic none` and explicit libkrun device setup support a no-IP-NIC-by-construction design. Effective runtime device binding remains unverified. | NOT TESTED — runtime binding unknown | +| OS-01 | `a4c848a` | Network paths / direct-egress bypass | DOC-CLAIM + SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | Driver-specific controls and named tests identified; runtime behavior unknown. | NOT TESTED — runtime bypass status unknown | +| OS-02 | `a4c848a` | Credential binding / rotation / revocation | TEST-CONTRACT | INTEGRITY_CTX(C,B,E); EXCLUSIVITY; NON_BYPASSABILITY(B,E) | E2E source test contract covers endpoint binding and credential rotation/revocation. | NOT TESTED — source test contract only | +| OS-06 | `a4c848a` RFC baseline; `b58e24c` follow-up source review | Authorization generation and credential guard | SOURCE + TEST-CONTRACT + DOC-CLAIM | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | TLS/L7/destination are projections of the inspected authorization snapshot; separate credential-guard result has no paired generation. RFC Phase 3 status for the follow-up commit and runtime effect remain unresolved. | NOT TESTED | +| OS-07 | `a4c848a` | Evaluation errors vs missing L7 metadata | TEST-CONTRACT + SOURCE | INTEGRITY_CTX(C,B,E); EXCLUSIVITY; NON_BYPASSABILITY(B,E) | Regression contract distinguishes evaluation errors from missing-metadata fallback; credentialed L4-only fallback concern cross-references OS-09. | NOT TESTED — source regression contract only | +| OS-08 | `a4c848a` | VM host bind mounts / virtiofs | DOC-CLAIM + SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_DEF(B); INTEGRITY_CTX(C,B,E) | Several controls identified; complete host-path isolation unverified. | NOT TESTED — host-path escape status unknown | +| OS-09 | `a4c848a` tests; `b58e24c` counter-evidence | Missing L7 metadata and credential-injection boundary | SOURCE + TEST-CONTRACT + DOC-CLAIM | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | Credential guard and overlap regression are counter-evidence to treating L4 fallback alone as a vulnerability; runtime credential behavior remains untested. See OS-07. | NOT TESTED | +| BACKEND-TRUST-01 | `b58e24c` | Delegated backend assurance boundary | SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_DEF(B); INTEGRITY_CTX(C,B,E) | Admission/context binding exists; it does not alone prove the admitted backend's enforcement claims. This is a trust-boundary question, not automatically a defect. | NOT TESTED | +| SG-01 | Public claims accessed 2026-10-17; implementation SHA not pinned | Sentry standalone enforcement | VENDOR DOC-CLAIM only | To be determined from concrete protected effect and boundary | Public materials describe optional BlueField-4/DOCA enforcement; implementation and effect-side behavior not verified. See Sentry evidence-gap assessment. | NOT TESTED | +| COM-01 | Public claims accessed 2026-10-17; OpenShell/Sentry pair not pinned | OpenShell + Sentry composition | VENDOR DOC-CLAIM only | To be determined for the composed enforcement boundary | Policy handoff, identity/generation binding, failure behavior and end-to-end enforcement are not independently verified. See Sentry evidence-gap assessment. | NOT TESTED | + +## OS-09 — Missing L7 metadata and credential-injection boundary + +**Evidence classes:** `SOURCE`, `TEST-CONTRACT`, and `DOC-CLAIM`. **Status: NOT TESTED — runtime credential-injection behavior has not been exercised.** + +At the pinned original baseline `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`, compatibility tests preserve an L4-only fallback when authorized L7 metadata is missing, while a separate test denies an authoritative policy-evaluation error ([compatibility tests, lines 282–325](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy/tests/compatibility.rs#L282-L325)). That is a test contract, not proof that every credentialed route is safe. + +**Counter-evidence from the follow-up source review:** at OpenShell commit `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`, the proxy queries credential guards and rejects CONNECT for provider-credentialed endpoints when uninspected credentials are not explicitly allowed ([guard decision and 403, lines 2899–2944](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2899-L2944); [guard aggregation, lines 4008–4054](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L4008-L4054)). The guard's Rego query includes L4-only endpoints and has a regression test ensuring an L4-only credentialed endpoint cannot shadow the inspected endpoint's TLS/SSRF config ([OPA test, lines 9612–9690](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L9612-L9690)). NVIDIA's current policy documentation, accessed 2026-10-17 (rolling `latest` URL), also says credentialed L4-only and `tls: skip` endpoints are rejected by default, with `allow_uninspected_credentials: true` as an explicit opt-in ([policy documentation](https://docs.nvidia.com/openshell/latest/sandboxes/policies)). + +This is meaningful source-level counter-evidence against treating L4 fallback alone as a vulnerability. The remaining assurance question is whether missing/malformed metadata, overlapping endpoint definitions, policy reloads and the explicit opt-in behave correctly end-to-end. An explicit opt-in is a policy choice, not automatically a bypass; its scope and operator intent must be visible in the effective policy. + +**EABC relevance:** `NON_BYPASSABILITY(B,E)` asks whether the protected request can reach the upstream without satisfying the declared boundary; `INTEGRITY_CTX(C,B,E)` asks whether the endpoint and credential context used for injection matches the authorization decision. These are candidate criteria, not conformance findings. + +**Verification plan:** use a canary upstream that records request path, headers and injected-credential presence. Test missing L7 metadata, missing/malformed credential-guard metadata, authoritative evaluation error, overlapping L4 and inspected endpoints, and both default-deny and explicit `allow_uninspected_credentials: true` configurations. Include wildcard hosts, aliases and policy reloads where supported. Verify that default-deny cases never deliver protected requests or credentials to the canary, and that explicit opt-in only enables the exact configured endpoint. Runtime status remains `NOT TESTED`. + +## BACKEND-TRUST-01 — Delegated backend assurance boundary + +**Evidence class:** `SOURCE` + `TEST-CONTRACT`. **Status: NOT TESTED — trust in the admitted delegated implementation remains an operator/deployment assurance question.** + +The source does **more than simply accept an arbitrary payload**. The supervisor selects a backend from trusted composition, requires a matching admitted backend name before decoding, then binds the decoded sandbox ID, session and runtime generation to trusted launch inputs ([`SelectedBackend::select`, lines 51–140](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/backend_setup.rs#L51-L140)). The registration tests reject unknown or differently cased names, mismatched backend/TLS/fence/identity inputs, and mismatched admission before decode/discovery ([registration tests, lines 37–109](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/backend_setup/tests.rs#L37-L109); [admission rejection test, lines 387–416](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor/src/backend_setup/tests.rs#L387-L416)). The common runtime also checks that the confirmation matches generation, session, identity, resource claims and provisioning-evidence digest ([runtime confirmation, lines 357–375](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox-backend/src/runtime.rs#L357-L375)). + +At the same time, the delegated-backend contract intentionally allows `backend_audit = null` and then starts the agent ([delegated test, lines 81–107](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox-backend/src/runtime/tests/delegated.rs#L81-L107)). The shared startup contract states that backend selection is made by trusted composition, not payload contents. These controls establish admission and context binding; they do **not alone demonstrate the truth of the admitted backend's enforcement claims**. This is not automatically a vulnerability: it may be the intended trust boundary for an operator-selected external backend. + +**EABC relevance:** `NON_BYPASSABILITY(B,E)` and `INTEGRITY_DEF(B)` require evidence that the admitted backend's actual boundary is complete and enforced; `INTEGRITY_CTX(C,B,E)` requires the enforcement state to correspond to the admitted identity, generation and protected effect. A matching descriptor/evidence digest proves binding of the value, not the truth of the backend's enforcement assertion. + +**Verification plan:** document the admission and operator trust model for every enabled backend; verify how the registered endpoint is authenticated and protected against process/socket replacement; enumerate backend versions and configuration; test a deliberately non-enforcing but correctly admitted backend in an isolated harness and determine whether the gateway has any independent signal to detect that mismatch; and observe protected effects at the destination. Keep the null-`backend_audit` behavior as an explicit protocol contract, not a failure by itself. Runtime status remains `NOT TESTED`. + +## VM-FENCE-01 — VM outer-fence evidence and launch binding + +**Evidence class:** `SOURCE`. **Status: NOT TESTED — source supports no-NIC-by-construction; runtime binding not independently verified.** + +At the checked upstream commit, `VmOuterFenceEvidence::project` rejects an empty generation or non-zero network-device count. `VmBoundarySpec::provision` sets `network_device_count: 0` as a fixed value ([VM isolation contract, lines 22–42 and 71–94](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-vm/src/isolation/mod.rs#L22-L42)). Further source review found relevant counter-evidence: the QEMU launch arguments explicitly include `-nic none` ([QEMU launch and network arguments, lines 121–150 and 188–190](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-vm/src/runtime.rs#L121-L150)); the libkrun path states that it starts no network helper and uses the protected vsock mapping plus optional virtiofs shares, disables implicit vsock, and explicitly adds only vsock/virtiofs devices ([libkrun launch, lines 320–354](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-vm/src/runtime.rs#L320-L354)). A source unit test asserts QEMU's `-nic none` arguments ([lines 908–911](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-vm/src/runtime.rs#L908-L911)). + +This is meaningful source-level support for a no-IP-NIC-by-construction design, so the fixed zero count is not by itself evidence of a defect. The remaining assurance gap is that the count is not derived from a measured final device inventory, and neither these source assertions nor the evidence digest proves the effective runtime configuration under every supported platform, launcher version, or failure/recovery path. Vsock is a host/guest communication channel and should be assessed as part of the boundary; it is not an ordinary guest IP NIC. + +**EABC relevance:** `INTEGRITY_DEF(B)` asks whether the boundary definition is complete and stable; `INTEGRITY_CTX(C,B,E)` asks whether the declared generation/context corresponds to the actual enforcement instance; `NON_BYPASSABILITY(B,E)` requires evidence that all paths to the protected effect traverse the boundary. A generation-bound digest alone does not prove the effective VM device configuration, although the reviewed launch code provides relevant supporting evidence. + +**Verification plan:** on each supported QEMU/libkrun platform, capture the effective device configuration and host-side network state; verify no NIC or alternate direct-egress helper exists; inspect vsock endpoint exposure and policy; exercise restart/recovery and launcher failure; where feasible, inject an unexpected device and require launch/confirmation to fail closed. Record exact VM backend, host platform, launcher and libkrun/QEMU versions and evidence artifacts. Runtime status remains `NOT TESTED`. + +## BASELINE-02 — Outer-fence assurance contract changed + +**Evidence class:** `SOURCE`. **Status: NOT TESTED — assurance-contract change, runtime effect unknown.** This is a concrete source-level difference between the pinned audit baseline and the checked newer upstream commit. It is not, by itself, proof of a runtime vulnerability. + +At the pinned baseline, `OuterFenceGuarantees::validate` required the exact set `DefaultDenyEgress`, `NoUnmanagedEgressPath`, `RevocationVerified`, and `ControllerLossFailsClosed` for the admitted generation ([old contract, lines 389–469](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-isolation-interface/src/contract.rs#L389-L469)). At the checked newer upstream commit, this common guarantee set is replaced by `ProvisioningEvidence`, which binds native evidence to a generation and explicitly says the digest is not independent proof of policy enforcement ([new contract, lines 219–293](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-isolation-interface/src/contract.rs#L219-L293)). The Docker projection itself checks non-empty container ID, `network_mode == "none"`, and no unexpected networks before creating the evidence digest ([Docker isolation, lines 25–60](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-docker/src/isolation.rs#L25-L60)). Importantly, Docker also inspects the actual container configuration and attached networks and rejects drift ([Docker outer-fence inspection, lines 3082–3110](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-docker/src/lib.rs#L3082-L3110)). Podman likewise inspects the actual container and rejects a non-`none` network mode, privileged mode, or attached network ([Podman fence verification, lines 564–595](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-podman/src/client.rs#L564-L595)); its launch and restart paths call this check before starting the workload ([launch path, lines 1536–1546](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-podman/src/driver.rs#L1536-L1546), [restart path, lines 1636–1644](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-driver-podman/src/driver.rs#L1636-L1644)). The common runtime validates generation, session, resource claims and evidence-digest equality before proceeding, and validates native audit schema only for its built-in backend ([runtime confirmation, lines 357–389](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox-backend/src/runtime.rs#L357-L389)). A delegated-backend test intentionally accepts `backend_audit = null` and proceeds to `start_agent` ([delegated runtime test, lines 81–101](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-sandbox-backend/src/runtime/tests/delegated.rs#L81-L101)). + +**Interpretation:** the newer design may deliberately move enforcement-specific validation into trusted driver/backend code. Therefore, the removal of common normalized guarantees is not enough to claim a regression. But the old common interface's explicit four-property check is no longer present at this layer. Source evidence in this section covers `DefaultDenyEgress` and `NoUnmanagedEgressPath` through Docker/Podman checks. **For `RevocationVerified` and `ControllerLossFailsClosed`, the normative requirement still exists in RFC 0012, and source shows narrow static-provider-credential revocation paths; what remains missing is a complete per-backend trace and test evidence showing how the equivalent whole-boundary guarantees are established, validated, and maintained.** See [the focused revocation/controller-loss review](evidence/openshell-revocation-controller-loss-review.md). Treat these as evidence-collection tasks, not findings that the guarantees are absent or broken. A targeted `DOC-CLAIM` review of the pinned runtime guide also did not locate a per-backend supervisor-loss scenario paired with a documented stopping bound for Docker, Podman, QEMU/libkrun, or Kubernetes. Podman's `stop_timeout_secs` exists, but its relation to supervisor/boundary loss was not established. This is a documentation evidence gap only, not proof of unsafe runtime behavior; details and limitations are recorded in the focused review. +**Focused follow-up:** the newer [revocation and controller-loss source review](evidence/openshell-revocation-controller-loss-review.md) found that RFC 0012 retains a normative requirement for enforcement to remain active after logical supervisor/transport loss, with outbound denial and a documented bound to stop execution if enforcement cannot be maintained. Source code also has specific static-provider-credential revocation paths, but those do not prove whole-policy revocation or immediate closure of every active network flow. The remaining issue is implementation and test coverage per backend, not an established absence of the requirement. + + +**EABC relevance:** `NON_BYPASSABILITY(B,E)` requires evidence that all paths to the protected effect traverse enforcement; `INTEGRITY_STATE(B,E)` requires evidence for revocation and controller-loss transitions where applicable; `INTEGRITY_CTX(C,B,E)` requires binding of the admitted generation/session/identity/policy to the actual enforcement state. An evidence digest binds bytes to a generation; it does not itself prove the truth or completeness of the claims represented by those bytes. + +**Falsification / verification plan:** for Docker, Podman and VM independently, inspect the trusted native validation path and test default-deny, attempted unmanaged egress, revocation of previously allowed traffic, and controller/broker loss. Use an upstream canary that records whether any protected bytes arrive. Include built-in and delegated backends, including missing, empty, malformed and semantically incomplete audit evidence. Record whether launch is refused and whether active traffic is closed; do not treat digest equality or successful startup alone as proof. + +## BASELINE-01 — Upstream source baseline drift + +**Evidence class:** `SOURCE`. **Status: NOT TESTED — newer baseline partially reviewed in selected areas only.** + +**Observation:** The audit baseline is pinned to `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`. At the time of this check, NVIDIA/OpenShell `main` was `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`, 13 commits ahead of the pinned baseline. The comparison reports 225 changed files across the full repository. This does not automatically invalidate commit-specific observations, but it means they must not be presented as an audit of current `main`. + +**Relevant changed surfaces:** `crates/openshell-isolation-interface/src/contract.rs` changed from 1,076 to 626 lines and now describes validated data shared by an RPC client/server rather than the earlier runtime-selectable trait contract; `crates/openshell-isolation-interface/tests/backend_conformance.rs` changed from 907 to 140 lines, with its header now describing shared-data validation and lifecycle/process behavior tested over RPC. Driver isolation modules and network-recovery tests also changed. These are architectural/test-harness changes to review, not proof that coverage or enforcement weakened; test coverage may have moved to other files. + +**EABC relevance:** Re-audit the concrete enforcement boundary and substrate before making claims about `NON_BYPASSABILITY(B,E)`, `INTEGRITY_DEF(B)`, `INTEGRITY_STATE(B,E)`, or `INTEGRITY_CTX(C,B,E)`. A conformance harness change is not itself evidence of EABC conformance or non-conformance. + +**Pinned comparison evidence:** [baseline commit](https://github.com/NVIDIA/OpenShell/commit/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317); [checked upstream commit](https://github.com/NVIDIA/OpenShell/commit/b58e24c9dabd6d4bcf2b7186592d3ad50646541b); [compare the 13-commit range](https://github.com/NVIDIA/OpenShell/compare/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317...b58e24c9dabd6d4bcf2b7186592d3ad50646541b); [isolation contract at checked upstream commit](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-isolation-interface/src/contract.rs); [backend conformance tests at checked upstream commit](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-isolation-interface/tests/backend_conformance.rs). + +**Next step:** keep the current findings explicitly commit-scoped. Add a follow-up review of the changed isolation interface, RPC protocol, replacement conformance tests, driver implementations and network recovery behavior before making any claim about current upstream `main`. Do not silently move the pinned baseline. + +--- + +## OS-01 — Network paths and direct-egress bypass + +**Evidence classes:** `DOC-CLAIM` for driver documentation; `SOURCE` for inspected implementation; `TEST-CONTRACT` for named tests. **Runtime status: NOT TESTED — runtime bypass status unknown.** + +**EABC relevance:** Primarily `NON_BYPASSABILITY(B,E)` for every path to the protected effect, plus `INTEGRITY_CTX(C,B,E)` where routing/endpoint context determines authorization. This is a candidate mapping, not an EABC conformance result. + +- Docker driver documentation describes `network_mode=none` and TCP/DNS mediation through a seccomp user-notification broker. +- Podman documentation describes `network=none`, protected Unix-socket/authenticated gRPC mediation, and no generic UDP support. +- VM driver documentation describes no virtual NIC and a protected vsock channel. +- Source tests include `workload_sockets_are_bound_to_loopback_and_cannot_be_rebound`, `broker_refuses_socket_families_it_cannot_confine`, `external_connect_waits_for_explicit_relay_decision`, `denied_external_connect_keeps_socket_unconnected`, and `workload_cannot_bind_a_non_loopback_source_address`. + +**Limits:** These are documentation/source/test-contract observations, not evidence that tests ran. Test each driver independently. Test direct TCP, UDP, IPv6, ICMP, raw sockets, UNIX socket paths outside the broker, supervisor failure/restart, private/link-local/metadata targets, and DNS rebinding including mixed A/AAAA answers. + +**Pinned evidence:** [Docker driver README, lines 39–44](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-docker/README.md#L39-L44); [Podman networking, lines 1–25](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-podman/NETWORKING.md#L1-L25); [VM driver README, lines 281–286](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/README.md#L281-L286); [network broker tests, lines 2603–2690 and 2898–3005](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-sandbox/src/network_broker.rs#L2603-L2690) and [network broker connect tests](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-sandbox/src/network_broker.rs#L2898-L3005). + +## OS-02 — Credential binding, rotation, revocation + +**Evidence class:** `TEST-CONTRACT` (source test inspected). **Runtime status: NOT TESTED — source test contract only.** + +**EABC relevance:** `INTEGRITY_CTX(C,B,E)` for endpoint/credential binding, `EXCLUSIVITY` for preventing use outside the authorized endpoint, and `NON_BYPASSABILITY(B,E)` only if all paths to the protected effect are mediated. The test contract alone does not establish those EABC properties. + +Pinned source test: [`stable_external_placeholders.rs`, lines 1028–1043](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/e2e/rust/tests/stable_external_placeholders.rs#L1028-L1043). + +The file is gated by `e2e-docker`. Tests named `persistent_external_placeholder_rotation_and_revocation` and `ordinary_external_placeholder_keeps_revoked_assertion_after_rotation` exercise a synthetic `tools/call` request over a sandbox HTTPS path, endpoint binding controls, and credential rotation/revocation. This is not a complete MCP session or full agent-runtime test. Do not describe it as runtime-passed without a run record. [Pinned test functions, lines 1028–1043](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/e2e/rust/tests/stable_external_placeholders.rs#L1028-L1043). + +## OS-06 — Authorization generation / credential guard + +**Evidence classes:** `SOURCE`, `TEST-CONTRACT`; RFC statements are `DOC-CLAIM`. **Runtime status: NOT TESTED — race behavior not validated end-to-end.** + +**EABC relevance:** `INTEGRITY_STATE(B,E)` and `INTEGRITY_CTX(C,B,E)` because policy generation and endpoint context must remain bound to the decision; `NON_BYPASSABILITY(B,E)` if a stale decision can reach the protected effect. These are audit mappings, not conformance conclusions. + +The original audit baseline is pinned to `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`. A follow-up source-drift review at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` found explicit generation guards around CONNECT setup, upstream dialing, the CONNECT success response, and active relays. The guard captures an expected generation, rejects a mismatch when created, exposes `ensure_current()`, and waits for generation changes; CONNECT code rejects a stale route before dialing, races upstream dialing against a stale-generation signal, and checks the guard again before sending `200 Connection Established` ([generation guard, lines 206–249](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L206-L249); [CONNECT checks, lines 2947–2999](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2947-L2999)). A source unit test reloads policy and asserts a stale forward relay writes no bytes to upstream ([test, lines 14100–14150](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L14100-L14150)). + +**Unresolved documentation/implementation discrepancy:** RFC 0005 `current-shape.md` still describes separate metadata queries not all asserted against the L4 generation ([lines 221–240](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/current-shape.md#L221-L240)), while its implementation plan calls for a single generation-consistent authorization result and reload-race tests ([lines 66–83](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/rfc/0005-sandbox-proxy-egress-adapter/implementation-plan.md#L66-L83)). The source guards materially mitigate stale-generation use at the dial/relay boundary, but do not alone prove that every materialized field came from the same generation or that all race windows are covered. Record this as an unresolved documentation/implementation discrepancy until the maintainers reconcile the RFC appendix with the exact implementation and its tests; do not label it a confirmed vulnerability. + +The separate credential-guard query does not itself return a generation. That fact alone is not a vulnerability because the surrounding guards may reject stale decisions. The relevant falsification test must observe the actual protected effect, not just supervisor logs. + +**Falsification test:** add barriers between primary authorization, credential-guard query, TLS/L7 metadata hydration, final generation check, upstream dial completion, and CONNECT success. Reload from a raw-tunnel-allowed rule to a credentialed endpoint requiring L7, and reverse. During active HTTP/raw relays, publish both a valid new generation and a fail-closed quarantine generation. Use an upstream canary that records request bytes and whether injected credentials arrived. Expected fail-closed result: no stale-generation protected bytes or credentials reach upstream; a stale CONNECT is rejected before success, and active stale relays close. Runtime status remains `NOT TESTED`. + +## OS-07 — Evaluation error vs missing L7 metadata + +**Evidence class:** `TEST-CONTRACT` (source regression tests inspected). **Runtime status: NOT TESTED — source regression contract only.** + +**EABC relevance:** `INTEGRITY_CTX(C,B,E)` and `NON_BYPASSABILITY(B,E)`: a fallback must not silently weaken the boundary applicable to the protected effect. + +Pinned test file: [`compatibility.rs`, lines 283–330](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy/tests/compatibility.rs#L283-L330). + +Tests cover missing authorized L7 metadata falling back to L4-only defaults and an authoritative evaluation error denying rather than falling back. This is a useful distinction, but it does not prove every production retrieval/decode failure follows the same fail-closed path. For the credential-injection-specific analysis and newer-source counter-evidence, see [OS-09](#os-09--missing-l7-metadata-and-credential-injection-boundary); OS-07 and OS-09 overlap in the fallback question but are not identical: OS-07 distinguishes evaluation error from missing metadata, while OS-09 assesses whether the fallback can expose injected credentials. [Pinned compatibility tests, lines 270–345](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-supervisor-network/src/proxy/tests/compatibility.rs#L270-L345). + +## OS-08 — VM bind mounts / virtiofs + +**Evidence classes:** `DOC-CLAIM`, `SOURCE`, and `TEST-CONTRACT`. **Runtime status: NOT TESTED — host-path escape status unknown.** + +**EABC relevance:** `NON_BYPASSABILITY(B,E)` and `INTEGRITY_DEF(B)` for the filesystem boundary; `INTEGRITY_CTX(C,B,E)` where the configured share defines the authorized context. + +Pinned source areas: `crates/openshell-driver-vm/src/driver.rs`, `scripts/openshell-vm-sandbox-init.sh`, `src/ffi.rs`, `README.md`, and `e2e/rust/tests/vm_bind_mount.rs`. + +- Bind mounts are opt-in (`enable_bind_mounts` defaults false) and rejected when resource admission is enabled. +- Mount configuration has `read_only` defaulting true; the flag is passed to the libkrun virtiofs API. +- Source path validation checks absolute paths, rejects a final symlink, checks directory/accessibility at provisioning, and fails on missing/inaccessible paths. +- Guest target validation rejects reserved/internal paths and overlaps; guest init refuses symlink target components and fails if mount fails. +- E2E test contract covers two temporary host shares, read/write behavior for RW, and refusal to overwrite through RO. +- OpenShell VM README warns host bind mounts expose host files and may bypass workspace isolation/filesystem policy. + +Upstream libkrun documentation warns that virtiofs alone does not isolate a share from other directories/filesystems visible to the host VMM process and recommends host OS mount isolation. This is a material question, not proof that OpenShell is vulnerable: inspect the actual launch environment and verify whether the VMM process is restricted to the intended host paths. Test with harmless canary files outside the allowed share, separately for RO/RW and each supported host platform. Also test symlinks and hardlinks inside the shared tree that target outside paths, `..` traversal, and already-open file descriptors; determine whether the host VMM process or guest can follow those paths. [VM read-only default, lines 140–160](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/src/driver.rs#L140-L160); [bind-mount opt-in and validation, lines 5150–5165](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/src/driver.rs#L5150-L5165); [guest virtiofs target checks, lines 526–585](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/scripts/openshell-vm-sandbox-init.sh#L526-L585); [VM bind-mount E2E test, lines 1–100](https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/e2e/rust/tests/vm_bind_mount.rs#L1-L100). + +## SG-01 — Sentry standalone + +**Evidence class:** `DOC-CLAIM` for NVIDIA's public architecture/capability statements; `SOURCE` and `RUNTIME` not assessed. **Status: NOT TESTED — implementation and enforcement evidence pending.** NVIDIA describes Sentry as an out-of-band watchdog on BlueField-4, with in-silicon policy enforcement, agent monitoring, attested telemetry, identity verification and quarantine when an agent moves outside its software boundary ([official NVIDIA announcement, published 2026-09-28; accessed 2026-10-17](https://investor.nvidia.com/news/press-release-details/2026/NVIDIA-Launches-Open-Agent-Safety-Platform-to-Secure-Agents-From-Testing-to-Deployment/)). These are vendor claims, not independently verified behavior or an EABC conformance result. + +**Candidate EABC criteria, not yet established:** `NON_BYPASSABILITY(B,E)` requires proof that every path to the concrete protected effect traverses the boundary; `INTEGRITY_CTX(C,B,E)` requires binding of identity, policy, target and request context; `INTEGRITY_STATE(B,E)` may apply to policy/version freshness and fail-safe state transitions; `ENFORCEMENT_INDEPENDENCE` is an EBP assurance constraint, not an EABC semantic property. Do not mark any of these satisfied based on the announcement alone. Before testing, pin exact Sentry software/firmware version, device model, deployment mode and configuration; specify the protected effect, attacker model, trust boundary, failure behavior and observable evidence. + +## COM-01 — OpenShell + Sentry composition + +**Evidence class:** `DOC-CLAIM` for the platform description; integrated `SOURCE` and `RUNTIME` not assessed. **Status: NOT TESTED — integration evidence pending.** NVIDIA describes OpenShell as the software runtime boundary and Sentry/BlueField-4 as an additional out-of-band hardware layer ([official NVIDIA announcement, published 2026-09-28; accessed 2026-10-17](https://investor.nvidia.com/news/press-release-details/2026/NVIDIA-Launches-Open-Agent-Safety-Platform-to-Secure-Agents-From-Testing-to-Deployment/)). The announcement does not establish how authorization is bound across the two components or prove that all protected-effect commit paths are mediated. + +**Candidate EABC criteria, not yet established:** `NON_BYPASSABILITY(B,E)` for the composed boundary; `INTEGRITY_CTX(C,B,E)` for binding OpenShell policy, Sentry identity/decision and the actual target/request; `INTEGRITY_STATE(B,E)` for policy updates, reset, downgrade and component failure. Before testing, pin OpenShell commit plus exact Sentry software/firmware, device and configuration. Enumerate alternate/local paths to the protected effect, then test authorized/denied actions, failure, restart, policy changes, stale decisions and downgrade. Component claims must not be added together as if composition were proven. + +## References + +- OpenShell pinned commit: https://github.com/NVIDIA/OpenShell/commit/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 +- Docker driver: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-docker/README.md +- Podman networking: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-podman/NETWORKING.md +- VM driver README: https://github.com/NVIDIA/OpenShell/blob/a4c848adbddd0b4732fd70ddcf8a563a5b1e9317/crates/openshell-driver-vm/README.md +- libkrun security notes: https://github.com/libkrun/libkrun (upstream documentation; pin the exact reviewed revision before treating it as a reproducible evidence artifact) + + +## OS-06 — Authorization generation, credential guard and RFC 0005 Phase 3 + +**Evidence classes:** `SOURCE`, `TEST-CONTRACT`, `DOC-CLAIM`. **Status: NOT TESTED.** The original audit baseline is `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`; the follow-up source review is separately pinned to `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. The two are not interchangeable test baselines. See [OS-06 generation review](evidence/openshell-os06-generation-review.md) and [focused RFC 0005 call-path audit](evidence/openshell-rfc0005-phase3-callpath-audit.md). + +**EABC relevance:** `INTEGRITY_STATE(B,E)` and `INTEGRITY_CTX(C,B,E)` for policy generation and endpoint context; `NON_BYPASSABILITY(B,E)` if stale or insufficiently constrained authorization can reach the protected effect. These are candidate mappings, not conformance conclusions. + +At `b58e24c`, CONNECT checks the captured connection generation against the L7 route generation, rejects stale policy, races upstream dialing against stale-generation notification, and checks again before returning CONNECT success. Relay setup validates route generation, and a source unit test asserts that a stale forward relay writes no bytes to upstream ([generation guard](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/opa.rs#L195-L249); [CONNECT checks](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L2947-L2999); [stale relay source test](https://github.com/NVIDIA/OpenShell/blob/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/crates/openshell-supervisor-network/src/proxy.rs#L14100-L14150)). These are meaningful source-level controls, not a record of this audit executing the tests. + +The inspected CONNECT path projects TLS mode, L7 route and destination planning (`allowed_ips`) from the initial authorization decision's endpoint-config snapshot. The broad claim that those fields necessarily mix policy generations is **not supported by this source trace**. The credential guard is a separate OPA evaluation and its API returns `Result>`, not a result paired with its own generation. The handler instead relies on its captured generation and subsequent stale-generation checks. This is a falsifiable test lead, not proof that the guard result is misbound or that a bypass exists. + +RFC 0005's `current-shape.md` describes an earlier transitional shape, and the implementation plan describes Phase 3 as a target for one generation-consistent authorization result and reload-race tests. The reviewed RFC material does not establish whether Phase 3 was declared planned, in progress or complete for `b58e24c`. Until a commit-specific status is found, this is not classed as failure to meet a committed milestone. + +**Remaining work:** close the production call graph; establish the RFC Phase 3 status for the exact commit; run exact-SHA tests with deterministic barriers around the credential-guard query, upstream dial completion, CONNECT success and relay startup; and use an independent upstream canary to record whether protected bytes or synthetic credentials arrive. Runtime status remains **NOT TESTED**. No confirmed vulnerability is claimed. + diff --git a/audits/nvidia-openshell-sentry/test-matrix.md b/audits/nvidia-openshell-sentry/test-matrix.md new file mode 100644 index 0000000..986dc8b --- /dev/null +++ b/audits/nvidia-openshell-sentry/test-matrix.md @@ -0,0 +1,118 @@ +# Runtime test matrix — OpenShell / Sentry + +This is a test plan, not a test report. No runtime tests are represented as executed. Every row starts with status `NOT TESTED`. Run only in an isolated lab using synthetic credentials and harmless canary data. + +## Result-state vocabulary + +- `NOT TESTED`: no adequate runtime execution record exists. +- `INCONCLUSIVE`: test ran, but evidence does not decide the stated hypothesis. +- `PASS`: observed behavior meets the explicit expected result in the recorded scope. +- `FAIL`: observed behavior violates the explicit expected result in the recorded scope. + +Do not use `NOT REPRODUCED` unless an actual reproduction attempt ran and its conditions/results are recorded. Evidence class is separate from test result: `DOC-CLAIM`, `SOURCE`, `TEST-CONTRACT`, `RUNTIME`. + +## Baseline-drift gate + +Rows now carry an explicit `Target commit`. Legacy NET/CRED/GEN/EVAL/VM rows target OpenShell `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` unless noted; follow-up revocation/controller-loss and newer backend/source-review rows target `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. Sentry/composition rows remain unpinned until the exact Sentry implementation and OpenShell/Sentry pair are identified. Never run a row against a different SHA and reuse its result; create a new versioned row/evidence record instead. + +## Test matrix + +**Status vocabulary note:** the rightmost `Status` column is the sole test-result scale (`NOT TESTED`, `INCONCLUSIVE`, `PASS`, `FAIL`). Text in the `Evidence to capture` column such as “scope definition pending” describes prerequisites, not a second result state. `VENDOR DOC-CLAIM only` is an evidence class, not a test status. + +| ID | Target | Target commit | Test | Expected safe result | Evidence to capture, including effect-side observation | Evidence class at planning stage | EABC criterion | Status | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| NET-01 | Docker | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Attempt direct TCP to a controlled public canary IP without configured relay | No direct egress; canary receives no connection or payload | Exact image/commit/config, command, packet capture, broker logs, canary connection log | DOC-CLAIM + SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| NET-02 | Docker / Podman / VM separately | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Try direct UDP and DNS, IPv4 and IPv6, ICMP, raw sockets, alternate socket families, socket rebinding, and UNIX socket paths outside the approved broker; include mixed A/AAAA answers | Unsupported or unauthorized paths are rejected; no unmediated path reaches canary | Per-driver command/script, syscall and network traces, resolver answers, broker logs, canary-side records | DOC-CLAIM + SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| NET-03 | Each driver | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Kill/restart supervisor or broker during attempted connection and while a connection is active | No fail-open path; protected traffic stops or is denied | Fault-injection timeline, process logs, packet capture, upstream canary records | SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| NET-04 | Each driver | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Attempt private, link-local and metadata targets; DNS rebinding and mixed A/AAAA responses | Denied unless explicitly authorized; resolved destination remains within the authorized decision | Resolver answers, policy decision/generation, packet capture, canary/upstream records | SOURCE + TEST-CONTRACT | INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| CRED-01 | Docker E2E | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Wrong host/port/path, alias, untrusted CA and disallowed binary against synthetic endpoint | Backend receives no accepted protected call and no injected credential | Config/policy hashes, request trace, client result, backend counters and credential-safe audit record | TEST-CONTRACT | INTEGRITY_CTX(C,B,E); EXCLUSIVITY; NON_BYPASSABILITY(B,E) | NOT TESTED | +| CRED-02 | Docker E2E | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Rotate provider credential A→B; compare persistent and ordinary references; revoke A | Persistent reference uses current B as designed; revoked ordinary reference is rejected | Provider-side generation/counters, request trace and test output; never store raw secret values | TEST-CONTRACT | INTEGRITY_CTX(C,B,E); EXCLUSIVITY | NOT TESTED | +| REV-01S | Static provider credential revocation | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Establish a valid endpoint-bound static credential, then revoke/change its binding or force refresh/binding validation failure; attempt use of the old static placeholder | Old static placeholder is rejected after the documented activation boundary; no protected bytes or secret reach the canary | Exact SHA, provider/policy generations, refresh result, request decision, safe credential identifier, canary-side request/header record; never log raw secrets | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| REV-01D | Dynamic grant revocation/lifetime | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Establish a dynamic grant and prove its use; change/revoke policy or provider binding while grant remains live, then test the old grant before and after its documented expiry/refresh boundary | Expected behavior is determined from the explicit dynamic-grant contract; test must not assume static-credential revocation semantics apply to dynamic grants. Any grant permitted after change must be explicitly documented and scoped | Grant type/ID (not secret), policy/provider generations, issue/expiry/revocation timestamps, request decision, canary-side protected-effect record; never log raw secrets | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| CTL-01-D | Docker backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | While workload repeatedly attempts harmless egress to a recording canary, sever supervisor-to-boundary transport and separately terminate the logical supervisor | Deny egress immediately when the boundary/transport is unavailable. If enforcement cannot be maintained, stop/contain the workload; record measured time to denial and stop. A missing documented bound is a separate documentation gap and cannot count as PASS. | Exact SHA/config, fault-injection timestamps, driver/runtime logs, active connection and packet traces, measured stop bound, canary-side connection/payload records | SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| CTL-01-P | Podman backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | While workload repeatedly attempts harmless egress to a recording canary, sever supervisor-to-boundary transport and separately terminate the logical supervisor | Deny egress immediately when the boundary/transport is unavailable. If enforcement cannot be maintained, stop/contain the workload; record measured time to denial and stop. A missing documented bound is a separate documentation gap and cannot count as PASS. | Exact SHA/config, fault-injection timestamps, driver/runtime logs, active connection and packet traces, measured stop bound, canary-side connection/payload records | SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| CTL-01-V | QEMU/libkrun MicroVM backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | While workload repeatedly attempts harmless egress to a recording canary, sever supervisor-to-boundary transport and separately terminate the logical supervisor | Deny egress immediately when the boundary/transport is unavailable. If enforcement cannot be maintained, stop/contain the workload; record measured time to denial and stop. A missing documented bound is a separate documentation gap and cannot count as PASS. | Exact SHA/config, fault-injection timestamps, driver/runtime logs, active connection and packet traces, measured stop bound, canary-side connection/payload records | SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| CTL-01-K | Kubernetes backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | While workload repeatedly attempts harmless egress to a recording canary, sever supervisor-to-boundary transport and separately terminate the logical supervisor | Deny egress immediately when the boundary/transport is unavailable. If enforcement cannot be maintained, stop/contain the workload; record measured time to denial and stop. A missing documented bound is a separate documentation gap and cannot count as PASS. | Exact SHA/config, fault-injection timestamps, driver/runtime logs, active connection and packet traces, measured stop bound, canary-side connection/payload records | SOURCE + TEST-CONTRACT | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| CTL-02-D | Docker backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Attempt recovery with the same logical supervisor, then with a replacement supervisor and stale generation-bound launch credentials | Same-process recovery re-confirms binding; replacement supervisor cannot resume an old runtime generation without fresh admission/binding | Exact SHA/config, supervisor process IDs, session/generation IDs, credential lineage, attach/confirm transcripts, runtime lifecycle and canary records | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| CTL-02-P | Podman backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Attempt recovery with the same logical supervisor, then with a replacement supervisor and stale generation-bound launch credentials | Same-process recovery re-confirms binding; replacement supervisor cannot resume an old runtime generation without fresh admission/binding | Exact SHA/config, supervisor process IDs, session/generation IDs, credential lineage, attach/confirm transcripts, runtime lifecycle and canary records | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| CTL-02-V | QEMU/libkrun MicroVM backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Attempt recovery with the same logical supervisor, then with a replacement supervisor and stale generation-bound launch credentials | Same-process recovery re-confirms binding; replacement supervisor cannot resume an old runtime generation without fresh admission/binding | Exact SHA/config, supervisor process IDs, session/generation IDs, credential lineage, attach/confirm transcripts, runtime lifecycle and canary records | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| CTL-02-K | Kubernetes backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Attempt recovery with the same logical supervisor, then with a replacement supervisor and stale generation-bound launch credentials | Same-process recovery re-confirms binding; replacement supervisor cannot resume an old runtime generation without fresh admission/binding | Exact SHA/config, supervisor process IDs, session/generation IDs, credential lineage, attach/confirm transcripts, runtime lifecycle and canary records | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| GEN-01 | Supervisor proxy | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Place a barrier between main authorization and credential-guard evaluation; reload policy from raw-tunnel allowed to L7/credential-constrained and reverse | Stale decision cannot send protected request or injected credential to upstream | Barrier timestamps, generation IDs, client transcript, proxy logs AND upstream canary logs showing whether protected bytes/credential arrived | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| GEN-02 | Supervisor proxy | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Reload policy between final generation check and CONNECT success | Stale CONNECT rejected/closed before protected bytes reach upstream | Client transcript, generation timeline, proxy logs AND upstream canary connection/payload record | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| GEN-03 | Active relay | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Publish fail-closed generation during raw/HTTP relay | Stale relay closes; no protected bytes or injected credential flow after the applicable invalidation point | Generation timeline, socket traces, byte counts, proxy logs AND upstream canary records | SOURCE + TEST-CONTRACT | INTEGRITY_STATE(B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| GEN-04 | Authorization / credential guard / TLS-L7 metadata / CONNECT | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Insert deterministic barriers between each query/materialization stage and the final generation check; reload policy in both directions and publish fail-closed quarantine; use upstream canary for protected bytes and injected credentials | Any stale/mixed-generation decision is rejected before protected upstream bytes or injected credentials arrive; stale CONNECT never returns success; active stale relays close | Canary request/body/header log, policy and generation hashes, barrier schedule, OPA/proxy traces, CONNECT transcript, relay-close timing | TEST-CONTRACT + SOURCE | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| EVAL-01 | OPA/proxy | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Compare absent L7 metadata with authoritative evaluation error, including credential-injection endpoints | Authoritative evaluation error denies. Missing-metadata fallback must not weaken the applicable boundary or expose injected credentials | OPA input/result, policy and generation, proxy decision, client transcript, upstream canary record | TEST-CONTRACT + SOURCE | INTEGRITY_CTX(C,B,E); EXCLUSIVITY; NON_BYPASSABILITY(B,E) | NOT TESTED | +| EVAL-02 | Credentialed endpoint / L4 fallback | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Test missing/malformed L7 and credential-guard metadata, authoritative OPA error, overlapping L4 + inspected endpoints, and both default-deny and explicit `allow_uninspected_credentials: true` policies | Default-deny credentialed endpoints deliver neither protected request nor injected credential to upstream; explicit opt-in is confined to the exact configured endpoint | Canary request path/headers/credential record; effective policy hash; OPA/proxy traces; endpoint match and generation IDs | SOURCE + TEST-CONTRACT + DOC-CLAIM | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| VM-01 | VM/libkrun | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | RO and RW virtiofs behavior with temporary share | RO cannot mutate host share; RW changes only the intended share | Host hashes, guest commands, mount table, logs, host/guest versions | SOURCE + TEST-CONTRACT | INTEGRITY_DEF(B); NON_BYPASSABILITY(B,E) | NOT TESTED | +| VM-02 | VM/libkrun | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Put harmless canary files outside allowed share on same filesystem; attempt access from guest | Guest cannot access paths outside the authorized share | Host mount namespace and VMM process configuration, guest output, host audit logs and canary access logs | DOC-CLAIM + SOURCE | INTEGRITY_DEF(B); NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| VM-03 | VM/libkrun | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Test final and parent symlinks, symlinks and hardlinks inside share pointing outside, `..` traversal, source replacement during provisioning, and already-open file descriptors | No path or descriptor grants access outside the authorized share; invalid paths/races fail safely | Exact filesystem layout, race script, inode/device identities, host and guest traces, canary access logs | SOURCE + TEST-CONTRACT | INTEGRITY_DEF(B); NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| VM-04 | VM/libkrun | a4c848adbddd0b4732fd70ddcf8a563a5b1e9317 | Attempt reserved/overlapping guest targets and force virtiofs mount failure | Provision/mount fails rather than silently continuing with unintended semantics | Manifest, init logs, guest mount table, host-side records | SOURCE + TEST-CONTRACT | INTEGRITY_DEF(B); NON_BYPASSABILITY(B,E) | NOT TESTED | +| FENCE-01 | Docker / built-in backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Mutate attached network or network mode after provisioning and before launch/restart; test missing inspect fields and stale/wrong-generation evidence | Actual inspected fence drift is rejected before workload launch/restart; stale binding is rejected | Docker inspect response, driver result, descriptor/confirmation, supervisor result, upstream canary | TEST-CONTRACT + SOURCE | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| FENCE-02 | Podman / built-in backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Mutate attached network, network mode or privileged flag after provisioning and before launch/restart | Actual inspected fence drift is rejected before workload launch/restart; no unmanaged egress; controller loss does not open access | Podman inspect response, driver result, host networking state, broker logs, packet capture, upstream canary | TEST-CONTRACT + SOURCE | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| BACKEND-01 | Delegated backend | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Return null, empty, malformed and semantically incomplete audit/confirmation data; test wrong generation/session/identity/resource claims and mismatched evidence digest | Reject before agent launch unless trusted delegated validation establishes required boundary and launch binding | RPC transcript, descriptor/confirmation, driver-side native validation evidence, supervisor result, upstream canary | TEST-CONTRACT + SOURCE | INTEGRITY_DEF(B); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| VMNET-01 | VM / QEMU / libkrun | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Compare generated VM provisioning evidence with effective launched device inventory and, where feasible, inject an unexpected virtual NIC | Launch/confirmation rejected if effective VM configuration violates no-direct-network-path invariant; evidence must describe the actual launch | Exact launcher args, effective VM device inventory, hypervisor logs, generation descriptor, guest and host network state, upstream canary | TEST-CONTRACT + SOURCE | INTEGRITY_DEF(B); INTEGRITY_CTX(C,B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| VMNET-02 | VM / QEMU / libkrun | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Inspect guest-visible devices and host listeners; attempt direct guest IP egress and unauthorized host access through vsock | No guest IP NIC/direct egress; vsock exposes only the intended authenticated control/data path; loss/recovery cannot leave an unconfirmed boundary active | Effective VM device inventory, QEMU/libkrun arguments and versions, host socket/vsock listeners, guest route/device tables, control-channel logs, upstream canary | TEST-CONTRACT + SOURCE | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| BACKEND-02 | Delegated backend admission / confirmation | b58e24c9dabd6d4bcf2b7186592d3ad50646541b | Verify trusted-composition selection, admitted name, endpoint authentication/socket ownership and binding to sandbox/session/generation; test null, empty, malformed and semantically incomplete evidence; include a deliberately non-enforcing but correctly admitted backend in an isolated harness | Admission/context mismatches reject before discovery/launch; document whether a correctly admitted but non-enforcing backend can be detected; never treat null backend audit alone as a failure | Backend identity/version, registration and endpoint config, socket owner/permissions or TLS peer evidence, protocol transcript, descriptor and confirmation, upstream canary | TEST-CONTRACT + SOURCE | NON_BYPASSABILITY(B,E); INTEGRITY_DEF(B); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| SENTRY-01 | Sentry standalone | Not pinned — scope prerequisite | First pin exact Sentry software/firmware version, device/model, deployment mode and configuration; then identify protected effect and enumerate every commit path, including alternate/local paths | Audit scope is reproducible; every path to the protected effect traverses the claimed boundary | Version/firmware identifiers, wiring and architecture, threat model, effect-side traces and bypass attempts | Scope definition pending: pin version/config and protected effect | To be determined from concrete boundary and protected effect | NOT TESTED | +| SENTRY-02 | Sentry standalone | Not pinned — scope prerequisite | With pinned version, compromise/disable requester software; test replay, stale authorization, reset/downgrade and failure modes | Protected effect cannot commit without valid boundary satisfaction | Exact versions/config, fault-injection steps, authorization/effect traces, hardware records | Scope definition pending: pin version/config and protected effect | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E), as applicable | NOT TESTED | +| COMP-01 | OpenShell + Sentry | Not pinned — scope prerequisite | Pin OpenShell commit and exact Sentry software/firmware/device/config; exercise authorized and denied requests end-to-end | Only intended protected effects commit; no alternate path bypasses the composed boundary | Architecture and versions, policy/config hashes, component logs, client transcript AND protected-effect-side record | Scope definition pending: pin both components and deployment | To be determined for the composed boundary; assess NON_BYPASSABILITY(B,E) and binding of context/state | NOT TESTED | +| COMP-02 | OpenShell + Sentry | Not pinned — scope prerequisite | With pinned composition, fail/restart either component, change policy, downgrade configuration and disconnect control channel | Composition fails safely and preserves authorization-to-effect binding | Fault-injection timeline, versions/config, component logs, client transcript AND protected-effect-side record | Scope definition pending: pin both components and deployment | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E), as applicable | NOT TESTED | + +**Overlap resolution:** former `BASELINE-02-03` was removed as a duplicate composite row. Its distinct checks are covered by `VMNET-01` (effective VM device inventory/no unexpected NIC), `CTL-01-V` (VM boundary/supervisor loss), `REV-01S`/`REV-01D` (static credentials versus dynamic grants), and `VMNET-02` (vsock/host access and recovery). These are separate hypotheses and must not be double-counted as independent duplicate coverage. `VMNET-01` now covers effective device inventory only; restart/recovery belongs to `CTL-02-V`, and controller/transport loss belongs to `CTL-01-V`. + +**Targeted CI workflow:** [`.github/workflows/openshell-targeted-tests.yml`](../../.github/workflows/openshell-targeted-tests.yml) checks out the exact `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` source SHA, runs each named regression test separately, and uploads per-test logs, metadata, and JUnit XML. Creating the workflow does not mean it has passed; do not change any row from `NOT TESTED` until a completed run and its artifact have been inspected. + +**Named regression tests at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`:** (1) `stale_generation_fails_before_relay_context_is_created` in `crates/openshell-supervisor-network/src/proxy/relay.rs`; (2) `test_forward_relay_guard_blocks_stale_generation_before_upstream_write` in `crates/openshell-supervisor-network/src/proxy.rs`; and (3) `credential_guard_does_not_shadow_inspected_endpoint_config` in `crates/openshell-supervisor-network/src/opa.rs`. These are three distinct source tests. The targeted workflow runs each individually. All remain `NOT TESTED` until a run records the exact SHA, command, exit code, and individual test output. + +**CI evidence scope:** for run `38991707083`, the jobs API and downloaded job logs were inspected; logs showed broad `cargo nextest run` commands and successful job conclusions, but not individual test names/results. The only listed artifact was an API/SDK compatibility-review artifact, not Rust/JUnit output. The Actions run page itself was not independently read. Do not infer that the three named tests passed from that CI signal. + +## Execution record template + +For every attempted row, add: + +- Date/time and operator. +- Host OS/version, hardware, and relevant isolation settings. +- OpenShell commit, driver, libkrun version, and Sentry firmware/software/device versions where applicable. +- Exact test command/script revision and configuration/policy hashes. +- Expected result and observed result. +- Client-side result and independent upstream/protected-effect-side observation. +- Logs, packet captures, effect-side records, and artifact paths. +- Result: `PASS`, `FAIL`, or `INCONCLUSIVE`; explain deviations. +- Scope limitations and whether the result applies to Docker, Podman, VM, Sentry, or their composition. + +Do not mark a test `PASS` based only on a unit-test name, code inspection, or supervisor logs when the claim concerns whether a protected effect or credential reached its destination. + +## OS-06 source follow-up + +The OS-06 RFC/source comparison is recorded in [`evidence/openshell-os06-generation-review.md`](evidence/openshell-os06-generation-review.md). The source contains route-generation checks and stale-relay machinery, but the runtime matrix remains necessary to determine whether all connection metadata and credential-guard decisions remain generation-consistent under reload. In particular, run GEN-01 through GEN-04 with deterministic barriers and an independent upstream canary. All remain **NOT TESTED**; do not change status based on this source review. + +## Deterministic runtime protocol +The detailed execution protocol for GEN-01 through GEN-04 is recorded in [openshell-generation-runtime-protocol.md](evidence/openshell-generation-runtime-protocol.md). It specifies policy fixtures, deterministic barrier placement, independent upstream canary observations, evidence manifests, and PASS/FAIL/INCONCLUSIVE criteria. It is a plan only; all GEN rows remain **NOT TESTED** until actual runs and artifacts are recorded. +## Pinned-source seam map +The concrete CONNECT code order and recommended deterministic test-hook locations for GEN-01 through GEN-04 are documented in [openshell-generation-seam-map.md](evidence/openshell-generation-seam-map.md). This is still source review only; no runtime scenario has been executed and all GEN statuses remain **NOT TESTED**. + +## GEN-01 regression coverage review +The pinned-source review of existing stale-generation relay and credential-guard tests is recorded in [openshell-gen01-regression-coverage.md](evidence/openshell-gen01-regression-coverage.md). Existing tests lower the plausibility of a simple stale-generation race, but do not themselves establish canary-observed upstream behavior for the complete CONNECT path. No new runtime test was executed; GEN-01 through GEN-04 remain **NOT TESTED**. + +## OS-06 RFC 0005 conformance review +See [openshell-rfc0005-conformance-review.md](evidence/openshell-rfc0005-conformance-review.md) and the refined [Phase 3 CONNECT call-path audit](evidence/openshell-rfc0005-phase3-callpath-audit.md). Source inspection at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` shows TLS, L7 route and destination planning are projected from the initial authorization snapshot; the credential guard is the material separate OPA evaluation. Therefore the test priority is not to assume arbitrary mixed-generation fields, but to test alignment of the separate credential-guard result across policy reload, stale-generation rejection, upstream dial completion and relay startup. Existing locking, generation guards and overlap regression coverage are counter-evidence, not runtime proof. All relevant tests and canary scenarios remain **NOT TESTED**. + +## Upstream CI evidence for reviewed follow-up commit + +On 2026-10-17, GitHub's commit-status API was queried for exact commit `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`; the returned contexts were `success` for OpenShell Branch Checks, E2E and GPU E2E, with target URL [workflow run 38991707083](https://github.com/NVIDIA/OpenShell/actions/runs/38991707083), and `success` for Helm Lint, with target URL [workflow run 38991707025](https://github.com/NVIDIA/OpenShell/actions/runs/38991707025). The exact API endpoint is [commit combined status](https://api.github.com/repos/NVIDIA/OpenShell/commits/b58e24c9dabd6d4bcf2b7186592d3ad50646541b/status). This records the status API response as observed on that date, not immutable workflow logs. + +**Interpretation limit:** the accessible summaries do not show the individual test names or test output, so this audit has not verified that `stale_generation_fails_before_relay_context_is_created`, `credential_guard_does_not_shadow_inspected_endpoint_config`, or the specific reload/credential-guard tests ran. The run page itself could not be independently read in this review; attribution is based on the status checks attached to the exact commit SHA and the linked job summaries. These are CI status signals, not the audit's own execution record or an effect-side OpenShell/Sentry runtime canary. Do not mark GEN-01 through GEN-04, credential-injection runtime checks, direct-egress checks, Sentry standalone enforcement, or OpenShell+Sentry composition as PASS on this basis. Those matrix rows remain **NOT TESTED** until test-specific execution and independent protected-effect observations are recorded. + +## Follow-up source review at newer commit (not a replacement test baseline) + +A separate source-only review was performed at OpenShell `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`; see [focused RFC 0005 Phase 3 call-path audit](evidence/openshell-rfc0005-phase3-callpath-audit.md). This does not change the matrix's original execution baseline `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`. + +For the newer source review, the critical unresolved test is the relationship between the primary authorization snapshot and the separately evaluated credential guard. The guard query API returns values without a generation paired with the result; CONNECT instead relies on its captured generation guard and checks before success. Test reloads before/during the guard query and after it but before the final generation check, with an upstream canary proving whether any forbidden request or synthetic credential arrives. + +Do not report the above as an executed test. Both original-baseline tests and any tests on the newer commit require separate execution records with exact SHA, command, exit code and output. The commit's upstream CI status is supplementary evidence only; the CI status API does not identify whether these specific guard/reload tests ran. + +**Overlap resolution:** the former `BASELINE-02-03` VM row was removed as a duplicate composite. Its distinct checks are now scoped as follows: effective VM device inventory/no unexpected NIC in `VMNET-01`; VM supervisor/boundary loss in `CTL-01-V`; static and dynamic revocation in `REV-01S`/`REV-01D`; VM host/vsock access and restart behavior in `VMNET-02`. Do not count those as independent coverage twice. + +**Named stale-generation tests at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`:** there are two distinct tests, not aliases: (1) `stale_generation_fails_before_relay_context_is_created` in `crates/openshell-supervisor-network/src/proxy/relay.rs`; (2) `test_forward_relay_guard_blocks_stale_generation_before_upstream_write` in `crates/openshell-supervisor-network/src/proxy.rs`. The credential-guard regression `credential_guard_does_not_shadow_inspected_endpoint_config` in `src/opa.rs` is a third test. All three are targeted individually by the workflow below and remain `NOT TESTED` until its run produces results. + +**CI evidence scope:** run `38991707083` was checked through the GitHub Actions jobs API and downloaded job logs; the logs exposed the broad `cargo nextest run` commands and green job conclusions, but not individual passing test names. Its only listed artifact was an API/SDK compatibility-review artifact, not JUnit/Rust test results. This is not an assertion that the Actions run webpage itself was successfully rendered, and it does not prove these named tests passed. diff --git a/evidence/openshell-commit-pin-reconciliation.md b/evidence/openshell-commit-pin-reconciliation.md new file mode 100644 index 0000000..16956ac --- /dev/null +++ b/evidence/openshell-commit-pin-reconciliation.md @@ -0,0 +1,29 @@ +# OpenShell commit pin reconciliation + +## Status + +**Source-level regression evidence:** PASS at `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` (Run #12). +**Runtime-validation baseline requested by issue #6:** `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`. +**Baseline-vs-target equivalence:** NOT ESTABLISHED. +**Runtime result:** NOT TESTED. + +## Why there are two SHAs + +Issue #6 asks that runtime validation use OpenShell commit `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`, or explicitly record a reviewed newer commit. + +The existing targeted-regression workflow pins `b58e24c9dabd6d4bcf2b7186592d3ad50646541b`. Run #12 successfully checked out that exact commit and passed its three named source-level regression tests. The target commit's message is `fix(supervisor): report plaintext scheme to middleware (#4397)`; it is not, by its commit message alone, evidence that it is the right runtime baseline for every test family. + +The two commits are different. A successful run at `b58e24c` must not be represented as a runtime run at `a4c848a`, and results from one target must not silently be attributed to the other. + +## Required reconciliation before runtime results are recorded + +1. Keep Run #12 as source-level regression evidence for the exact SHA it tested. +2. Use `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317` as the initial runtime-validation baseline unless a test-specific reason to use another commit is recorded. +3. For each source-level test reused in runtime validation, verify that the test exists and has the intended semantics at the chosen SHA; record its exact test name and source path. +4. If a newer SHA is selected for a test family, record the reason, relevant changed files, and the exact claims that the newer source supports. +5. Keep test results separated by SHA. Do not combine them into one aggregate PASS. +6. Runtime validation still requires an isolated lab, synthetic credentials, a harmless canary effect, and independent effect-side observation. Unit-test success is not a substitute. + +## Current decision + +No baseline-versus-target runtime comparison has been executed in this record. The broader EABC/SLC assessment remains **INCONCLUSIVE**. GEN/REV/CTL, network alternate-path, filesystem-share, Sentry, and integrated rows remain **NOT TESTED** unless supported by their own pinned execution evidence. diff --git a/evidence/openshell-runtime-validation-template.md b/evidence/openshell-runtime-validation-template.md new file mode 100644 index 0000000..2d8312f --- /dev/null +++ b/evidence/openshell-runtime-validation-template.md @@ -0,0 +1,90 @@ +# OpenShell runtime validation — evidence template + +## Status + +**Runtime validation: NOT TESTED.** +**EABC/SLC conformance: INCONCLUSIVE.** + +This template is for a separately executed, isolated lab run. A GitHub Actions source-level regression pass is not runtime evidence and must not be copied into the results below. Do not mark any row PASS/FAIL until an actual run and effect-side observation are attached. + +## Safety and scope + +- Use an isolated lab, synthetic credentials, and harmless canary effects only. +- Do not target production services, real credentials, or real protected data. +- Pin the exact OpenShell commit. Baseline requested by issue #6: `a4c848adbddd0b4732fd70ddcf8a563a5b1e9317`; if testing another commit, record the reviewed reason and exact SHA. +- This record does not assume Sentry is present. If Sentry is in scope, identify exact BlueField model, Sentry software/firmware, deployment mode, config, and source/documentation revision before testing. + +## Run manifest — fill before execution + +| Field | Value | +| --- | --- | +| Run ID | NOT RECORDED | +| Operator | NOT RECORDED | +| Start/end UTC | NOT RECORDED | +| Host OS/kernel | NOT RECORDED | +| Hardware / driver | NOT RECORDED | +| OpenShell repository + commit | NOT RECORDED | +| OpenShell configuration hash | NOT RECORDED | +| Policy hash / generation identifier | NOT RECORDED | +| Canary endpoint / effect oracle | NOT RECORDED | +| Test harness commit | NOT RECORDED | +| Artifact hashes | NOT RECORDED | + +## Result vocabulary + +- `NOT TESTED`: no execution evidence exists. +- `PASS`: expected enforcement outcome observed **and** the effect-side oracle confirms the expected upstream effect/non-effect. +- `FAIL`: reproducible violation of the test's stated expectation, with evidence. +- `INCONCLUSIVE`: execution occurred but evidence is insufficient, contradictory, or the harness failed. + +A supervisor log by itself is not proof that the upstream effect did not occur. A harness failure is not a security-test failure. + +## Runtime matrix + +| ID | Test | Required observation | EABC mapping | Status | +| --- | --- | --- | --- | --- | +| NET-01 | Per-driver direct TCP/UDP and DNS attempts | Supervisor decision plus packet/effect-side evidence | NON_BYPASSABILITY(B,E); EBP assumptions | NOT TESTED | +| NET-02 | IPv6, ICMP, raw socket, alternate socket family, UNIX socket outside broker, rebinding, mixed A/AAAA | Each path enumerated; blocked/allowed outcome and effect-side evidence | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| GEN-01 | Stale policy generation, synchronized with a barrier | Reject decision and unchanged upstream canary counter | INTEGRITY_STATE(B,E); temporal EBP constraints | NOT TESTED | +| GEN-02 | Current valid generation control | Allow decision and exactly expected canary effect | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| GEN-03 | Policy changes between check and relay/commit | Race outcome plus effect-side record; repeat with deterministic barrier | NON_BYPASSABILITY(B,E); temporal EBP constraints | NOT TESTED | +| EVAL-01 | Missing L7 metadata vs authoritative evaluation error | Fail-closed behavior and whether canary receives protected bytes/synthetic credential | INTEGRITY_STATE(B,E); NON_BYPASSABILITY(B,E) | NOT TESTED | +| VM-01 | Read-only/read-write share boundary | Exact reads/writes and canary effect | NON_BYPASSABILITY(B,E); INTEGRITY_CTX(C,B,E) | NOT TESTED | +| VM-02 | Outside-share canary; symlink/hardlink; `..` traversal | Target inode/path and whether outside canary changed | NON_BYPASSABILITY(B,E) | NOT TESTED | +| VM-03 | Source replacement race and already-open file descriptor | Object identity before/after and observed effect | INTEGRITY_CTX(C,B,E); temporal EBP constraints | NOT TESTED | +| VM-04 | Invalid target and forced mount failure | Explicit failure mode and absence/presence of effect | NON_BYPASSABILITY(B,E) | NOT TESTED | +| SENTRY-01 | Authorization, replay/staleness, requester compromise | Version-pinned policy decision and hardware/effect-side record | NON_BYPASSABILITY(B,E); INTEGRITY_STATE(B,E) | NOT TESTED | +| SENTRY-02 | Reset/downgrade and fail-closed behavior | State across reset/downgrade and effect-side record | INTEGRITY_STATE(B,E); EXCLUSIVITY | NOT TESTED | +| COMP-01 | Integrated OpenShell + Sentry protected path | Full path enumeration, decisions, and effect-side record | NON_BYPASSABILITY(B,E); EXCLUSIVITY | NOT TESTED | +| COMP-02 | Integrated failure, policy-change, and downgrade cases | Failure injection, state transition, and effect-side record | INTEGRITY_STATE(B,E); INTEGRITY_CTX(C,B,E); EBP constraints | NOT TESTED | + +## Per-test evidence record + +Copy this section for every executed row. + +- Test ID: +- Exact command/script and version: +- Preconditions and expected result: +- OpenShell/Sentry commit and versions: +- Configuration/policy hashes: +- Start/end UTC: +- Supervisor decision/log reference: +- Network/host trace reference (if relevant): +- Canary/effect-side record before and after: +- Exit code and harness health: +- Raw artifact filenames and SHA-256: +- Actual observation: +- Result: `PASS` / `FAIL` / `INCONCLUSIVE` +- Limitations and deviations: +- EABC property mapping: +- EBP assurance constraints assessed separately: + +## Evaluation guardrails + +1. Keep source-level regression outcomes separate from runtime outcomes. +2. Do not mark GEN/REV/CTL rows PASS based solely on the three targeted source tests in Run #12. +3. An alternate-path attempt is a demonstrated bypass only if the same protected effect is observed without satisfying the required boundary conditions. +4. Failure to reproduce a bypass is not proof that every path is mediated; list the paths and coverage limits. +5. Sentry claims require a pinned device, firmware/software version, configuration, and enumerated commit paths. +6. Keep EABC semantic properties separate from EBP assurance constraints such as enforcement independence and timing/TOCTOU. +7. Overall EABC/SLC conformance remains INCONCLUSIVE until the concrete SLC implementation, substrate, configuration, deployment assumptions, and required evidence are assessed. diff --git a/evidence/openshell-targeted-regressions-run12.md b/evidence/openshell-targeted-regressions-run12.md new file mode 100644 index 0000000..74aa9da --- /dev/null +++ b/evidence/openshell-targeted-regressions-run12.md @@ -0,0 +1,59 @@ +# OpenShell targeted regression evidence — Run 12 + +## Status + +**Targeted regression result: PASS (3/3 named tests).** +**EABC/SLC conformance conclusion: INCONCLUSIVE.** + +This record captures the GitHub Actions result for the named source-level regression tests. It does not claim complete mediation, runtime non-bypassability, or EABC/SLC conformance. + +## Provenance + +- Audit repository: `omwei-org/eabc-agentrust-interoperability` +- Audit branch: `audit/openshell-sentry-2026-10` +- Audit commit used by successful run: `a530a10bcef6b0c2f588990a0dce56b62008be19` +- Target repository: `NVIDIA/OpenShell` +- Exact target commit: `b58e24c9dabd6d4bcf2b7186592d3ad50646541b` +- Workflow: [OpenShell targeted regression tests](../.github/workflows/openshell-targeted-tests.yml) +- Successful run: [GitHub Actions Run #12](https://github.com/omwei-org/eabc-agentrust-interoperability/actions/runs/39060031418) +- Artifact: `openshell-targeted-regressions-39060031418-1` +- Artifact SHA-256: `6a5d20928e9cff2a7e4e963df3797538e6b2ac8705cef20b193db531839a2fa8` +- Artifact expiry reported by GitHub: 2026-11-16T20:00:24Z + +## Per-test results + +The successful job completed the source checkout and SHA verification, Rust/tooling setup, named-test listing and execution, and evidence artifact upload. For each test, the workflow required a successful nextest exit code, a JUnit report containing exactly one testcase matching the requested name, and no JUnit failure/error or skip. + +| Named test | Result | +| --- | --- | +| `stale_generation_fails_before_relay_context_is_created` | PASS | +| `test_forward_relay_guard_blocks_stale_generation_before_upstream_write` | PASS | +| `credential_guard_does_not_shadow_inspected_endpoint_config` | PASS | + +The successful job's step list reports all steps completed with conclusion `success`, including “List and run each named regression test” and “Upload logs, metadata, test listings and JUnit results”. + +## Failed prior attempt, retained for auditability + +[Run #11](https://github.com/omwei-org/eabc-agentrust-interoperability/actions/runs/39059722272) used audit commit `1e6f820c8802393efd971c7f49d8352160c16876`, before the regex filter correction. It is classified as a **harness failure / invalid test attempt**, not a test failure. Its result must not be combined with Run #12 as a negative test finding. + +## Scope and limitations + +These are targeted source-level regression tests at the pinned OpenShell commit. They provide evidence only for the three named cases under the tested build/configuration. + +They do **not** independently establish: +- that every possible path to a protected upstream action is mediated; +- that the guard cannot be bypassed through an alternate path or separate commit authority; +- end-to-end runtime behavior against a canary upstream or equivalent external side-effect oracle; +- EABC property `NON_BYPASSABILITY`, any EBP conformance outcome, or SLC conformance. + +Accordingly, the evidence status for these three targeted tests is **PASS**, while the broader EABC/OpenShell enforcement assessment remains **INCONCLUSIVE** pending a separately designed runtime/alternate-path test. + +## Next experiment + +Design a bounded runtime test with an observable upstream side effect and explicit control cases: +1. stale generation is rejected and the upstream side-effect counter remains unchanged; +2. current/valid generation is accepted and produces the expected side effect; +3. attempt the same protected action through each identified alternate path, recording whether it reaches the upstream; +4. pin the tested OpenShell SHA, configuration, test harness, and artifact digest. + +Do not change broader `GEN-01`–`GEN-04`, `REV-01S`, or `CTL-*` findings based only on this targeted test result. diff --git a/evidence/sentry-target-public-source-inventory.md b/evidence/sentry-target-public-source-inventory.md new file mode 100644 index 0000000..751d950 --- /dev/null +++ b/evidence/sentry-target-public-source-inventory.md @@ -0,0 +1,54 @@ +# Sentry integration target — public-source inventory + +## Status + +**Target identification: PARTIAL. Runtime target pin: NOT READY.** +**Sentry runtime tests: NOT TESTED.** + +This record distinguishes public architecture claims from a reproducible implementation target. A product announcement is not a versioned Sentry test artifact. + +## Publicly stated architecture + +The NVIDIA Open Agent Safety Platform announcement and NVIDIA developer material describe: + +- OpenShell as the software runtime/sandbox boundary. +- NVIDIA Sentry as an additional out-of-band enforcement/monitoring layer associated with NVIDIA BlueField-4 DPUs. +- NVIDIA DOCA as the programmable software foundation used by Sentry. +- The intended architecture as an independent layer outside the agent/host execution domain. + +Sources checked 2026-10-18: + +1. NVIDIA Developer Blog, “NVIDIA Open Agent Safety Platform: A Reference for Continuous In-Silicon Agent Monitoring,” published 2026-09-28: https://developer.nvidia.com/blog/nvidia-open-agent-safety-platform-a-reference-for-continuous-in-silicon-agent-monitoring/ +2. NVIDIA Open Agent Safety Platform overview: https://www.nvidia.com/en-gb/solutions/ai/agent-safety/ +3. NVIDIA press release, 2026-09-28: https://nvidianews.nvidia.com/news/open-agent-safety-platform + +These sources support identifying **BlueField-4 + NVIDIA Sentry + DOCA** as the announced reference architecture. They do not, by themselves, identify a reproducible Sentry software/firmware release or expose a complete commit-path implementation for independent testing. + +## Required before SENTRY-01/02 or COMP-01/02 + +| Required field | Current evidence | Status | +| --- | --- | --- | +| BlueField hardware model/SKU and revision | Public material names BlueField-4; no physical lab device recorded | GAP | +| BlueField firmware/BSP version | No version pinned in the sources above | GAP | +| DOCA release and package versions | DOCA named; exact release/package set not pinned | GAP | +| Sentry software/source revision | Public reference-design descriptions; no exact source SHA pinned here | GAP | +| Sentry deployment mode and topology | General out-of-band architecture described; lab topology not recorded | GAP | +| Policy/configuration hashes | No lab configuration recorded | GAP | +| Protected effect and commit-path inventory | No concrete lab target/effect recorded | GAP | +| Independent effect-side oracle | Not configured or run | GAP | +| Reset/downgrade procedure and recovery evidence | Not documented for a pinned target | GAP | + +## Decision + +Do **not** mark SENTRY-01, SENTRY-02, COMP-01, or COMP-02 as PASS or FAIL. They remain **NOT TESTED** until a specific supported hardware/software target and lab setup are available and recorded. + +The next Sentry-specific action is target acquisition/identification, not a simulated test result: +1. Obtain the exact BlueField-4 device/SKU and firmware/BSP information from the intended lab. +2. Obtain the supported DOCA release and Sentry software/source revision plus its configuration/deployment documentation. +3. Identify every path that can commit the protected effect, including any host-side or alternate network path. +4. Define a harmless canary effect and an independent effect-side observation. +5. Pin all versions and hashes before running authorization, replay/staleness, reset/downgrade, and fail-closed tests. + +## EABC/EBP boundary + +The intended independent hardware layer is an architectural claim, not proof of `ENFORCEMENT_INDEPENDENCE` for a concrete deployment. Assess that EBP assurance constraint separately from EABC semantic properties. Do not infer `NON_BYPASSABILITY(B,E)`, `INTEGRITY_STATE(B,E)`, or `EXCLUSIVITY` from the product description alone.