Skip to content

Conversation

@JPeer264
Copy link
Member

closes FE-681

It seems that in some cases the headers do have a different casing. E.g. in Cloudflare Workers the [CF-Connecting-IP](https://developers.cloudflare.com/fundamentals/reference/http-headers/#cf-connecting-ip) is actually send as Cf-Connecting-Ip.

Screenshot 2026-01-19 at 13 15 27

According to RFC7540 8.1.2 the headers are case-insensitive, but for HTTP2 they must be lowercase. So theoretically this would fix also HTTP2 lower case headers

@JPeer264 JPeer264 self-assigned this Jan 19, 2026
@linear
Copy link

linear bot commented Jan 19, 2026

Comment on lines +59 to 69
for (const key of Object.keys(headers)) {
lowerCaseHeaders[key.toLowerCase()] = headers[key];
}

// This will end up being Array<string | string[] | undefined | null> because of the various possible values a header
// can take
const headerValues = ipHeaderNames.map((headerName: string) => {
const rawValue = headers[headerName];
const rawValue = lowerCaseHeaders[headerName.toLowerCase()];
const value = Array.isArray(rawValue) ? rawValue.join(';') : rawValue;

if (headerName === 'Forwarded') {
Copy link

Choose a reason for hiding this comment

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

Bug: The new case-insensitive IP header reading is not matched by the deletion logic, which remains case-sensitive, potentially leaking IP headers when PII stripping is enabled.
Severity: CRITICAL

Suggested Fix

Modify the header deletion logic in extractNormalizedRequestData() to be case-insensitive. This can be achieved by iterating over the actual request headers, converting each to lowercase, and checking if it exists in a pre-computed set of lowercase IP header names before deletion. This ensures symmetry between reading and removing IP-related headers.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: packages/core/src/vendor/getIpAddress.ts#L52-L69

Potential issue: The pull request updates `getClientIPAddress()` to read IP-related
headers in a case-insensitive manner. However, the corresponding logic in
`extractNormalizedRequestData()` for removing these headers when `sendDefaultPii` is
`false` remains case-sensitive. It iterates through `ipHeaderNames` and performs an
exact-match deletion. This creates a situation where a header like `Cf-Connecting-Ip`
will be correctly identified as containing an IP address but will not be deleted if PII
stripping is enabled. This results in the unintended leakage of IP address information
in events.

Did we get this right? 👍 / 👎 to inform future reviews.

@github-actions
Copy link
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 25.11 kB - -
@sentry/browser - with treeshaking flags 23.61 kB - -
@sentry/browser (incl. Tracing) 41.87 kB - -
@sentry/browser (incl. Tracing, Profiling) 46.45 kB - -
@sentry/browser (incl. Tracing, Replay) 80.47 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 70.16 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 85.17 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 97.37 kB - -
@sentry/browser (incl. Feedback) 41.83 kB - -
@sentry/browser (incl. sendFeedback) 29.79 kB - -
@sentry/browser (incl. FeedbackAsync) 34.79 kB - -
@sentry/browser (incl. Metrics) 26.21 kB - -
@sentry/browser (incl. Logs) 26.37 kB - -
@sentry/browser (incl. Metrics & Logs) 27.02 kB - -
@sentry/react 26.84 kB - -
@sentry/react (incl. Tracing) 44.09 kB - -
@sentry/vue 29.56 kB - -
@sentry/vue (incl. Tracing) 43.67 kB - -
@sentry/svelte 25.12 kB - -
CDN Bundle 27.67 kB - -
CDN Bundle (incl. Tracing) 42.67 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 43.5 kB - -
CDN Bundle (incl. Tracing, Replay) 79.37 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 84.81 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 85.72 kB - -
CDN Bundle - uncompressed 81.08 kB - -
CDN Bundle (incl. Tracing) - uncompressed 126.5 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 129.33 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 243.03 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 255.83 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 258.64 kB - -
@sentry/nextjs (client) 46.44 kB - -
@sentry/sveltekit (client) 42.25 kB - -
@sentry/node-core 51.94 kB +0.06% +28 B 🔺
@sentry/node 162.19 kB +0.02% +30 B 🔺
@sentry/node - without tracing 93.35 kB +0.03% +21 B 🔺
@sentry/aws-serverless 108.85 kB +0.03% +22 B 🔺

View base workflow run

@github-actions
Copy link
Contributor

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 11,585 - 9,480 +22%
GET With Sentry 2,014 17% 1,766 +14%
GET With Sentry (error only) 7,637 66% 6,074 +26%
POST Baseline 1,205 - 1,201 +0%
POST With Sentry 605 50% 594 +2%
POST With Sentry (error only) 1,073 89% 1,051 +2%
MYSQL Baseline 4,002 - 3,324 +20%
MYSQL With Sentry 556 14% 483 +15%
MYSQL With Sentry (error only) 3,299 82% 2,682 +23%

View base workflow run

@JPeer264 JPeer264 merged commit d2df7f6 into develop Jan 19, 2026
212 checks passed
@JPeer264 JPeer264 deleted the jp/find-ip branch January 19, 2026 12:56
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.

3 participants