Download codex-rs/cli/tests/sandbox_network_proxy.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 5.45 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/cli/tests/sandbox_network_proxy.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/cli/tests/sandbox_network_proxy.rs
-
curl -L -o sandbox_network_proxy.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/cli/tests/sandbox_network_proxy.rs
5.45 kB
| use std::net::TcpListener; | |
| use std::time::Duration; | |
| use std::time::Instant; | |
| use anyhow::Result; | |
| use tempfile::TempDir; | |
| const BWRAP_UNAVAILABLE_ERR: &str = "bubblewrap is unavailable"; | |
| fn sandbox_with_network_proxy_blocks_direct_loopback_access() -> Result<()> { | |
| let codex_home = TempDir::new()?; | |
| let listener = TcpListener::bind("127.0.0.2:0")?; | |
| let port = listener.local_addr()?.port(); | |
| std::fs::write( | |
| codex_home.path().join("config.toml"), | |
| r#" | |
| default_permissions = "network-test" | |
| [features] | |
| network_proxy = true | |
| use_legacy_landlock = true | |
| [permissions.network-test] | |
| extends = ":workspace" | |
| [permissions.network-test.network] | |
| enabled = true | |
| mode = "full" | |
| "#, | |
| )?; | |
| let url = format!("http://127.0.0.2:{port}/"); | |
| let output = std::process::Command::new(codex_utils_cargo_bin::cargo_bin("codex")?) | |
| .env("CODEX_HOME", codex_home.path()) | |
| .args([ | |
| "sandbox", | |
| "--permission-profile", | |
| "network-test", | |
| "--", | |
| "curl", | |
| "--noproxy", | |
| "*", | |
| "--silent", | |
| "--show-error", | |
| "--connect-timeout", | |
| "1", | |
| "--max-time", | |
| "2", | |
| url.as_str(), | |
| ]) | |
| .output()?; | |
| let stderr = String::from_utf8_lossy(&output.stderr); | |
| if stderr.contains(BWRAP_UNAVAILABLE_ERR) { | |
| eprintln!("skipping network proxy sandbox test: bubblewrap is unavailable"); | |
| return Ok(()); | |
| } | |
| assert_eq!( | |
| output.status.code(), | |
| Some(7), | |
| "expected direct loopback access to be blocked; status={:?}; stdout={}; stderr={}", | |
| output.status.code(), | |
| String::from_utf8_lossy(&output.stdout), | |
| stderr, | |
| ); | |
| Ok(()) | |
| } | |
| fn sandbox_with_network_proxy_allows_explicit_loopback_access() -> Result<()> { | |
| let codex_home = TempDir::new()?; | |
| let listener = TcpListener::bind("127.0.0.2:0")?; | |
| let port = listener.local_addr()?.port(); | |
| listener.set_nonblocking(true)?; | |
| let server = std::thread::spawn(move || -> std::io::Result<()> { | |
| let deadline = Instant::now() + Duration::from_secs(5); | |
| loop { | |
| match listener.accept() { | |
| Ok((mut stream, _)) => { | |
| // Closing with unread request bytes can reset the connection and yield a 502. | |
| stream.set_nonblocking(false)?; | |
| stream.set_read_timeout(Some(Duration::from_secs(5)))?; | |
| let mut request = Vec::new(); | |
| let mut buffer = [0_u8; 1024]; | |
| while !request.windows(4).any(|window| window == b"\r\n\r\n") { | |
| let bytes_read = std::io::Read::read(&mut stream, &mut buffer)?; | |
| if bytes_read == 0 || request.len() + bytes_read > 64 * 1024 { | |
| return Err(std::io::Error::other( | |
| "incomplete or oversized loopback request headers", | |
| )); | |
| } | |
| request.extend_from_slice(&buffer[..bytes_read]); | |
| } | |
| std::io::Write::write_all( | |
| &mut stream, | |
| b"HTTP/1.1 204 No Content\r\nContent-Length: 0\r\n\r\n", | |
| )?; | |
| return Ok(()); | |
| } | |
| Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { | |
| if Instant::now() >= deadline { | |
| return Err(std::io::Error::new( | |
| std::io::ErrorKind::TimedOut, | |
| "timed out waiting for allowlisted loopback request", | |
| )); | |
| } | |
| std::thread::sleep(Duration::from_millis(10)); | |
| } | |
| Err(err) => return Err(err), | |
| } | |
| } | |
| }); | |
| std::fs::write( | |
| codex_home.path().join("config.toml"), | |
| r#" | |
| default_permissions = "network-test" | |
| [features] | |
| network_proxy = true | |
| use_legacy_landlock = true | |
| [permissions.network-test] | |
| extends = ":workspace" | |
| [permissions.network-test.network] | |
| enabled = true | |
| mode = "full" | |
| allow_local_binding = false | |
| [permissions.network-test.network.domains] | |
| "127.0.0.2" = "allow" | |
| "#, | |
| )?; | |
| let url = format!("http://127.0.0.2:{port}/"); | |
| let output = std::process::Command::new(codex_utils_cargo_bin::cargo_bin("codex")?) | |
| .env("CODEX_HOME", codex_home.path()) | |
| .args([ | |
| "sandbox", | |
| "--permission-profile", | |
| "network-test", | |
| "--", | |
| "curl", | |
| "--fail", | |
| "--silent", | |
| "--show-error", | |
| "--connect-timeout", | |
| "2", | |
| "--max-time", | |
| "4", | |
| url.as_str(), | |
| ]) | |
| .output()?; | |
| let stderr = String::from_utf8_lossy(&output.stderr); | |
| if stderr.contains(BWRAP_UNAVAILABLE_ERR) { | |
| eprintln!("skipping network proxy sandbox test: bubblewrap is unavailable"); | |
| return Ok(()); | |
| } | |
| assert!( | |
| output.status.success(), | |
| "expected allowlisted loopback access to succeed; status={:?}; stdout={}; stderr={}", | |
| output.status.code(), | |
| String::from_utf8_lossy(&output.stdout), | |
| stderr, | |
| ); | |
| server.join().expect("loopback server panicked")?; | |
| Ok(()) | |
| } | |