* fix(ci): preserve Windows Rust build cache Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): invalidate empty Windows caches Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * perf(ci): cache Windows builds with sccache Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): restore target directory caching Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * perf(ci): use prebuilt Z3 on Windows Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * perf(ci): layer sccache on Windows target cache Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): split PR checks from main validation Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): separate checks builds and cache seeding Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): simplify Windows build dependency Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): rely on Windows job dependency status Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): use valid opt-in Windows ARM runner Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): keep ARM64 validation local Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): install Clippy for Windows validation Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): focus platform lint coverage Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(licenses): explain bzip2 allowance Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): simplify workflow name Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(windows): allow async platform stub Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(network): make file fingerprints portable Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): lint supported deliverables Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): allow platform-gated lint Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * chore(ci): align Windows cache action with main Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): align Windows validation with prerequisites Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): pin Rust toolchain action Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): use enterprise-approved Windows actions Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(windows): restore strict MSVC validation Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): run Rust tests with nextest Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): normalize nextest lock provenance Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): add native arm64 validation Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): lock nextest for Windows ARM64 Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(windows): resolve duplicate MXC authentication method Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * test(conformance): use native absolute paths on Windows Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(windows): address MSVC review feedback Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): simplify cache key names Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): isolate Windows Rust toolchains for stable caches Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(ci): configure Rustup home in runner setup Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): surface sccache server write diagnostics Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): remove temporary cache diagnostics Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * ci(windows): address review feedback Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(windows): reconcile merged driver capabilities Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(deps): preserve AWS-LC-only lockfile Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * chore(deps): allow z3 prebuilt TLS wrapper Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> --------- Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
openshell-prover
Formal verifier for OpenShell sandbox policies. Encodes a policy + its attached credential set + a binary capability registry as a Z3 SMT model, then runs reachability queries to detect credentialed-reach and capability changes a reviewer should be aware of.
Used by the gateway to gate auto-approval of agent-authored policy
proposals: any finding blocks auto-approval, an empty delta lets the
chunk pass through (when the reviewer opts in via the
proposal_approval_mode setting at either gateway or sandbox scope).
What it decides
The prover answers four formal questions. Each "yes" answer is its own
categorical finding — there is no severity grade. The categories live
in finding::category.
| Category | Question the prover decides |
|---|---|
link_local_reach |
Does this policy grant reach to a host in 169.254.0.0/16 or fe80::/10? |
l7_bypass_credentialed |
Does it let a binary using a non-HTTP wire protocol (per the binary registry's bypasses_l7 flag) reach a host where a credential is in scope? |
credential_reach_expansion |
Does it let a binary reach a (host, port) with a credential in scope, where the binary couldn't reach that endpoint before? |
capability_expansion |
On a (binary, host, port) the binary already reaches with credentials, does it add a new HTTP method? |
The first two are unconditional risks. The latter two are delta properties — the gateway runs the prover on both the baseline policy and the merged policy and surfaces only the new paths.
Evidence shape
Each finding carries one or more FindingPath::Exfil
entries:
pub struct ExfilPath {
pub binary: String,
pub endpoint_host: String,
pub endpoint_port: u16,
pub mechanism: String, // human-readable description
pub policy_name: String, // rule the path traverses
pub category: String, // one of the category constants
pub method: String, // populated for capability_expansion; empty otherwise
}
The gateway's finding_delta keys paths by (category, binary, host:port, category, method) so that adding a new method on an
already-reached host surfaces as exactly one new path (not the whole
re-emission of the existing method set).
Category suppression at the delta layer
capability_expansion paths whose (binary, host, port) tuple is also
in the credential_reach_expansion delta are suppressed by the
gateway. A brand-new credentialed reach is described by the
reach-expansion finding alone, not also by N per-method findings.
Adding a new category
- Add a constant to
src/finding.rs::category. - In
src/queries.rs::check_credential_safety, add the branch that detects the new category and emits oneExfilPathper evidence row. Setpath.categoryto the new constant. - In
src/report.rs::format_path_line, add amatcharm rendering the per-path display string the reviewer sees. - (Gateway) If the new category should be suppressed by another, add
the suppression rule to
crates/openshell-server/src/grpc/policy.rs::finding_delta. - Add a unit test in
src/queries.rsand an integration test incrates/openshell-server/src/grpc/policy.rs::tests.
The four v1 categories cover the formal properties the OpenShell auto-approval gate cares about today. Additional categories (e.g., "destructive method introduced," "new outbound TLS without SNI") would be additive — they don't displace existing categories.
What the prover does not decide
- Semantic risk of an action. The prover models can the binary do
this?, not is this destructive?.
PUT /repos/.../contents/file.mdandGET /repos/.../contents/file.mdare both authenticated actions; the reviewer (or a downstream layer like an LLM contextual reviewer or an intent file) decides if the action is desired. - Cross-sandbox or cross-binary intent. The model is per-sandbox. If two sandboxes share a credential through external policy, the prover reasons about each independently.
- Runtime behavior. The prover analyzes the policy as written; it doesn't observe the proxy's actual decisions. The proxy is the enforcement layer; the prover is the change-review layer.
Inputs
- Policy — a
SandboxPolicyproto, parsed viaopenshell-policy::parse_sandbox_policy. - Credential set — built from the sandbox's attached providers in
crates/openshell-server/src/grpc/policy.rs::build_credential_set_for_sandbox. v1 captures presence only (host-coarse); no scope modeling. - Binary registry — YAML descriptors at
crates/openshell-prover/registry/binaries/*.yaml. Each describes the binary's protocols,bypasses_l7flag, andcan_exfiltratecapability.
Outputs
- A list of
Findingvalues, one per fired category. Each finding'squeryfield holds the category name. - The CLI renderer (
report::render_compact/render_report) prints human-readable output for theopenshell-proverbinary. - The gateway calls
report::finding_shorthandto build thevalidation_resultstring persisted on each draft chunk.
Z3 model layout
See src/model.rs. Briefly:
- Bool sorts per
(binary, endpoint)pair encode policy reachability, filtered by binary capability flags (can_exfiltrate,bypasses_l7). - Bool sorts per
(binary, host)encode credential-in-scope (one credential set per sandbox). - The reachability formula composes these into the SAT query the
queries::check_credential_safetyloop iterates over.
Tests
- Unit tests in each module (
src/queries.rs,src/report.rs,src/policy.rs) cover individual primitives and category emission. - Integration tests in
src/lib.rs::testsexercise the full parse → build_model → run_all_queries pipeline against testdata policies intestdata/. - Gateway-level acceptance tests in
crates/openshell-server/src/grpc/policy.rs::testslock in the end-to-endvalidation_resultshape and the auto-approval gate.