🤖 Found by Claude ultrareview — automated high-effort code review. Please verify independently before acting.
Location: impit/src/impit.rs:343 (Impit::new)
The HTTP/2 pseudo-header order is published through a process-global environment variable:
if !pseudo_headers_order.is_empty() {
std::env::set_var(
"IMPIT_H2_PSEUDOHEADERS_ORDER",
pseudo_headers_order.join(","),
);
}
The forked h2 layer reads this variable at connection time.
Impact:
- Last-writer-wins across clients. Constructing two
Impit instances with different fingerprints in one process (e.g. a Chrome client and a Firefox client) makes both emit whichever pseudo-header order was set last. The first client's HTTP/2 fingerprint is silently wrong — defeating the impersonation the library exists to provide.
- Data race.
std::env::set_var is process-global and not synchronized with concurrent getenv; building clients concurrently on multiple threads is a race (and set_var is unsafe in the Rust 2024 edition for exactly this reason).
Suggested direction: thread the pseudo-header order through the reqwest/h2 client config at build time as per-client state, instead of via a shared environment variable.
Location:
impit/src/impit.rs:343(Impit::new)The HTTP/2 pseudo-header order is published through a process-global environment variable:
The forked h2 layer reads this variable at connection time.
Impact:
Impitinstances with different fingerprints in one process (e.g. a Chrome client and a Firefox client) makes both emit whichever pseudo-header order was set last. The first client's HTTP/2 fingerprint is silently wrong — defeating the impersonation the library exists to provide.std::env::set_varis process-global and not synchronized with concurrentgetenv; building clients concurrently on multiple threads is a race (andset_varisunsafein the Rust 2024 edition for exactly this reason).Suggested direction: thread the pseudo-header order through the reqwest/h2 client config at build time as per-client state, instead of via a shared environment variable.