Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

120 lines
3.8 KiB
Python

"""Escape-hatch (UNPROTECTED scope) tests — ADR-0007 stage C.
UNPROTECTED disables the egress-scope restrictions (the opt-out) but must NOT
lift the hard SSRF / cloud-metadata invariant, and must lift the forced
local-inference requirements.
"""
from __future__ import annotations
from local_deep_research.security.egress.policy import (
EgressContext,
EgressScope,
context_from_snapshot,
evaluate_engine,
evaluate_llm_endpoint,
evaluate_retriever,
evaluate_url,
)
def unprot_ctx(primary: str = "arxiv") -> EgressContext:
return EgressContext(
scope=EgressScope.UNPROTECTED,
primary_engine=primary,
require_local_llm=False,
require_local_embeddings=False,
)
def test_engine_any_allowed_under_unprotected():
# A normally-unclassified/unknown engine is permitted by the escape hatch.
d = evaluate_engine(
"some_unknown_engine", unprot_ctx(), settings_snapshot={}
)
assert d.allowed
assert d.reason == "egress_unprotected"
def test_retriever_allowed_under_unprotected():
assert evaluate_retriever("anything", unprot_ctx()).allowed
def test_url_public_allowed_under_unprotected():
assert evaluate_url("http://example.com/", unprot_ctx()).allowed
def test_metadata_ssrf_still_blocked_under_unprotected():
# The hard invariant survives the escape hatch.
d = evaluate_url("http://169.254.169.254/latest/meta-data/", unprot_ctx())
assert not d.allowed
def test_cloud_llm_allowed_under_unprotected():
# require_local_llm is False under the hatch -> cloud provider allowed.
assert evaluate_llm_endpoint(
"openai", unprot_ctx(), settings_snapshot={}
).allowed
def test_context_unprotected_lifts_local_requirements():
# Even with the require-local flags saved on, UNPROTECTED lifts them.
snap = {
"policy.egress_scope": "unprotected",
"llm.require_local_endpoint": True,
"embeddings.require_local": True,
"search.tool": "arxiv",
}
ctx = context_from_snapshot(snap, "arxiv")
assert ctx.scope is EgressScope.UNPROTECTED
assert ctx.require_local_llm is False
assert ctx.require_local_embeddings is False
def test_unprotected_warning_fires_and_is_non_dismissible():
from local_deep_research.security.egress.warnings import (
check_unprotected_egress,
)
w = check_unprotected_egress("unprotected")
assert w is not None
assert w["type"] == "egress_unprotected"
assert w["dismissKey"] is None # non-dismissible
assert check_unprotected_egress("adaptive") is None
assert check_unprotected_egress("private_only") is None
def test_trusted_destinations_warning():
from local_deep_research.security.egress.warnings import (
check_trusted_destinations,
)
assert check_trusted_destinations([], []) is None
w = check_trusted_destinations(["anthropic"], [])
assert w is not None
assert w["type"] == "egress_trusted_destinations"
assert "anthropic" in w["message"]
# tolerates the JSON-string shape a snapshot may carry
w2 = check_trusted_destinations('["openai"]', "[]")
assert w2 is not None and "openai" in w2["message"]
def test_validate_trusted_search_engines_rejects_public():
from local_deep_research.security.egress.validators import (
validate_trusted_search_engines,
)
# An inherently-public engine cannot be trusted (would launder a sink).
err = validate_trusted_search_engines(
{"policy.trusted_search_engines": ["searxng"]}, {}
)
assert err is not None and "searxng" in err["error"]
# A local-nature store / unknown name is accepted (runtime still gates).
assert (
validate_trusted_search_engines(
{"policy.trusted_search_engines": ["elasticsearch"]}, {}
)
is None
)
assert validate_trusted_search_engines({}, {}) is None