Skip to content

[PM-30751] - add secure SSRF protection for internal IPs#7184

Open
jaasen-livefront wants to merge 1 commit intomainfrom
PM-30751
Open

[PM-30751] - add secure SSRF protection for internal IPs#7184
jaasen-livefront wants to merge 1 commit intomainfrom
PM-30751

Conversation

@jaasen-livefront
Copy link
Collaborator

🎟️ Tracking

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

📔 Objective

Adds centralized SSRF (Server-Side Request Forgery) protection to prevent server-initiated HTTP requests from reaching internal/private/reserved IP ranges when the destination URL is derived from external input.

Problem

SSRF protection logic existed only in the Icons project (IPAddressExtension), and did not cover CGNAT ranges (RFC 6598). Multiple other HTTP clients accepting user-supplied or admin-configured URLs had no IP validation at all.

Solution

Shared IP validation — Moved IsInternal() logic from Icons into Core/Utilities/IPAddressExtensions.cs so all projects can use it. Added CGNAT blocking (100.64.0.0/10).

SsrfProtectionHandler — A DelegatingHandler that:

  • Resolves DNS before connecting (closes the gap where redirects could bypass IP checks)
  • Validates all resolved addresses against the internal IP blocklist
  • Blocks with SsrfProtectionException if any resolved IP is internal
  • Rewrites the request URI to the validated IP while preserving the Host header for TLS SNI

One-line opt-inIHttpClientBuilder.AddSsrfProtection() extension method to wire the handler into any named HttpClient.

Protected clients

Client Risk Reason
ChangePasswordUriService Highest User-supplied domain
WebhookIntegrationHandler High Admin-configured URL
DatadogIntegrationHandler High Admin-configured URL
SlackService Medium Integration URLs
TeamsService Medium Integration URLs
Icons (fetch + redirect) Existing Now uses shared code + CGNAT fix

Out-of-scope clients (server-configured URLs not from external input): BaseIdentityClientService, SSOController, NotificationHubPushRegistrationService, AliveJob, HomeController.

Changes

  • New: src/Core/Utilities/IPAddressExtensions.cs — shared IP blocklist with CGNAT
  • New: src/Core/Utilities/SsrfProtectionHandler.cs — DNS-resolving delegating handler
  • New: src/Core/Utilities/HttpClientBuilderSsrfExtensions.cs.AddSsrfProtection() extension
  • Modified: src/Icons/Util/IPAddressExtension.cs — delegates to shared Core implementation
  • Modified: src/Icons/Util/ServiceCollectionExtension.cs — adds SSRF protection to Icons/ChangePasswordUri clients
  • Modified: src/Core/Dirt/EventIntegrations/EventIntegrationsServiceCollectionExtensions.cs — adds SSRF protection to Webhook, Datadog, Slack, Teams clients
  • New: test/Core.Test/Utilities/IPAddressExtensionsTests.cs — 30 test cases covering all IP ranges + CGNAT boundaries
  • New: test/Core.Test/Utilities/SsrfProtectionHandlerTests.cs — 21 test cases for handler behavior

Future usage

Any new HTTP client that accepts external input can opt in with:

services.AddHttpClient("MyClient").AddSsrfProtection();

📸 Screenshots

@jaasen-livefront jaasen-livefront requested a review from a team as a code owner March 9, 2026 18:50
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 9, 2026

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

Logo
Checkmarx One – Scan Summary & Details1e42024b-345e-4aed-83d9-0fc2af38006c

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

@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 82.41758% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.10%. Comparing base (4732d7f) to head (4f2d472).

Files with missing lines Patch % Lines
src/Core/Utilities/SsrfProtectionHandler.cs 74.07% 8 Missing and 6 partials ⚠️
src/Core/Utilities/IPAddressExtensions.cs 92.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7184      +/-   ##
==========================================
+ Coverage   57.08%   57.10%   +0.02%     
==========================================
  Files        2028     2031       +3     
  Lines       88794    88855      +61     
  Branches     7914     7925      +11     
==========================================
+ Hits        50684    50741      +57     
  Misses      36279    36279              
- Partials     1831     1835       +4     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant