Repository navigation
fix(https_fn): stop logging callable request contents on invalid bodies #330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b37140c
77ab967
67debc9
a93ef11
fc7c756
e940a92
14a9c2d
ac74442
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,9 +16,13 @@ | |
| """ | ||
|
|
||
| import datetime as _dt | ||
| import logging | ||
| from os import environ, path | ||
|
|
||
| from flask import Flask | ||
|
|
||
| from firebase_functions.private.util import ( | ||
| _on_call_valid_body, | ||
| _unsafe_decode_id_token, | ||
| deep_merge, | ||
| firebase_config, | ||
|
|
@@ -165,3 +169,72 @@ def test_unsafe_decode_token(): | |
| result = _unsafe_decode_id_token(test_token) | ||
| assert result["sub"] == "firebase" | ||
| assert result["name"] == "John Doe" | ||
|
|
||
|
|
||
| def _valid_body(body: str) -> bool: | ||
| with Flask(__name__).test_request_context( | ||
| method="POST", data=body, content_type="application/json" | ||
| ) as ctx: | ||
| return _on_call_valid_body(ctx.request) | ||
|
|
||
|
|
||
| def test_on_call_valid_body_logs_extra_field_keys_without_values(caplog): | ||
| with caplog.at_level(logging.WARNING): | ||
| assert not _valid_body('{"data": {}, "extraKey": "secretValue"}') | ||
| assert "Request body has extra fields: ['extraKey']" in caplog.text | ||
| assert "secretValue" not in caplog.text | ||
|
|
||
|
|
||
| def test_on_call_valid_body_escapes_newlines_in_extra_field_keys(caplog): | ||
| with caplog.at_level(logging.WARNING): | ||
| assert not _valid_body('{"data": {}, "a\\nFAKE LOG LINE": 1}') | ||
| assert "\n" not in caplog.text.rstrip("\n") | ||
|
|
||
|
|
||
| def test_on_call_valid_body_logs_only_key_names_when_data_is_missing(caplog): | ||
| with caplog.at_level(logging.WARNING): | ||
| assert not _valid_body('{"secretKey": "secretValue"}') | ||
| assert "Request body is missing data. Fields: ['secretKey']" in caplog.text | ||
| assert "secretValue" not in caplog.text | ||
|
|
||
|
|
||
| def test_on_call_valid_body_does_not_log_non_object_body_when_data_is_missing(caplog): | ||
| for body in ( | ||
| '["secretValue"]', | ||
| '["data", "secretValue"]', | ||
| '"data secretValue"', | ||
| "123", | ||
| ): | ||
| caplog.clear() | ||
| with caplog.at_level(logging.WARNING): | ||
| assert not _valid_body(body) | ||
| assert "Request body is missing data." in caplog.text | ||
| assert "secretValue" not in caplog.text | ||
|
|
||
|
|
||
| def test_on_call_valid_body_rejects_empty_body(caplog): | ||
| with caplog.at_level(logging.WARNING): | ||
| assert not _valid_body("") | ||
| assert "Request is missing body." in caplog.text | ||
|
|
||
|
|
||
| def test_on_call_valid_body_rejects_malformed_json_without_logging_it(caplog): | ||
| with caplog.at_level(logging.WARNING): | ||
| assert not _valid_body("{secretValue") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Add happy-path test for valid callable bodies All 6 new unit tests assert rejection ( def test_on_call_valid_body_accepts_valid_payloads(caplog):
for body in (
'{"data": {}}',
'{"data": "value"}',
'{"data": 123}',
'{"data": null}',
'{"data": [1, 2, 3]}',
):
caplog.clear()
with caplog.at_level(logging.WARNING):
assert _valid_body(body)
assert caplog.text == ""
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, added in 14a9c2d |
||
| assert "Request body is not valid JSON." in caplog.text | ||
| assert "Request is missing body." not in caplog.text | ||
| assert "secretValue" not in caplog.text | ||
|
|
||
|
|
||
| def test_on_call_valid_body_accepts_any_data_value_without_logging(caplog): | ||
| for body in ( | ||
| '{"data": {}}', | ||
| '{"data": "value"}', | ||
| '{"data": 123}', | ||
| '{"data": null}', | ||
| '{"data": [1, 2, 3]}', | ||
| ): | ||
| caplog.clear() | ||
| with caplog.at_level(logging.WARNING): | ||
| assert _valid_body(body), body | ||
| assert caplog.text == "" | ||
Uh oh!
There was an error while loading. Please reload this page.