| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
|
| 14 |
|
| 15 |
|
| 16 |
use crate::harness::{HarnessOptions, TestHarness}; |
| 17 |
use axum::http::StatusCode; |
| 18 |
|
| 19 |
async fn http_preview_harness() -> TestHarness { |
| 20 |
TestHarness::with_options(HarnessOptions { |
| 21 |
link_preview_http: true, |
| 22 |
..Default::default() |
| 23 |
}) |
| 24 |
.await |
| 25 |
} |
| 26 |
|
| 27 |
#[tokio::test] |
| 28 |
async fn img_proxy_requires_login() { |
| 29 |
let mut h = http_preview_harness().await; |
| 30 |
|
| 31 |
let resp = h.client.get("/img-proxy?u=http://example.com/a.png").await; |
| 32 |
assert_eq!( |
| 33 |
resp.status, |
| 34 |
StatusCode::UNAUTHORIZED, |
| 35 |
"anonymous /img-proxy must be 401, got {}", |
| 36 |
resp.status |
| 37 |
); |
| 38 |
} |
| 39 |
|
| 40 |
#[tokio::test] |
| 41 |
async fn img_proxy_refuses_cloud_metadata_ip() { |
| 42 |
let mut h = http_preview_harness().await; |
| 43 |
h.login_as("proxyuser_meta").await; |
| 44 |
let resp = h |
| 45 |
.client |
| 46 |
.get("/img-proxy?u=http://169.254.169.254/latest/meta-data/") |
| 47 |
.await; |
| 48 |
assert_eq!( |
| 49 |
resp.status, |
| 50 |
StatusCode::BAD_GATEWAY, |
| 51 |
"link-local cloud-metadata IP must be refused (502), got {}", |
| 52 |
resp.status |
| 53 |
); |
| 54 |
} |
| 55 |
|
| 56 |
#[tokio::test] |
| 57 |
async fn img_proxy_refuses_loopback() { |
| 58 |
let mut h = http_preview_harness().await; |
| 59 |
h.login_as("proxyuser_loop").await; |
| 60 |
let resp = h.client.get("/img-proxy?u=http://127.0.0.1:1/x.png").await; |
| 61 |
assert_eq!( |
| 62 |
resp.status, |
| 63 |
StatusCode::BAD_GATEWAY, |
| 64 |
"loopback target must be refused (502), got {}", |
| 65 |
resp.status |
| 66 |
); |
| 67 |
} |
| 68 |
|
| 69 |
#[tokio::test] |
| 70 |
async fn img_proxy_refuses_rfc1918_private_ip() { |
| 71 |
let mut h = http_preview_harness().await; |
| 72 |
h.login_as("proxyuser_priv").await; |
| 73 |
let resp = h.client.get("/img-proxy?u=http://10.0.0.5/x.png").await; |
| 74 |
assert_eq!( |
| 75 |
resp.status, |
| 76 |
StatusCode::BAD_GATEWAY, |
| 77 |
"RFC1918 private IP must be refused (502), got {}", |
| 78 |
resp.status |
| 79 |
); |
| 80 |
} |
| 81 |
|
| 82 |
#[tokio::test] |
| 83 |
async fn img_proxy_refuses_non_web_port() { |
| 84 |
let mut h = http_preview_harness().await; |
| 85 |
h.login_as("proxyuser_port").await; |
| 86 |
|
| 87 |
|
| 88 |
let resp = h.client.get("/img-proxy?u=http://1.1.1.1:6379/x").await; |
| 89 |
assert_eq!( |
| 90 |
resp.status, |
| 91 |
StatusCode::BAD_GATEWAY, |
| 92 |
"non-web port must be refused (502), got {}", |
| 93 |
resp.status |
| 94 |
); |
| 95 |
} |
| 96 |
|
| 97 |
#[tokio::test] |
| 98 |
async fn img_proxy_refuses_non_http_scheme() { |
| 99 |
let mut h = http_preview_harness().await; |
| 100 |
h.login_as("proxyuser_scheme").await; |
| 101 |
let resp = h.client.get("/img-proxy?u=ftp://example.com/x.png").await; |
| 102 |
assert_eq!( |
| 103 |
resp.status, |
| 104 |
StatusCode::BAD_GATEWAY, |
| 105 |
"non-http scheme must be refused (502), got {}", |
| 106 |
resp.status |
| 107 |
); |
| 108 |
} |
| 109 |
|