#![cfg(feature = "fetch")]
use super::common::*;
mod blocked_hosts {
use super::*;
use std::io::{Read, Write};
use std::net::TcpListener;
use std::sync::mpsc;
fn valid_png_bytes() -> Vec<u8> {
let img = image::RgbImage::from_pixel(1, 1, image::Rgb([220, 20, 60]));
let mut buf = Vec::new();
image::DynamicImage::ImageRgb8(img)
.write_to(&mut std::io::Cursor::new(&mut buf), image::ImageFormat::Png)
.expect("encode fixture png");
buf
}
fn spawn_png_server(listener: TcpListener, tx: mpsc::Sender<()>) {
std::thread::spawn(move || {
if let Ok((mut stream, _)) = listener.accept() {
let _ = tx.send(());
let mut discard = [0u8; 1024];
let _ = stream.read(&mut discard);
let body = valid_png_bytes();
let header = format!(
"HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
body.len()
);
let _ = stream.write_all(header.as_bytes());
let _ = stream.write_all(&body);
}
});
}
fn assert_blocked(md: &str, needle: &str, conn_rx: Option<&mpsc::Receiver<()>>) {
let bytes = render(md, "");
assert!(pdf_well_formed(&bytes), "PDF not well-formed");
let wrapped = format!("[image: {needle}]");
assert!(
contains_text(&bytes, &wrapped),
"expected fallback `{wrapped}` — guard should have blocked the fetch \
(if this fails, the guard let a real image through)"
);
if let Some(rx) = conn_rx {
assert!(
rx.try_recv().is_err(),
"guard failed to block: the local PNG server observed a connection \
for `{needle}` — the fetch reached the network"
);
}
}
#[test]
fn loopback_ipv4() {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind local listener");
let port = listener.local_addr().expect("local addr").port();
let (tx, rx) = mpsc::channel();
spawn_png_server(listener, tx);
let md = format!("\n");
assert_blocked(&md, "LOOPBACK_V4", Some(&rx));
}
#[test]
fn localhost_hostname() {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind local listener");
let port = listener.local_addr().expect("local addr").port();
let (tx, rx) = mpsc::channel();
spawn_png_server(listener, tx);
let md = format!("\n");
assert_blocked(&md, "LOCALHOST", Some(&rx));
}
#[test]
fn loopback_ipv6() {
let Ok(listener) = TcpListener::bind("[::1]:0") else {
eprintln!("skipping loopback_ipv6: could not bind [::1]:0 in this environment");
return;
};
let port = listener.local_addr().expect("local addr").port();
let (tx, rx) = mpsc::channel();
spawn_png_server(listener, tx);
let md = format!("\n");
assert_blocked(&md, "LOOPBACK_V6", Some(&rx));
}
#[test]
fn cloud_metadata_address() {
assert_blocked(
"\n",
"METADATA",
None,
);
}
#[test]
fn file_scheme_is_blocked() {
assert_blocked("\n", "FILESCHEME", None);
}
}