Skip to content

fix(https_fn): stop logging callable request contents on invalid bodies - #330

Draft
IzaakGough wants to merge 2 commits into
mainfrom
fix/on-call-validation-logging
Draft

IzaakGough wants to merge 2 commits into
mainfrom
fix/on-call-validation-logging

Conversation

@IzaakGough

@IzaakGough IzaakGough commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #328.

When an on_call function got a malformed request, its warning log could include values from the request body, and this happens before any auth check.

This logs only the names of any extra fields, and never their values or the body.

  • Key names are logged with %r, so a name containing a newline cannot add fake log lines. Node also logs the names.

Tested with new unit tests and in the Functions emulator. Not tested on a deployed function.

Invalid callable bodies are logged before auth is checked, so log only
the count of extra fields and never the body.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the _on_call_valid_body function to prevent logging sensitive request body content, opting instead to log the count of extra fields. Corresponding unit tests were added to verify this behavior. The reviewer suggested adding a type check to ensure request.json is a dictionary to avoid potential runtime errors and recommended expanding test coverage to include non-dictionary JSON inputs to ensure robust error handling.

Comment on lines 123 to 131
if "data" not in request.json:
_logging.warning("Request body is missing data.", request.json)
_logging.warning("Request body is missing data.")
return False

extra_keys = {key: request.json[key] for key in request.json.keys() if key != "data"}
if len(extra_keys) != 0:
_logging.warning(
"Request body has extra fields: %s",
"".join(f"{key}: {value}," for (key, value) in extra_keys.items()),
)
# Request content is logged before auth is checked, so log neither keys nor values.
extra_field_count = sum(1 for key in request.json.keys() if key != "data")
if extra_field_count:
_logging.warning("Request body has extra fields (count=%d).", extra_field_count)
return False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the request body is a JSON list (e.g., ["data", "extra"]) or a non-dictionary type (e.g., an integer or string), checking "data" not in request.json or calling request.json.keys() will raise a TypeError or AttributeError. Checking isinstance(request.json, dict) first ensures that the request body is a dictionary before accessing its keys or checking for the presence of "data" keys.

Suggested change
if "data" not in request.json:
_logging.warning("Request body is missing data.", request.json)
_logging.warning("Request body is missing data.")
return False
extra_keys = {key: request.json[key] for key in request.json.keys() if key != "data"}
if len(extra_keys) != 0:
_logging.warning(
"Request body has extra fields: %s",
"".join(f"{key}: {value}," for (key, value) in extra_keys.items()),
)
# Request content is logged before auth is checked, so log neither keys nor values.
extra_field_count = sum(1 for key in request.json.keys() if key != "data")
if extra_field_count:
_logging.warning("Request body has extra fields (count=%d).", extra_field_count)
return False
if not isinstance(request.json, dict) or "data" not in request.json:
_logging.warning("Request body is missing data.")
return False
# Request content is logged before auth is checked, so log neither keys nor values.
extra_field_count = sum(1 for key in request.json.keys() if key != "data")
if extra_field_count:
_logging.warning("Request body has extra fields (count=%d).", extra_field_count)
return False

Comment thread tests/test_util.py
Comment on lines +189 to +195
def test_on_call_valid_body_does_not_log_body_when_data_is_missing(caplog):
for body in ('{"secretKey": "secretValue"}', '["secretValue"]'):
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add additional test cases to verify that non-dictionary JSON bodies (such as lists containing the string "data" or raw integers) are handled gracefully without raising unhandled exceptions.

Suggested change
def test_on_call_valid_body_does_not_log_body_when_data_is_missing(caplog):
for body in ('{"secretKey": "secretValue"}', '["secretValue"]'):
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_does_not_log_body_when_data_is_missing(caplog):
for body in ('{"secretKey": "secretValue"}', '["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

Matches the Node SDK. Names are logged with %r so a key cannot add log lines.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

on_call validation logs request body / extra field values before auth verification

1 participant