Skip to content

guard_wiremock's freed-port tests can hit a recycled pooled listener instead of ECONNREFUSED #115

Description

@plusky

Summary

wiremock's process-wide server pool keeps listener ports for the process lifetime, and the freed-port I12 tests bind an ephemeral port, free it, and fire requests at it expecting refusal. Under load the freed port can belong to a newly created pooled listener in the same process: ~1-4 failures per 300 stress runs. Independently reproduced by implementer and reviewer during #93.

The freed-port sites on main:

  • crates/bugwarden-core/tests/guard_wiremock.rsapi_key_absent_from_transport_error_i12 (bind at :413), whoami_api_key_absent_from_transport_error_i12 (:1141), valid_login_api_key_absent_from_transport_error_i12 (:1221); one binary, one shared pool.
  • Siblings in their own processes: crates/bugwarden/tests/preflight_wiremock.rs:269 and crates/bugwarden/tests/tools_wiremock.rs:1649.

Failure modes observed

  • unwrap_err() panicking on Ok carrying another test's corpus;
  • .expect(1) over-counting a foreign request;
  • worst, api_key_absent_from_transport_error_i12 silently not exercising I12 sanitization at all when the "refused" port answers — the test goes green without touching the invariant it exists for.

Why it matters

Two of the modes are flakes that poison unrelated tests' assertions; the third is a silent coverage loss on a security invariant (I12: the API key never appears in a transport error). #93/#112 fixed the one body-parsing victim; the hazard remains at every site above.

Suggested direction

Stop aiming real connects at recycled ephemeral ports: keep the listener bound and shut it down so the port is never returned to the OS while wiremock's pool is live, or use a reserved unroutable address.

Acceptance criteria

  • No test issues a connect to an ephemeral port that has been freed back to the OS in a process where wiremock's pool is (or may become) live — the refusal comes from a socket the test still controls, or from an address a pooled listener can never occupy.
  • Every I12 site above still produces a real transport-level error whose text is asserted free of the API key.
  • A stress run at the reproduction strength from Flaky: client_create_bug_posts_the_payload_to_rest_bug parses an empty recorded body under load #93 (≥300 iterations of the affected binaries) shows zero cross-test hits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions