WARDEN: separate fetch evaluator URL for secret-read checks (CUST-WP-0075)
check_fetch_policy now posts only to policy.fetch_flex_auth_url (access-engine pin flex-auth-ops-warden-fetch, workstation 127.0.0.1:19091). Signing keeps policy.flex_auth_url. Unset or unreachable fetch evaluator fails closed with a message naming it; no fallback to the signing pin or to allow. warden access advisory output names the fetch evaluator. Recorded under WARDEN-WP-0039-T03. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 3775@bnt-lap001 Assistant-Session: cfacb6a5-ad5b-4f79-ac67-053e3b0d34a3
This commit is contained in:
parent
30747f84c4
commit
7d4381e887
11 changed files with 292 additions and 28 deletions
|
|
@ -203,11 +203,18 @@ def _proxy_env(monkeypatch, tmp_path):
|
|||
monkeypatch.setenv("WARDEN_CONFIG", str(_warden_yaml(tmp_path)))
|
||||
|
||||
|
||||
def test_cli_proxy_unknown_zone_fail_open_reaches_transport_guard(monkeypatch, tmp_path):
|
||||
def _allow_fetch_gate(monkeypatch):
|
||||
"""Stand in for an allowing secret-read evaluator (flex-auth-ops-warden-fetch)."""
|
||||
monkeypatch.setattr(
|
||||
"warden.policy.check_fetch_policy", lambda *a, **k: "decision:test-fetch"
|
||||
)
|
||||
|
||||
|
||||
def test_cli_proxy_unset_fetch_evaluator_fails_closed(monkeypatch, tmp_path):
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller")
|
||||
# The unknown-zone profile proceeds when no evaluator is configured, then
|
||||
# the independent safe-transport boundary still refuses captured stdout.
|
||||
# No policy.fetch_flex_auth_url: the fetch is refused before any transport,
|
||||
# whatever the unknown-zone failure mode (CUST-WP-0075).
|
||||
monkeypatch.setattr(
|
||||
"warden.proxy.subprocess.run",
|
||||
lambda *a, **k: (_ for _ in ()).throw(AssertionError("fetch ran despite gate")),
|
||||
|
|
@ -217,8 +224,9 @@ def test_cli_proxy_unknown_zone_fail_open_reaches_transport_guard(monkeypatch, t
|
|||
["access", "npm", "--domain", "coulomb_social", "--field", "NPM_AUTH_TOKEN",
|
||||
"--path", "platform/x/y/z", "--fetch"],
|
||||
)
|
||||
assert r.exit_code == 6
|
||||
assert "unknown-zone fail_open" in r.output
|
||||
assert r.exit_code == 4
|
||||
assert "fetch_flex_auth_url" in r.output
|
||||
assert "fail_open applied" not in r.output
|
||||
|
||||
|
||||
def test_cli_proxy_requires_caller_auth(monkeypatch, tmp_path):
|
||||
|
|
@ -240,7 +248,10 @@ def test_cli_explicit_policy_refusal_never_fetches_or_starts_child(monkeypatch,
|
|||
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
cfg = tmp_path / "warden.yaml"
|
||||
cfg.write_text(cfg.read_text() + "policy:\n flex_auth_url: http://pdp.test\n")
|
||||
cfg.write_text(
|
||||
cfg.read_text()
|
||||
+ "policy:\n flex_auth_url: http://sign.test\n fetch_flex_auth_url: http://pdp.test\n"
|
||||
)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller-test-value")
|
||||
monkeypatch.setattr(
|
||||
"warden.policy.httpx.post",
|
||||
|
|
@ -634,6 +645,7 @@ def test_build_wrapped_fetch_refuses_placeholder_path():
|
|||
def test_access_fetch_to_nonterminal_stdout_is_refused(tmp_path, monkeypatch):
|
||||
"""The anti-pattern: streaming a value to captured stdout is refused (exit 6)."""
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
_allow_fetch_gate(monkeypatch)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller-token") # G1 caller-auth precheck
|
||||
# The guard trips before the fetch runs; make a real bao call fail loudly if reached.
|
||||
monkeypatch.setattr(
|
||||
|
|
@ -649,6 +661,7 @@ def test_access_fetch_to_nonterminal_stdout_is_refused(tmp_path, monkeypatch):
|
|||
def test_access_fingerprint_masks_and_bypasses_stdout_guard(monkeypatch, tmp_path):
|
||||
"""--fingerprint prints a masked fingerprint (never the value) even to captured stdout."""
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
_allow_fetch_gate(monkeypatch)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller-token")
|
||||
|
||||
class _Fake:
|
||||
|
|
@ -668,6 +681,7 @@ def test_access_fingerprint_masks_and_bypasses_stdout_guard(monkeypatch, tmp_pat
|
|||
def test_access_agent_high_risk_raw_stream_refused(tmp_path, monkeypatch):
|
||||
"""WP-0026 T04: WARDEN_AGENT_ID + risk=high refuses raw value stream (exit 7)."""
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
_allow_fetch_gate(monkeypatch)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller-token")
|
||||
monkeypatch.setenv("WARDEN_AGENT_ID", "grok")
|
||||
# Prefer high-risk lane; use --unsafe-stdout so T02 would allow if T04 failed.
|
||||
|
|
@ -687,6 +701,7 @@ def test_access_issued_agent_subject_refuses_raw_stream_without_legacy_marker(
|
|||
):
|
||||
"""WP-0034 T02: the issued KeyCape subject is sufficient for exit 7."""
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
_allow_fetch_gate(monkeypatch)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller-token")
|
||||
monkeypatch.delenv("WARDEN_AGENT_ID", raising=False)
|
||||
monkeypatch.setenv(
|
||||
|
|
@ -706,6 +721,7 @@ def test_access_issued_agent_subject_refuses_raw_stream_without_legacy_marker(
|
|||
def test_access_agent_high_risk_fingerprint_allowed(tmp_path, monkeypatch):
|
||||
"""Agents may use --fingerprint on high-risk lanes (no raw value)."""
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
_allow_fetch_gate(monkeypatch)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller-token")
|
||||
monkeypatch.setenv("WARDEN_AGENT_ID", "grok")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue