[PM-40507] Change Password Well Known URLs Issues#8036
Conversation
🤖 Bitwarden Claude Code ReviewOverall Assessment: APPROVE Reviewed the change-password well-known URL bugfix spanning the SSRF DNS-resolution fix, the Code Review DetailsNo findings above the confidence threshold. Notes considered but not flagged:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8036 +/- ##
==========================================
+ Coverage 62.44% 62.49% +0.04%
==========================================
Files 2293 2294 +1
Lines 99829 99941 +112
Branches 9010 9017 +7
==========================================
+ Hits 62337 62454 +117
+ Misses 35319 35308 -11
- Partials 2173 2179 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
nick-livefront
left a comment
There was a problem hiding this comment.
Nice find, and solution!
jaasen-livefront
left a comment
There was a problem hiding this comment.
Looks good! Just a single failing test to fix.
It's a flaky test. There's a WIP #8041 to address it |
🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-40507
📔 Objective
The extension's
Change Passwordnotification was hanging for 30–60 seconds before timing out and falling back to the raw cipher URI, despite the target domain still exposing a valid.well-known/change-passwordendpoint. The issue reproduced only on US production (not self-host or EU cloud) and behaved inconsistently, flipping between working and broken. This PR fixes the underlying DNS-resolution regression and stops transient lookup failures from being cached as permanent "no change-password URL" answers.Root cause
The SSRF protection added in #7256 resolves DNS on every outbound probe via
Dns.GetHostEntryAsync, which also performs a reverse (PTR) lookup the SSRF check never needs, and passes no cancellation token — so a slow resolve was never bounded by the 20-secondHttpClienttimeout. Two sequential probes against a stalling resolver produced the 30–60 second hang. Because DNS/PTR resolution is environment-specific, this only manifested on US production.Two caching layers then amplified the failure into intermittent, "sticky" behavior: the controller cached the resulting transient
nullfor 24 hours, and the Icons pipeline stamped a blanket 7-day edge (Fastly)Cache-Controlheader on every response — including failures — pinning a wrong answer per-PoP for a week.What this fixes
SsrfProtectionHandlernow usesDns.GetHostAddressesAsync(forward resolution only) and threads the cancellation token through, so a stalled resolve is bounded by the request timeout. This benefits every SSRF-protected client (Icons, Webhook, Datadog, Slack, Teams, Admin).ChangePasswordUriServicenow returns a result that distinguishes a definitive answer (Found/NotSupported) from a transientLookupFailed, instead of collapsing both tonull. The controller caches only definitive answers; transient failures are not cached.Cache-Control. The controller sets its own header per result:public, max-age=1hfor definitive answers,no-storefor transient failures.📸 Screenshots
Edge-cache bug - Failed lookup is cached for 7 days
Before
After
DNS/PTR Stall
Before
After