@@ -389,7 +389,7 @@ async def _enqueue_ws_payload(self, websocket, payload: dict[str, Any]) -> None:
389389
390390 if _LOG .isEnabledFor (logging .DEBUG ):
391391 _LOG .debug (
392- "[%s] ->: %s" , websocket .remote_address , filter_log_msg_data (payload )
392+ "[%s] ->: %s" , websocket .remote_address , sanitize_json_message (payload )
393393 )
394394
395395 match payload .get ("kind" ):
@@ -1777,46 +1777,83 @@ def local_hostname() -> str:
17771777 )
17781778
17791779
1780- def filter_log_msg_data (data : dict [str , Any ]) -> dict [str , Any ]:
1780+ _REDACTED_VALUE = "***REDACTED***"
1781+ _SENSITIVE_KEYS = {
1782+ "token" ,
1783+ "token_id" ,
1784+ "access_token" ,
1785+ "refresh_token" ,
1786+ "id_token" ,
1787+ "authorization_code" ,
1788+ "client_secret" ,
1789+ "secret" ,
1790+ "auth_url" ,
1791+ "client_data" ,
1792+ "password" ,
1793+ }
1794+
1795+
1796+ def _filter_base64_images (json_data : Any ) -> Any :
1797+ """
1798+ Filter out base64 encoded images from a JSON object.
1799+
1800+ **Attention:** the provided JSON object is modified in-place!
1801+
1802+ :param json_data: The JSON object to filter.
1803+ :returns: The filtered JSON object.
1804+ """
1805+ if json_data and isinstance (json_data , dict ) and "msg_data" in json_data :
1806+ msg_data = json_data ["msg_data" ]
1807+ if isinstance (msg_data , list ):
1808+ for item in msg_data :
1809+ if (
1810+ isinstance (item , dict )
1811+ and "attributes" in item
1812+ and isinstance (item ["attributes" ], dict )
1813+ and item ["attributes" ]
1814+ .get (MediaAttr .MEDIA_IMAGE_URL , "" )
1815+ .startswith ("data:" )
1816+ ):
1817+ item ["attributes" ][MediaAttr .MEDIA_IMAGE_URL ] = "data:..."
1818+ elif (
1819+ isinstance (msg_data , dict )
1820+ and "attributes" in msg_data
1821+ and isinstance (msg_data ["attributes" ], dict )
1822+ and msg_data ["attributes" ]
1823+ .get (MediaAttr .MEDIA_IMAGE_URL , "" )
1824+ .startswith ("data:" )
1825+ ):
1826+ msg_data ["attributes" ][MediaAttr .MEDIA_IMAGE_URL ] = "data:..."
1827+ return json_data
1828+
1829+
1830+ def sanitize_json_message (data : Any ) -> Any :
17811831 """
1782- Filter attribute fields to exclude for log messages in the given msg data dict.
1832+ Sanitizes a JSON message by redacting sensitive fields such as tokens and secrets.
1833+
1834+ Base64 encoded images starting with `data:` are removed in `msg_data.attributes.media_image_url`
1835+ fields to limit log output.
17831836
1784- - Attributes are filtered in `data["msg_data"]`:
1785- - dict object: key `attributes`
1786- - list object: every list item `attributes`
1787- - Filtered attributes: `MEDIA_IMAGE_URL`
1837+ The original message is not modified, the returned redacted message is a deepcopy.
17881838
1789- :param data: the message data dict
1790- :return: copy of the message data dict with filtered attributes
1839+ :param data: The JSON object to be sanitized.
1840+ :return: The sanitized JSON object with sensitive information redacted.
17911841 """
17921842 # do not modify the original dict
1793- log_upd = deepcopy (data )
1794- if not log_upd :
1843+ json_upd = deepcopy (data )
1844+ if not json_upd :
17951845 return {}
17961846
1797- # filter out base64 encoded images in the media player's media_image_url attribute
1798- if "msg_data" in log_upd :
1799- if (
1800- "attributes" in log_upd ["msg_data" ]
1801- and MediaAttr .MEDIA_IMAGE_URL in log_upd ["msg_data" ]["attributes" ]
1802- and (
1803- media_image_url := log_upd ["msg_data" ]["attributes" ][
1804- MediaAttr .MEDIA_IMAGE_URL
1805- ]
1806- )
1807- and media_image_url .startswith ("data:" )
1808- ):
1809- log_upd ["msg_data" ]["attributes" ][MediaAttr .MEDIA_IMAGE_URL ] = "data:***"
1810- elif isinstance (log_upd ["msg_data" ], list ):
1811- for item in log_upd ["msg_data" ]:
1812- if (
1813- "attributes" in item
1814- and MediaAttr .MEDIA_IMAGE_URL in item ["attributes" ]
1815- and (
1816- media_image_url := item ["attributes" ][MediaAttr .MEDIA_IMAGE_URL ]
1817- )
1818- and media_image_url .startswith ("data:" )
1819- ):
1820- item ["attributes" ][MediaAttr .MEDIA_IMAGE_URL ] = "data:***"
1847+ def sanitize_for_logging (value : Any ) -> Any :
1848+ if value and isinstance (value , (dict , list )):
1849+ if isinstance (value , list ):
1850+ return [sanitize_for_logging (item ) for item in value ]
1851+
1852+ for k , v in value .items ():
1853+ if k in _SENSITIVE_KEYS :
1854+ value [k ] = _REDACTED_VALUE
1855+ else :
1856+ value [k ] = sanitize_for_logging (v )
1857+ return value
18211858
1822- return log_upd
1859+ return sanitize_for_logging ( _filter_base64_images ( json_upd ))
0 commit comments