From ae3fc7eb5783e3fb218f32d8138515cbf94f5c9d Mon Sep 17 00:00:00 2001 From: Tom Hu <88201630+thomasrockhu-codecov@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:54:24 +0300 Subject: [PATCH] fix: sanitize yaml token from logs (#485) * fix: sanitize yaml token from logs * fix: take into account JSON decoding error * fix: add unit tests --- codecov_cli/helpers/request.py | 29 ++++++++++++++++++++++++++++- tests/helpers/test_request.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/codecov_cli/helpers/request.py b/codecov_cli/helpers/request.py index a170b565..dbafc9a3 100644 --- a/codecov_cli/helpers/request.py +++ b/codecov_cli/helpers/request.py @@ -1,3 +1,4 @@ +import json import logging from sys import exit from time import sleep @@ -143,7 +144,9 @@ def log_warnings_and_errors_if_any( ) logger.debug( f"{process_desc} result", - extra=dict(extra_log_attributes=dict(result=sending_result)), + extra=dict( + extra_log_attributes=dict(result=_sanitize_request_result(sending_result)) + ), ) if sending_result.warnings: number_warnings = len(sending_result.warnings) @@ -157,3 +160,27 @@ def log_warnings_and_errors_if_any( logger.error(f"{process_desc} failed: {sending_result.error.description}") if fail_on_error: exit(1) + + +def _sanitize_request_result(result: RequestResult): + if not hasattr(result, "text"): + return result + + try: + text_as_dict = json.loads(result.text) + token = text_as_dict.get("repository").get("yaml").get("codecov").get("token") + if token: + sanitized_token = str(token)[:1] + 18 * "*" + text_as_dict["repository"]["yaml"]["codecov"]["token"] = sanitized_token + sanitized_text = json.dumps(text_as_dict) + + return RequestResult( + status_code=result.status_code, + error=result.error, + warnings=result.warnings, + text=sanitized_text, + ) + except (AttributeError, json.JSONDecodeError): + pass + + return result diff --git a/tests/helpers/test_request.py b/tests/helpers/test_request.py index 8be7cef6..1125f93f 100644 --- a/tests/helpers/test_request.py +++ b/tests/helpers/test_request.py @@ -54,6 +54,38 @@ def test_log_error_raise(mocker): mock_log_error.assert_called_with(f"Process failed: Unauthorized") +def test_log_result_without_token(mocker): + mock_log_debug = mocker.patch.object(req_log, "debug") + result = RequestResult( + error=None, + warnings=[], + status_code=201, + text="{\"message\":\"commit\",\"timestamp\":\"2024-03-25T15:41:07Z\",\"ci_passed\":true,\"state\":\"complete\",\"repository\":{\"name\":\"repo\",\"is_private\":false,\"active\":true,\"language\":\"python\",\"yaml\":null},\"author\":{\"avatar_url\":\"https://example.com\",\"service\":\"github\",\"username\":null,\"name\":\"dependabot[bot]\",\"ownerid\":2780265},\"commitid\":\"commit\",\"parent_commit_id\":\"parent\",\"pullid\":1,\"branch\":\"main\"}" + ) + log_warnings_and_errors_if_any(result, "Commit creating", False) + mock_log_debug.assert_called_with('Commit creating result', extra={'extra_log_attributes': {'result': result}}) + + +def test_log_result_with_token(mocker): + mock_log_debug = mocker.patch.object(req_log, "debug") + result = RequestResult( + error=None, + warnings=[], + status_code=201, + text="{\"message\": \"commit\", \"timestamp\": \"2024-07-16T20:51:07Z\", \"ci_passed\": true, \"state\": \"complete\", \"repository\": {\"name\": \"repo\", \"is_private\": false, \"active\": true, \"language\": \"python\", \"yaml\": {\"codecov\": {\"token\": \"faketoken\"}}, \"author\": {\"avatar_url\": \"https://example.com\", \"service\": \"github\", \"username\": \"author\", \"name\": \"author\", \"ownerid\": 3461769}, \"commitid\": \"commit\", \"parent_commit_id\": \"parent_commit\", \"pullid\": null, \"branch\": \"main\"}}" + ) + + expected_text = "{\"message\": \"commit\", \"timestamp\": \"2024-07-16T20:51:07Z\", \"ci_passed\": true, \"state\": \"complete\", \"repository\": {\"name\": \"repo\", \"is_private\": false, \"active\": true, \"language\": \"python\", \"yaml\": {\"codecov\": {\"token\": \"f******************\"}}, \"author\": {\"avatar_url\": \"https://example.com\", \"service\": \"github\", \"username\": \"author\", \"name\": \"author\", \"ownerid\": 3461769}, \"commitid\": \"commit\", \"parent_commit_id\": \"parent_commit\", \"pullid\": null, \"branch\": \"main\"}}" + expected = RequestResult( + error=None, + warnings=[], + status_code=201, + text=expected_text, + ) + log_warnings_and_errors_if_any(result, "Commit creating", False) + mock_log_debug.assert_called_with('Commit creating result', extra={'extra_log_attributes': {'result': expected}}) + + def test_get_token_header_or_fail(): # Test with a valid UUID token token = uuid.uuid4()