Skip to content

Commit

Permalink
Avoid recursing too deep when redacting logs (apache#16491)
Browse files Browse the repository at this point in the history
Fix apache#16473

(cherry picked from commit 7453d3e)
(cherry picked from commit 6a5e676)
(cherry picked from commit 5398eb5)
(cherry picked from commit de563e3)
  • Loading branch information
uranusjr authored and kaxil committed Jun 23, 2021
1 parent ddcb073 commit 5a7e9ee
Showing 1 changed file with 29 additions and 21 deletions.
50 changes: 29 additions & 21 deletions airflow/utils/log/secrets_masker.py
Expand Up @@ -124,6 +124,7 @@ class SecretsMasker(logging.Filter):
patterns: Set[str]

ALREADY_FILTERED_FLAG = "__SecretsMasker_filtered"
MAX_RECURSION_DEPTH = 5

def __init__(self):
super().__init__()
Expand Down Expand Up @@ -169,35 +170,34 @@ def filter(self, record) -> bool:

return True

def _redact_all(self, item: "RedactableItem") -> "RedactableItem":
if isinstance(item, dict):
return {dict_key: self._redact_all(subval) for dict_key, subval in item.items()}
elif isinstance(item, str):
def _redact_all(self, item: "RedactableItem", depth: int) -> "RedactableItem":
if depth > self.MAX_RECURSION_DEPTH or isinstance(item, str):
return '***'
if isinstance(item, dict):
return {dict_key: self._redact_all(subval, depth + 1) for dict_key, subval in item.items()}
elif isinstance(item, (tuple, set)):
# Turn set in to tuple!
return tuple(self._redact_all(subval) for subval in item)
return tuple(self._redact_all(subval, depth + 1) for subval in item)
elif isinstance(item, list):
return list(self._redact_all(subval) for subval in item)
return list(self._redact_all(subval, depth + 1) for subval in item)
else:
return item

# pylint: disable=too-many-return-statements
def redact(self, item: "RedactableItem", name: str = None) -> "RedactableItem":
"""
Redact an any secrets found in ``item``, if it is a string.
If ``name`` is given, and it's a "sensitve" name (see
:func:`should_hide_value_for_key`) then all string values in the item
is redacted.
"""
def _redact(self, item: "RedactableItem", name: Optional[str], depth: int) -> "RedactableItem":
# Avoid spending too much effort on redacting on deeply nested
# structures. This also avoid infinite recursion if a structure has
# reference to self.
if depth > self.MAX_RECURSION_DEPTH:
return item
try:
if name and should_hide_value_for_key(name):
return self._redact_all(item)

return self._redact_all(item, depth)
if isinstance(item, dict):
return {dict_key: self.redact(subval, dict_key) for dict_key, subval in item.items()}
return {
dict_key: self._redact(subval, name=dict_key, depth=(depth + 1))
for dict_key, subval in item.items()
}
elif isinstance(item, str):
if self.replacer:
# We can't replace specific values, but the key-based redacting
Expand All @@ -207,9 +207,9 @@ def redact(self, item: "RedactableItem", name: str = None) -> "RedactableItem":
return item
elif isinstance(item, (tuple, set)):
# Turn set in to tuple!
return tuple(self.redact(subval) for subval in item)
return tuple(self._redact(subval, name=None, depth=(depth + 1)) for subval in item)
elif isinstance(item, list):
return list(self.redact(subval) for subval in item)
return [self._redact(subval, name=None, depth=(depth + 1)) for subval in item]
else:
return item
# I think this should never happen, but it does not hurt to leave it just in case
Expand All @@ -223,8 +223,16 @@ def redact(self, item: "RedactableItem", name: str = None) -> "RedactableItem":
)
return item

# pylint: enable=too-many-return-statements
def redact(self, item: "RedactableItem", name: Optional[str] = None) -> "RedactableItem":
"""Redact an any secrets found in ``item``, if it is a string.
If ``name`` is given, and it's a "sensitive" name (see
:func:`should_hide_value_for_key`) then all string values in the item
is redacted.
"""
return self._redact(item, name, depth=0)

# pylint: enable=too-many-return-statements
def add_mask(self, secret: Union[str, dict, Iterable], name: str = None):
"""Add a new secret to be masked to this filter instance."""
if isinstance(secret, dict):
Expand Down

0 comments on commit 5a7e9ee

Please sign in to comment.