Skip to content

[PM-41325] feat: Add custom header support for self-hosted environments - #2925

Open
jalenfran wants to merge 2 commits into
bitwarden:mainfrom
jalenfran:feat/self-hosted-custom-headers
Open

[PM-41325] feat: Add custom header support for self-hosted environments#2925
jalenfran wants to merge 2 commits into
bitwarden:mainfrom
jalenfran:feat/self-hosted-custom-headers

Conversation

@jalenfran

Copy link
Copy Markdown
Contributor

🎟️ Tracking

Community feature request: Allow custom header for the Bitwarden app (Android, iOS)

📔 Objective

Allow users to configure custom HTTP headers on the pre-auth Self-Hosted environment screen,
applied to every request sent to the environment's hosts. This supports self-hosted deployments
behind reverse proxies that gate access on a header — most commonly Cloudflare Access
(CF-Access-Client-Id / CF-Access-Client-Secret) — as a lighter-weight alternative to mTLS.

The implementation deliberately mirrors the existing mTLS client-certificate feature:

  • Storage: header name/value pairs are credentials, so they are stored in the iOS Keychain
    (AfterFirstUnlockThisDeviceOnly). Only an opaque UUID identifier is persisted in
    EnvironmentURLData, exactly like the certificate fingerprint. The identifier is shared across
    accounts pointing at the same environment, with reference-counted Keychain cleanup.
  • Injection: a new CustomHeadersRequestHandler runs in the HTTPServiceBuilder chain.
    It is host-scoped: headers are only attached when the request host matches one of the
    environment's hosts, so credentials are never sent to third parties (e.g. HIBP).
  • Icons: CipherIconImageLoader bypasses HTTPService, so it attaches the headers itself —
    the same dual-path treatment mTLS required.
  • UI: a "Custom headers" section on the Self-Hosted screen with add/remove name–value rows;
    values are masked with a reveal toggle like other credential fields.

The second commit fixes three pre-existing credential-hygiene patterns shared with mTLS,
found while auditing the feature:

  • Switching from a self-hosted environment to a built-in region now removes Keychain
    credentials (client certificate identity and custom headers) whose pre-auth references were
    dropped, instead of orphaning them.
  • deleteAccount now cleans up the account's client certificate and custom headers,
    matching logout.
  • OSLogHTTPLogger now redacts the values of headers not on a known-safe allow-list, so
    authorization tokens, cookies, and user-configured custom headers no longer reach the
    unified log verbatim.

📸 Screenshots

Custom headers section on the Self-Hosted environment screen:

Value revealed Value masked (default)
Self-hosted settings with a custom header value shown in plain text Self-hosted settings with the custom header value masked

Allow configuring custom HTTP headers on the pre-auth self-hosted
environment screen, applied to every request sent to the environment's
hosts. Supports reverse proxies that gate access on a header, such as
Cloudflare Access.

- Store header values in the Keychain; only an opaque identifier is
  persisted in EnvironmentURLData, mirroring the mTLS fingerprint
- Inject headers via a request handler in the HTTPServiceBuilder chain,
  scoped to environment hosts so credentials never reach third parties
- Apply headers to icon requests in CipherIconImageLoader, which
  bypasses the HTTPService pipeline
- Reference-count Keychain cleanup across accounts and on logout
…alues

Fixes three credential-hygiene gaps shared by the mTLS client certificate
and custom headers features:

- Selecting a built-in region now removes Keychain credentials (client
  certificate identity, custom headers) whose pre-auth references were
  dropped by replacing the self-hosted environment URLs, instead of
  orphaning them. Removal is reference-counted, so credentials still
  used by an account remain.
- Account deletion now cleans up the account's client certificate and
  custom headers, matching logout. Cleanup failures are logged without
  blocking local account removal, since the server-side deletion has
  already succeeded.
- OSLogHTTPLogger now redacts the values of headers not on a known-safe
  allow-list, so authorization tokens, cookies, and user-configured
  custom headers no longer reach the unified log verbatim.
@jalenfran
jalenfran requested review from a team and matt-livefront as code owners August 1, 2026 00:55
@bitwarden-bot

Copy link
Copy Markdown
Collaborator

Thank you for your contribution! We've added this to our internal tracking system for review.
ID: PM-41325
Link: https://bitwarden.atlassian.net/browse/PM-41325

Details on our contribution process can be found here: https://contributing.bitwarden.com/contributing/pull-requests/community-pr-process.

@bitwarden-bot bitwarden-bot changed the title Feat/self hosted custom headers [PM-41325] Feat/self hosted custom headers Aug 1, 2026
@jalenfran jalenfran changed the title [PM-41325] Feat/self hosted custom headers [PM-41325] feat: Add custom header support for self-hosted environments Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants