Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions sentry_sdk/integrations/_asgi_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,7 @@ def _get_request_data(

headers = _get_headers(asgi_scope)

request_data["headers"] = _filter_headers(
headers,
use_annotated_value=False,
)
request_data["headers"] = _filter_headers(headers)

if has_data_collection_enabled(client_options):
qs = _get_query(asgi_scope)
Expand Down Expand Up @@ -175,7 +172,7 @@ def _get_request_attributes(

headers = _get_headers(asgi_scope)

filtered_headers = _filter_headers(headers, use_annotated_value=False)
filtered_headers = _filter_headers(headers)
for header, value in filtered_headers.items():
attributes[f"http.request.header.{header.lower()}"] = value

Expand Down
46 changes: 13 additions & 33 deletions sentry_sdk/integrations/_wsgi_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,38 +221,18 @@ def _is_json_content_type(ct: "Optional[str]") -> bool:

def _filter_headers(
headers: "Mapping[str, str]",
use_annotated_value: bool = True,
) -> "Mapping[str, Union[AnnotatedValue, str]]":
) -> "Mapping[str, str]":
client_options = sentry_sdk.get_client().options

if has_data_collection_enabled(client_options):
data_collection_configuration = client_options["data_collection"]

filtered = _apply_key_value_collection_filtering(
items=headers,
behaviour=data_collection_configuration["http_headers"]["request"],
)

for key in filtered:
if isinstance(key, str) and key.lower() in ("cookie", "set-cookie"):
filtered[key] = SENSITIVE_DATA_SUBSTITUTE

return filtered
else:
if should_send_default_pii():
return headers

substitute: "Union[AnnotatedValue, str]" = (
SENSITIVE_DATA_SUBSTITUTE
if not use_annotated_value
else AnnotatedValue.removed_because_over_size_limit()
)

return {
k: (
v
if k.upper().replace("-", "_") not in SENSITIVE_HEADERS
else substitute
)
for k, v in headers.items()
}
data_collection_configuration = client_options["data_collection"]

filtered = _apply_key_value_collection_filtering(
items=headers,
behaviour=data_collection_configuration["http_headers"]["request"],
)

for key in filtered:
if isinstance(key, str) and key.lower() in ("cookie", "set-cookie"):
filtered[key] = SENSITIVE_DATA_SUBSTITUTE

return filtered
6 changes: 1 addition & 5 deletions sentry_sdk/integrations/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,8 @@ async def sentry_app_handle(
Scope.set_custom_sampling_context({"aiohttp_request": request})

header_attributes: "dict[str, Any]" = {}
for header, header_value in _filter_headers(
headers,
use_annotated_value=False,
).items():
for header, header_value in _filter_headers(headers).items():
header_attributes[f"http.request.header.{header.lower()}"] = (
# header_value will always be a string because we set `use_annotated_value` to false above
header_value
)

Expand Down
4 changes: 1 addition & 3 deletions sentry_sdk/integrations/aws_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,7 @@ def sentry_handler(
headers = {}

header_attributes: "dict[str, Any]" = {}
for header, header_value in _filter_headers(
headers, use_annotated_value=False
).items():
for header, header_value in _filter_headers(headers).items():
header_attributes[f"http.request.header.{header.lower()}"] = (
header_value
)
Expand Down
4 changes: 1 addition & 3 deletions sentry_sdk/integrations/chalice.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ def wrapped_view_function(**function_args: "Any") -> "Any":
headers = request_dict.get("headers", {})

header_attrs: "Dict[str, Any]" = {}
for header, value in _filter_headers(
headers, use_annotated_value=False
).items():
for header, value in _filter_headers(headers).items():
header_attrs[f"http.request.header.{header.lower()}"] = value

additional_attrs: "Dict[str, Any]" = {}
Expand Down
5 changes: 1 addition & 4 deletions sentry_sdk/integrations/gcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,8 @@ def sentry_func(
header_attributes: "dict[str, Any]" = {}
if hasattr(gcp_event, "headers"):
headers = gcp_event.headers
for header, header_value in _filter_headers(
headers, use_annotated_value=False
).items():
for header, header_value in _filter_headers(headers).items():
header_attributes[f"http.request.header.{header.lower()}"] = (
# header_value will always be a string because we set `use_annotated_value` to false above
header_value
)

Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/quart.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ async def _request_websocket_started(app: "Quart", **kwargs: "Any") -> None:
header_attributes: "dict[str, Any]" = {}

for header, header_value in _filter_headers(
dict(request_websocket.headers), use_annotated_value=False
dict(request_websocket.headers)
).items():
header_attributes[f"http.request.header.{header.lower()}"] = header_value

Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def _get_request_attributes(request: "Request") -> "Dict[str, Any]":
if request.method:
attributes[SPANDATA.HTTP_REQUEST_METHOD] = request.method.upper()

headers = _filter_headers(dict(request.headers), use_annotated_value=False)
headers = _filter_headers(dict(request.headers))
for header, value in headers.items():
attributes[f"{SPANDATA.HTTP_REQUEST_HEADER}.{header.lower()}"] = value

Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
if request.method:
attributes[SPANDATA.HTTP_REQUEST_METHOD] = request.method.upper()

headers = _filter_headers(dict(request.headers), use_annotated_value=False)
headers = _filter_headers(dict(request.headers))
for header, value in headers.items():
attributes[f"{SPANDATA.HTTP_REQUEST_HEADER}.{header.lower()}"] = value

Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def _get_request_attributes(
if method:
attributes["http.request.method"] = method.upper()

headers = _filter_headers(dict(_get_headers(environ)), use_annotated_value=False)
headers = _filter_headers(dict(_get_headers(environ)))
for header, value in headers.items():
attributes[f"http.request.header.{header.lower()}"] = value

Expand Down
113 changes: 0 additions & 113 deletions tests/integrations/aiohttp/test_aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1449,119 +1449,6 @@ async def hello(request):
)


@pytest.mark.parametrize(
"data_collection,expected",
[
pytest.param(
{
"http_headers": {"request": {"mode": "off"}},
},
None,
id="data_collection_off_does_not_add_headers",
),
pytest.param(
{
"http_headers": {"request": {"mode": "allowlist"}},
},
{
"authorization": "[Filtered]",
"custom": "[Filtered]",
"cookie": "[Filtered]",
},
id="data_collection_allow_list_redacts_terms_that_do_not_appear",
),
pytest.param(
{
"http_headers": {
"request": {"mode": "allowlist", "terms": ["Authorization"]}
}
},
{
"authorization": "[Filtered]",
"custom": "[Filtered]",
"cookie": "[Filtered]",
},
id="data_collection_allow_list_redacts_sensitive_terms_even_when_provided_by_user",
),
pytest.param(
{"http_headers": {"request": {"mode": "allowlist", "terms": ["custom"]}}},
{
"authorization": "[Filtered]",
"custom": "foobar",
"cookie": "[Filtered]",
},
id="data_collection_allow_list_does_not_redact_provided_term",
),
pytest.param(
{"http_headers": {"request": {"mode": "denylist", "terms": ["custom"]}}},
{
"authorization": "[Filtered]",
"custom": "[Filtered]",
"cookie": "[Filtered]",
},
id="data_collection_deny_list_redacts_sensitive_terms_when_provided_by_user",
),
pytest.param(
{"http_headers": {"request": {"mode": "allowlist", "terms": ["cookie"]}}},
{
"authorization": "[Filtered]",
"custom": "[Filtered]",
"cookie": "[Filtered]",
},
id="data_collection_cookie_is_always_redacted_even_when_allow_listed",
),
],
)
@pytest.mark.asyncio
async def test_sensitive_header_passthrough_with_pii(
sentry_init, aiohttp_client, capture_items, data_collection, expected, request
):
sentry_init(
integrations=[AioHttpIntegration()],
traces_sample_rate=1.0,
data_collection=data_collection,
)

async def hello(request):
return web.Response(text="hello")

app = web.Application()
app.router.add_get("/", hello)

items = capture_items("span")

client = await aiohttp_client(app)
await client.get(
"/",
headers={
"Authorization": "Bearer secret-token",
"x-custom-header": "foobar",
"Cookie": "sessionid=secret",
},
)

sentry_sdk.flush()

(server_span,) = [item.payload for item in items]

if expected is None:
assert "http.request.header.authorization" not in server_span["attributes"]
assert "http.request.header.cookie" not in server_span["attributes"]
else:
assert (
server_span["attributes"]["http.request.header.authorization"]
== expected["authorization"]
)
assert (
server_span["attributes"]["http.request.header.x-custom-header"]
== expected["custom"]
)
assert (
server_span["attributes"]["http.request.header.cookie"]
== expected["cookie"]
)


@pytest.mark.asyncio
@pytest.mark.parametrize(
"url,transaction_style,expected_name,expected_source",
Expand Down
Loading
Loading