Skip to content

HTTP/2 pseudo-header order uses a process-global env var; multiple clients clobber each other #472

Description

@barjin

🤖 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.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working.rustThis issue concerns the Rust part of this monorepo.t-toolingIssues with this label are in the ownership of the tooling team.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions