Skip to content

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

@barjin

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

No one assigned

    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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions