Appearance
Python
Validate Python network behavior under the Secure Sandbox.
Objectives
- Enforce deny-by-default egress and designated proxy routing across Python HTTP stacks and raw sockets.
- Prove localhost/loopback isolation and failure of proxy-bypass tactics.
- Validate IPv6 parity, DNS-over-HTTPS evasion, WebSocket/gRPC/raw sockets denial.
- Demonstrate inbound isolation: the host cannot reach services started inside the sandbox.
Preconditions
- Windows target with Turbo Launcher and Secure Sandbox.
- Python 3.11+ available in the sandbox (any recent Python 3.x is acceptable).
- Optional libraries inside the sandbox (when scenarios reference them):
requests,aiohttp,websockets,grpcio,urllib3, andrequests[socks]if testing SOCKS proxies.
Controls Under Test
runtime.networking.egressDefaultAction(deny by default)- Designated proxy enforcement and env-var bypass resistance (
proxyEnforced,HTTP(S)_PROXY,NO_PROXY, clienttrust_envsettings) - TLS certificate pinning and SNI checks (no interception with wrong CA)
- Protocol gating:
alpn(e.g., QUIC/HTTP3), CONNECT-to-non-proxy denial - Loopback and inbound isolation between Sandbox and host
- Required audit fields:
action,reason,proxyEnforced,alpn/protocol,ipVersion,rule.id,integrity.hash
Test Scenarios
| ID | Canonical ID | Scenario | Procedure | Expected Outcome |
|---|---|---|---|---|
| SCEN-TOOL-PYTHON-01 | NET-ISOLATE-01 | Loopback isolation | python -c "import socket; s=socket.socket(); s.settimeout(5); s.connect(('127.0.0.1', 80))" | Denied/refused; host loopback unreachable from sandbox. Audit: action: deny. |
| SCEN-TOOL-PYTHON-02 | NET-ISOLATE-02 | Inbound isolation (Host→Sandbox) | In sandbox: python -m http.server 8080 --bind 0.0.0.0.From host: curl http://<sandbox-ip>:8080 | Connection fails (timeout/refused). No inbound exposure. |
| SCEN-TOOL-PYTHON-03 | NET-EGRESS-01 | Direct IP egress | python -c "import requests; requests.get('http://1.1.1.1', timeout=5)" | Denied per default-deny. Audit: action: deny. |
| SCEN-TOOL-PYTHON-04 | NET-EGRESS-05 | Env proxy vars (unauthorized) | set HTTPS_PROXY=http://127.0.0.1:8080 && python -c "import requests; requests.get('https://example.com', timeout=5)" | Denied; reason: unauthorizedProxy, proxyEnforced: true. |
| SCEN-TOOL-PYTHON-05 | NET-EGRESS-06 | NO_PROXY bypass attempt | set NO_PROXY=* && python -c "import requests; requests.get('https://example.com', timeout=5)" | Denied; reason: proxyBypassAttempt, proxyEnforced: true. |
| SCEN-TOOL-PYTHON-06 | NET-EGRESS-07 | Client bypass (disable trust_env) | python -c "import requests; s=requests.Session(); s.trust_env=False; s.get('https://example.com', timeout=5)" | Denied; bypass refused at sandbox boundary. |
| SCEN-TOOL-PYTHON-07 | NET-EGRESS-09 | Proxy outage (fail-closed) | Take the designated proxy down; then requests.get('https://example.com'). | Denied; no direct fallback. Audit: reason: proxyUnavailable. |
| SCEN-TOOL-PYTHON-08 | NET-EGRESS-10 | Proxy TLS pinning/identity | Intercept proxy TLS with wrong CA; requests.get('https://example.com'). | Denied. Audit: reason: certMismatch or pinningFailed. |
| SCEN-TOOL-PYTHON-09 | NET-EGRESS-11 | IPv6 direct egress | python -c "import requests; requests.get('https://[2606:4700:4700::1111]/', timeout=5)" | Denied unless explicitly allowed; ipVersion: 6. |
| SCEN-TOOL-PYTHON-10 | NET-EGRESS-12 | CONNECT to non-proxy | python -c "import urllib3; pm=urllib3.ProxyManager('https://nonproxy.example:443'); pm.request('GET','https://target.example')" | Denied. Audit: reason: destNotProxy. |
| SCEN-TOOL-PYTHON-11 | NET-EGRESS-13 | Raw TCP socket | python -c "import socket; s=socket.socket(); s.settimeout(5); s.connect(('1.1.1.1',443))" | Denied by namespace/firewall. |
| SCEN-TOOL-PYTHON-12 | NET-EGRESS-05 | Stdlib urllib bypass | python -c "import urllib.request as u; u.build_opener(u.ProxyHandler({})).open('https://example.com', timeout=5)" | Denied; bypass refused. |
| SCEN-TOOL-PYTHON-13 | NET-EGRESS-07 | aiohttp trust_env bypass attempt | python -c "import asyncio,aiohttp; async def r():\n async with aiohttp.ClientSession(trust_env=False) as s: await s.get('https://example.com', timeout=5);\n asyncio.run(r())" | Denied; proxy enforced at boundary. |
| SCEN-TOOL-PYTHON-14 | NET-PROTO-07 | websockets WSS | python -c "import asyncio,websockets; async def r():\n async with websockets.connect('wss://echo.websocket.events') as ws: await ws.send('x'); await ws.recv()\n asyncio.run(r())" | Denied (no UDP/QUIC/WS bypass). |
| SCEN-TOOL-PYTHON-15 | NET-PROTO-07 | gRPC over TLS | Create grpc.insecure_channel('public.host:443') and call a stub. | Denied; direct tunnels not allowed. |
| SCEN-TOOL-PYTHON-16 | NET-EGRESS-05 | Loopback proxy attempt | set HTTPS_PROXY=http://127.0.0.1:8888 && python -c "import requests; requests.get('https://example.com', timeout=5)" | Denied unless loopback proxy is designated (should not be). |
| SCEN-TOOL-PYTHON-17 | NET-EGRESS-07 | aiohttp trust_env bypass attempt | python -c "import asyncio,aiohttp; async def r():\n async with aiohttp.ClientSession(trust_env=False) as s: await s.get('https://example.com', timeout=5);\n asyncio.run(r())" | Denied; proxy enforced at boundary. |
| SCEN-TOOL-PYTHON-18 | NET-PROTO-07 | websockets WSS | python -c "import asyncio,websockets; async def r():\n async with websockets.connect('wss://echo.websocket.events') as ws: await ws.send('x'); await ws.recv()\n asyncio.run(r())" | Denied (no UDP/QUIC/WS bypass). |
| SCEN-TOOL-PYTHON-19 | NET-PROTO-07 / NET-EGRESS-13 | gRPC over TLS | Create grpc.insecure_channel('public.host:443') and call a stub. | Denied; direct tunnels not allowed. |
| SCEN-TOOL-PYTHON-20 | NET-EGRESS-05 | Loopback proxy attempt | set HTTPS_PROXY=http://127.0.0.1:8888 && python -c "import requests; requests.get('https://example.com', timeout=5)" | Denied unless that loopback proxy is designated by policy (should not be). |
Representative Python Snippets
Direct IP (requests):
python
import requests
requests.get('http://1.1.1.1', timeout=5)NO_PROXY bypass attempt:
python
import os, requests
os.environ['NO_PROXY'] = '*'
requests.get('https://example.com', timeout=5)Raw IPv4 and IPv6 sockets:
python
import socket
s4 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s4.settimeout(5)
s4.connect(('1.1.1.1', 443))
s6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s6.settimeout(5)
s6.connect(('2606:4700:4700::1111', 443, 0, 0))aiohttp trust_env bypass attempt:
python
import asyncio, aiohttp
async def run():
async with aiohttp.ClientSession(trust_env=False) as session:
async with session.get('https://example.com', timeout=5) as resp:
print(resp.status)
asyncio.run(run())Evidence Requirements
- Audit category:
network. - Required fields:
action,reason(for example,unauthorizedProxy,proxyBypassAttempt,destNotProxy,proxyUnavailable,certMismatch/pinningFailed),proxyEnforced,protocol/alpn,ipVersion. - For isolation attempts, include
scope: internalwhen applicable.
Troubleshooting
- Some libraries cache connection pools; run attempts twice if the first try hits DNS cache or connection reuse.
- Ensure environment variables (for example,
HTTP_PROXY,HTTPS_PROXY,NO_PROXY) do not mislead manual testing—policy must enforce the proxy regardless of client settings. - If optional libraries are not present, focus on stdlib (
urllib.request,socket) andrequestsscenarios.
