Skip to content

[PM.24380] fix: Correct and redact flight recorder hostname on logs#6633

Open
aj-rosado wants to merge 8 commits intomainfrom
PM-24380/flight-recorder-redact-hostname
Open

[PM.24380] fix: Correct and redact flight recorder hostname on logs#6633
aj-rosado wants to merge 8 commits intomainfrom
PM-24380/flight-recorder-redact-hostname

Conversation

@aj-rosado
Copy link
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-24380

📔 Objective

This aims two address different scenarios.

  1. On the network exception we are logging the cloud api when the user is self-hosted. This is caused because we are looking at the instance without the BaseUrlInterceptor having updated the url. So now we are checking on the NetworkResultCall if we should update the BaseUrl using the existing BaseUrlsProvider
  2. Replace the hostname from self-hosted instance on flight recorder logs in order to protect PII information from the logs.

@aj-rosado aj-rosado requested review from a team and david-livefront as code owners March 10, 2026 12:03
@github-actions github-actions bot added app:password-manager Bitwarden Password Manager app context app:authenticator Bitwarden Authenticator app context labels Mar 10, 2026
@codecov
Copy link

codecov bot commented Mar 10, 2026

Codecov Report

❌ Patch coverage is 75.86207% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.42%. Comparing base (417a14f) to head (4a711c8).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...in/com/bitwarden/network/core/NetworkResultCall.kt 41.66% 6 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6633      +/-   ##
==========================================
+ Coverage   85.79%   86.42%   +0.62%     
==========================================
  Files         804      789      -15     
  Lines       57205    56813     -392     
  Branches     8306     8311       +5     
==========================================
+ Hits        49081    49100      +19     
+ Misses       5242     4832     -410     
+ Partials     2882     2881       -1     
Flag Coverage Δ
app-data 17.59% <0.00%> (-0.01%) ⬇️
app-ui-auth-tools 20.79% <0.00%> (-0.01%) ⬇️
app-ui-platform 15.07% <0.00%> (-0.01%) ⬇️
app-ui-vault 25.84% <0.00%> (-0.02%) ⬇️
authenticator 6.64% <0.00%> (+0.03%) ⬆️
lib-core-network-bridge 4.32% <75.86%> (+0.05%) ⬆️
lib-data-ui 0.94% <0.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 10, 2026

Logo
Checkmarx One – Scan Summary & Detailsc7847c08-19f4-431c-87e8-ca93ef527b2a

Great job! No new security vulnerabilities introduced in this pull request

@aj-rosado aj-rosado changed the title [PM.24380] Correct and redact flight recorder hostname on logs [PM.24380] fix: Correct and redact flight recorder hostname on logs Mar 10, 2026
@aj-rosado aj-rosado added the t:bug Change Type - Bug label Mar 10, 2026
Copy link
Contributor

@SaintPatrck SaintPatrck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ I recently added logging of hostname to CookieIntercepter. Do those need to be checked/redacted also?


// Check if this is a hardcoded default URL that will be replaced by BaseUrlInterceptor
// Match against the defaults from RetrofitsImpl.kt line 111 and EnvironmentUrlDataJson
val actualHost = if (baseUrlsProvider != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a let

// Match against the defaults from RetrofitsImpl.kt line 111 and EnvironmentUrlDataJson
val actualHost = if (baseUrlsProvider != null) {
when (originalUrl.host) {
"api.bitwarden.com" -> baseUrlsProvider.getBaseApiUrl().toHttpUrlOrNull()?.host
Copy link
Collaborator

@david-livefront david-livefront Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can avoid all this complexity with an Interceptor that handles the error logging.

class NetworkErrorLogInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        return chain
            .proceed(chain.request())
            .also {
                if (!it.isSuccessful) {
                    val url = it.request.url.toUrl().run { "$protocol://$authority$path" }
                    Timber.e("Network Error: $url")
                }
            }
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 The kind of logs that are showing the wrong url are not being catched by the interceptors.
The UnknownHostException is only being returned by the enqueue's callback from Retrofit

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, that is pretty annoying. I just don't like the idea of having the baseUrlsProvider in this class, as it breaks our separation of concerns.

I'd be curious if @SaintPatrck has any thoughts about this?

Copy link
Contributor

@SaintPatrck SaintPatrck Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for not seeing this earlier.

🤔 I agree that injecting baseUrlsProvider here feels like the wrong layer. Since we're already comparing against hardcoded cloud hostnames, we could skip the provider entirely and just categorize them. If we map *.bitwarden.com → "US", *.bitwarden.eu → "EU", anything else → "SH", self-hosted hostnames never touch the log, the wrong-URL bug disappears, and the class stays clean.

Thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would resolve my worries. Unless there is a desire to get specific base urls?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-read comments on the Jira ticket and it seems like there's a desire to keep the cloud hostnames. If that's still the case, we can just check and map the self-hosted hostnames to [REDACTED] and leave the known ones alone.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial approach was to have a regex that would identify URL patterns and [REDACT] them.
This had one issue, sometimes we are throwing logs with the hostname that is similar to a namespace.
Like on UnknownHostException
java.net.UnknownHostException: Unable to resolve host "vault.qa.bitwarden.pw": No address associated with hostname

and NetworkCookieManager
2026-03-02 13:05:31:871 – DEBUG – NetworkCookieManagerImpl – getCookies(vault.qa.bitwarden.pw): resolved=vault.qa.bitwarden.pw, count=0

We can have a more specific approach to these scenarios, we might have unidentified scenarios that are leaking the hostname and we need to be aware of this on future implementations.

I am not sure if we feel that need to not redact the hostname on cloud or if it was simply a nice to have @vvolkgang

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Knowing if the actual log was a call to our servers or not will help us troubleshoot issues.

we can just check and map the self-hosted hostnames to [REDACTED] and leave the known ones alone.

works although @aj-rosado will know better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to keep the cloud domains without the BaseUrlProvide we end up with the wrong URL on the UnknownHostException, as it will always return https://api.bitwarden.com/, I am not sure if we have an alternative to get the correct url on this scenario 🤔

2026-03-04 17:39:47:781 – WARNING – NetworkResultCall – Network Error: https://api.bitwarden.com/accounts/prelogin
java.net.UnknownHostException: Unable to resolve host "vault.qa.bitwarden.pw": No address associated with hostname

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a concept of EnvironmentRegion in the app already.

enum class EnvironmentRegion {
    UNITED_STATES,
    EUROPEAN_UNION,
    INTERNAL,
    SELF_HOSTED,
}

What if we replaced the hostname with [UNITED_STATES] or [SELF_HOST]?

@aj-rosado
Copy link
Contributor Author

❓ I recently added logging of hostname to CookieIntercepter. Do those need to be checked/redacted also?

This change is redacting them, so we are fine

# Conflicts:
#	data/src/main/kotlin/com/bitwarden/data/manager/di/DataManagerModule.kt
#	data/src/main/kotlin/com/bitwarden/data/manager/flightrecorder/FlightRecorderWriterImpl.kt
Adding regex validations to HostnameRedactionUtil in order to redact names
Changing the NetworkResultCall to get the correct hostname from the Throwable's message
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:authenticator Bitwarden Authenticator app context app:password-manager Bitwarden Password Manager app context t:bug Change Type - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants