Skip to content

feat(http): [Data Collection 13] Apply cookie collection policy - #5811

Draft
adinauer wants to merge 12 commits into
feat/data-collectionfrom
feat/data-collection-cookies
Draft

feat(http): [Data Collection 13] Apply cookie collection policy#5811
adinauer wants to merge 12 commits into
feat/data-collectionfrom
feat/data-collection-cookies

Conversation

@adinauer

@adinauer adinauer commented Jul 22, 2026

Copy link
Copy Markdown
Member

PR Stack (Data Collection)


📜 Description

Apply the cookie Data Collection policy to automatically captured request and response cookies.

The policy is used by Spring MVC/WebFlux, OkHttp, Ktor, and Apollo 3/4 failed-request events. Explicit Data Collection supports off, deny-list, and allow-list behavior. Built-in sensitive cookie names and Spring integration-provided session cookie names are always filtered, including when allow-listed. Set-Cookie values are parsed separately so attributes such as Path, HttpOnly, and SameSite are preserved.

When Data Collection is absent, integrations preserve their existing sendDefaultPii behavior, including Spring's legacy security-cookie filtering and raw HTTP-client cookie values.

💡 Motivation and Context

Cookie collection previously relied on sendDefaultPii as an on/off gate, with filtering only in Spring integrations. This wires the existing dataCollection.cookies option across cookie capture paths and provides consistent explicit-mode filtering without changing the legacy bridge for applications that have not configured Data Collection.

Refs #5666

💚 How did you test it?

  • ./gradlew spotlessApply apiDump
  • ./gradlew :sentry:apiCheck
  • Core cookie filtering tests
  • OkHttp and Ktor failed-request tests
  • Spring, Spring Jakarta, and Spring 7 request tests
  • Apollo 3 and Apollo 4 test suites
  • git diff --check

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

Complete the remaining Data Collection configuration, documentation, and migration work.

#skip-changelog

⚠️ Merge this PR using a merge commit (not squash). Only the collection branch is squash-merged into main.

Filter automatically captured request and response cookies according to the Data Collection policy across Spring and HTTP client integrations. Preserve existing sendDefaultPii behavior when Data Collection is absent.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 6cdd40e

@sentry

sentry Bot commented Jul 22, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.48.0 (1) release

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 387.14 ms 447.16 ms 60.02 ms
Size 0 B 0 B 0 B

Baseline results on branch: feat/data-collection-query-params

Startup times

Revision Plain With Sentry Diff
adae5de 372.16 ms 476.20 ms 104.04 ms

App size

Revision Plain With Sentry Diff
adae5de 0 B 0 B 0 B

Previous results on branch: feat/data-collection-cookies

Startup times

Revision Plain With Sentry Diff
670b3d8 329.76 ms 371.15 ms 41.39 ms
df76abc 308.28 ms 356.24 ms 47.96 ms
b0be236 316.30 ms 372.60 ms 56.30 ms

App size

Revision Plain With Sentry Diff
670b3d8 0 B 0 B 0 B
df76abc 0 B 0 B 0 B
b0be236 0 B 0 B 0 B

adinauer and others added 2 commits July 23, 2026 10:30
Replace malformed request cookie pairs and invalid Set-Cookie values with the filtered placeholder. Preserve valid empty values, padded values, and response cookie attributes.

Co-Authored-By: Claude <noreply@anthropic.com>
Keep mocked OkHttp responses consistent with the non-null headers contract so failed-request capture can inspect response cookies.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

// Cookie is only sent if isSendDefaultPii is enabled
urlDetails.applyToRequest(this)
cookies = if (scopes.options.isSendDefaultPii) request.headers["Cookie"] else null
cookies = getRequestCookies(scopes, request.headers["Cookie"])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There could be multiple Cookie and Set-Cookie headers. we are currently only ever processing one of them and send them to sentry. Is that what we want or should we go through all of these?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've created #5982 so we can change this (likely) in the next major.

io.sentry.protocol.Response().apply {
// Set-Cookie is only sent if isSendDefaultPii is enabled due to PII
cookies = if (scopes.options.isSendDefaultPii) response.headers["Set-Cookie"] else null
cookies = getResponseCookies(scopes, response.headers["Set-Cookie"])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There could be multiple Cookie and Set-Cookie headers. we are currently only ever processing one of them and send them to sentry. Is that what we want or should we go through all of these?

urlDetails.applyToRequest(this)
// Cookie is only sent if isSendDefaultPii is enabled
cookies = if (scopes.options.isSendDefaultPii) request.headers["Cookie"] else null
cookies = getRequestCookies(scopes, request.headers["Cookie"])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There could be multiple Cookie and Set-Cookie headers. here we are currently only ever processing one of them and send them to sentry. Is that what we want or should we go through all of these?

io.sentry.protocol.Response().apply {
// Set-Cookie is only sent if isSendDefaultPii is enabled due to PII
cookies = if (scopes.options.isSendDefaultPii) response.headers["Set-Cookie"] else null
cookies = getResponseCookies(scopes, response.headers["Set-Cookie"])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There could be multiple Cookie and Set-Cookie headers. here we are currently only ever processing one of them and send them to sentry. Is that what we want or should we go through all of these?

}

private fun getResponseCookies(headers: List<HttpHeader>): String? {
val cookies = getHeader("Set-Cookie", headers)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There could be multiple Cookie and Set-Cookie headers. here we are currently only ever processing one of them and send them to sentry. Is that what we want or should we go through all of these?

} else {
null
}
cookies = getResponseCookies(response.headers)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There could be multiple Cookie and Set-Cookie headers. here we are currently only ever processing one of them and send them to sentry. Is that what we want or should we go through all of these?

}

try {
final @NotNull String[] cookieValues = cookies.split(";", -1);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Malformed cookies could become a problem. i.e.

   Cookie: theme=dark, sessionId=secret
   Cookie: theme=dark sessionId=secret

would be parsed as valid in our current implementation and leak the sessionId.
This is a fabricated example but we may want to check for cookie validity

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've improved the parser so this now falls back to [Filtered].

Validate cookie names and values before applying Data Collection filters.
Fail closed for malformed values that could embed additional sensitive
cookie pairs while preserving valid quoted and padded values.

Refs #5666
Co-Authored-By: Claude <noreply@anthropic.com>
Base automatically changed from feat/data-collection-query-params to feat/data-collection September 2, 2026 12:24
Bring the latest data collection behavior into the cookie filtering branch and retain coverage for both cookie and request header filtering.

Co-Authored-By: Claude <noreply@anthropic.com>

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

added some comments!

filterCookie(cookieValues[i], behavior, additionalSensitiveCookieNames));
}
return filteredCookies.toString();
} catch (Throwable ignored) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should probably catch something narrower otherwise we have no way of knowing that this code is working or not.
We also shouldn't be catching exceptions like OutOfMemoryError or StackOverflowError as the jvm is already in a bad state and ignoring it will leave the JVM in a worse state.

return filteredQuery.toString();
}

public static @Nullable List<String> filterCookiesFromHeader(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two nits:

  1. Can we move all the cookie related methods to a Cookies.java? I feel HttpUtils.java is getting too long. This also makes the methods more idiomatic. Cookies.filterFromHeader() reads more naturally to me than HttpUtils.filterCookiesFromHeader()
  2. Can we declare all of these as @ApiUsage.Internal or are they intended to be customer facing?

return filteredHeaders;
}

public static @Nullable String filterCookies(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you add a test for trailing spaces in cookies ?
my clanker tells me this would add a [Filtered] because of the way split is called.


final @NotNull List<String> filteredHeaders = new ArrayList<>();
for (final String header : headers) {
filteredHeaders.add(filterCookies(header, behavior, additionalSensitiveCookieNames));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this can add null items in to the list since filterCookies is @Nullable

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