From 569a16c4ac5df991848eabbdca8d738ba947ab86 Mon Sep 17 00:00:00 2001 From: tammy-baylis-swi Date: Thu, 5 Nov 2026 17:37:11 -0700 Subject: [PATCH 1/3] hmac the sig check --- solarwinds_apm/oboe/trace_options.py | 6 +++++- tests/unit/test_oboe/test_trace_options.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/solarwinds_apm/oboe/trace_options.py b/solarwinds_apm/oboe/trace_options.py index 0c0e5e1a5..3ead6f671 100644 --- a/solarwinds_apm/oboe/trace_options.py +++ b/solarwinds_apm/oboe/trace_options.py @@ -382,6 +382,10 @@ def validate_signature(header, signature, key, timestamp): "Failed to encode key or header for signature validation: %s", exc ) return Auth.BAD_SIGNATURE - if signature == digest: + try: + signature_matches = hmac.compare_digest(signature, digest) + except (TypeError, ValueError): + return Auth.BAD_SIGNATURE + if signature_matches: return Auth.OK return Auth.BAD_SIGNATURE diff --git a/tests/unit/test_oboe/test_trace_options.py b/tests/unit/test_oboe/test_trace_options.py index 7422a9046..75de5ad4a 100644 --- a/tests/unit/test_oboe/test_trace_options.py +++ b/tests/unit/test_oboe/test_trace_options.py @@ -351,3 +351,15 @@ def test_stringify_trace_options_response(): def test_validate_signature(header, signature, key, timestamp, expected): result = validate_signature(header, signature, key, timestamp) assert result == expected + + +def test_validate_signature_uses_constant_time_comparison(mocker): + compare_digest = mocker.patch( + "solarwinds_apm.oboe.trace_options.hmac.compare_digest", + return_value=True, + ) + + result = validate_signature("header", "signature", "key", int(time.time())) + + compare_digest.assert_called_once() + assert result == Auth.OK From fb6594519c9d4dd4eb238f0fe1cd2ec6bd753a65 Mon Sep 17 00:00:00 2001 From: Tammy Baylis <96076570+tammy-baylis-swi@users.noreply.github.com> Date: Thu, 5 Nov 2026 17:42:41 -0700 Subject: [PATCH 2/3] Implement test for malformed signature rejection Add parameterized test for validating malformed signatures. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/unit/test_oboe/test_trace_options.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unit/test_oboe/test_trace_options.py b/tests/unit/test_oboe/test_trace_options.py index 75de5ad4a..c748915b8 100644 --- a/tests/unit/test_oboe/test_trace_options.py +++ b/tests/unit/test_oboe/test_trace_options.py @@ -363,3 +363,12 @@ def test_validate_signature_uses_constant_time_comparison(mocker): compare_digest.assert_called_once() assert result == Auth.OK + + +@pytest.mark.parametrize( + "signature", ["", "not-a-digest", "é", None, b"signature", 123] +) +def test_validate_signature_rejects_malformed_signatures(signature: object) -> None: + """Reject malformed signatures without propagating comparison errors.""" + result = validate_signature("header", signature, "key", int(time.time())) + assert result == Auth.BAD_SIGNATURE From 94fbfcb4ee82e1e36bd51f54a1510bcf2eb7cf22 Mon Sep 17 00:00:00 2001 From: tammy-baylis-swi Date: Thu, 5 Nov 2026 17:43:54 -0700 Subject: [PATCH 3/3] Lint --- tests/unit/test_oboe/test_trace_options.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_oboe/test_trace_options.py b/tests/unit/test_oboe/test_trace_options.py index c748915b8..714479158 100644 --- a/tests/unit/test_oboe/test_trace_options.py +++ b/tests/unit/test_oboe/test_trace_options.py @@ -368,7 +368,9 @@ def test_validate_signature_uses_constant_time_comparison(mocker): @pytest.mark.parametrize( "signature", ["", "not-a-digest", "é", None, b"signature", 123] ) -def test_validate_signature_rejects_malformed_signatures(signature: object) -> None: +def test_validate_signature_rejects_malformed_signatures( + signature: object, +) -> None: """Reject malformed signatures without propagating comparison errors.""" result = validate_signature("header", signature, "key", int(time.time())) assert result == Auth.BAD_SIGNATURE