Skip to content

Commit 92937df

Browse files
authored
fix(ddwaf): allow conversion of arbitrary Mappings and Sequences to ddwaf_object (#14913)
## Description Allow conversion of arbitrary Mappings and Sequences to ddwaf_object type. ## Motivation When using `requests` without `urllib3` patching with `urllib3<2`, headers are represented by a `requests.structures.CaseInsensitiveDict` instead of a regular Dict when they are intercepted at the `http.client` level by the patched `HTTPConnection.request` function. When converting to ddwaf_object this coerces it into a string instead of properly representing it as a `map`. This makes headers matching effectively useless. ## Testing - Added a unit test ## Risks <!-- Note any risks associated with this change, or "None" if no risks --> ## Additional Notes <!-- Any other information that would be helpful for reviewers -->
1 parent c7d0b6a commit 92937df

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

ddtrace/appsec/_ddwaf/ddwaf_types.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from collections.abc import Mapping
2+
from collections.abc import Sequence
13
import ctypes
24
import ctypes.util
35
from enum import IntEnum
@@ -128,7 +130,7 @@ def truncate_string(string: bytes) -> bytes:
128130
ddwaf_object_string(self, truncate_string(struct))
129131
elif isinstance(struct, float):
130132
ddwaf_object_float(self, struct)
131-
elif isinstance(struct, list):
133+
elif isinstance(struct, Sequence):
132134
if max_depth <= 0:
133135
observator.set_container_depth(DDWAF_MAX_CONTAINER_DEPTH)
134136
max_objects = 0
@@ -145,7 +147,7 @@ def truncate_string(string: bytes) -> bytes:
145147
max_string_length=max_string_length,
146148
)
147149
ddwaf_object_array_add(array, obj)
148-
elif isinstance(struct, dict):
150+
elif isinstance(struct, Mapping):
149151
if max_depth <= 0:
150152
observator.set_container_depth(DDWAF_MAX_CONTAINER_DEPTH)
151153
max_objects = 0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
AAP: This fix resolves an issue where downstream request analysis would not match headers in rules when using `requests` with `urllib3<2`.

tests/appsec/appsec/test_ddwaf_fuzz.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from hypothesis import given
44
from hypothesis import strategies as st
55
import pytest
6+
from requests.structures import CaseInsensitiveDict
67

78
from ddtrace.appsec._ddwaf.ddwaf_types import _observator
89
from ddtrace.appsec._ddwaf.ddwaf_types import ddwaf_object
@@ -57,6 +58,19 @@ def test_small_objects(obj, res):
5758
assert dd_obj.struct == res
5859

5960

61+
@pytest.mark.parametrize(
62+
["obj", "res"],
63+
[
64+
(CaseInsensitiveDict({"SomeHeader": "SomeValue"}), {"SomeHeader": "SomeValue"}),
65+
(range(1, 4), [1, 2, 3]),
66+
((1, 2, 3), [1, 2, 3]),
67+
],
68+
)
69+
def test_mappings_and_sequences(obj, res):
70+
dd_obj = ddwaf_object(obj)
71+
assert dd_obj.struct == res
72+
73+
6074
@pytest.mark.parametrize(
6175
"obj, res, trunc",
6276
[

0 commit comments

Comments
 (0)