scopegate is a fail-closed network scope gate for AI agents and tools. Given a
policy of allowed schemes, exact hosts, domains, CIDRs, and subdomain handling,
it decides whether an outbound target is in scope. The default answer is DENY.
It is intentionally small and network-free: it does not scan, probe, resolve DNS, or enforce egress. It canonicalizes the target, evaluates policy, and returns an auditable ALLOW or DENY decision before a tool opens a socket.
An AI agent with tool or network access can be prompt-injected into contacting
targets outside its intended engagement scope, including internal services,
metadata endpoints, or attacker-controlled lookalikes. A scope gate is useful
only if it interprets targets at least as strictly as the networking stack that
will later connect to them; otherwise parse differentials become scope escapes.
scopegate is built for that pre-flight authorization boundary. It is not a
container, firewall, DNS policy engine, or sandbox.
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
scopegate check http://127.0.0.1:8080 --policy examples/lab-policy.json
scopegate check https://api.example.test --policy examples/lab-policy.json --jsonExample policy:
{
"allowed_schemes": ["http", "https"],
"allowed_hosts": ["example.test"],
"allowed_domains": ["example.test"],
"allowed_cidrs": ["127.0.0.0/8", "10.10.0.0/16"],
"allow_subdomains": true
}CLI exit codes are 0 for ALLOW and 2 for DENY.
- Fail closed: malformed targets and canonicalization failures return DENY instead of raising through the policy boundary.
- Canonicalize before policy: hosts are lowercased, IDNA-normalized, trailing dots are removed, and URL userinfo is rejected.
- Compare CIDRs against canonical IPs, including loose IPv4 forms accepted by
libc. This blocks a real parse-differential escape such as
http://10.10, which a naive gate may read as10.10.0.0while libc resolves it as10.0.0.10, outside an allowed10.10.0.0/16. - Deny target-smuggling patterns such as suffix lookalikes
(
example.test.evil.test), unsupported schemes, missing hosts, and private IPs that are not explicitly covered by an allowed CIDR. - Ship an adversarial regression corpus for malformed URLs, integer and short IPv4 forms, userinfo smuggling, invalid ports, and scope boundary cases.
Install the dev dependency and run the pytest suite:
pip install -e ".[dev]"
PYTHONPATH=src python3 -m pytest -q