Skip to content

Commit bd109dc

Browse files
committed
Add redact_sensitive_data function for secure logging
Signed-off-by: Jesse Sanford <108698+jessesanford@users.noreply.github.com>
1 parent d28a1a6 commit bd109dc

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

src/mcp/server/fastmcp/utilities/logging.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Logging utilities for FastMCP."""
22

33
import logging
4-
from typing import Literal
4+
from collections.abc import Mapping
5+
from typing import Any, Literal
56

67

78
def get_logger(name: str) -> logging.Logger:
@@ -41,3 +42,52 @@ def configure_logging(
4142
format="%(message)s",
4243
handlers=handlers,
4344
)
45+
46+
47+
# ---------------------------------------------------------------------------
48+
# Helper – redact sensitive data before logging
49+
# ---------------------------------------------------------------------------
50+
51+
52+
def redact_sensitive_data(
53+
data: Mapping[str, Any] | None,
54+
sensitive_keys: set[str] | None = None,
55+
) -> Mapping[str, Any] | None:
56+
"""Return a shallow copy with sensitive values replaced by "***".
57+
58+
This shared helper can be used across the code-base (e.g. the transparent
59+
OAuth proxy) to ensure we treat secrets consistently.
60+
61+
Parameters
62+
----------
63+
data:
64+
Original mapping (typically request/response payload). If *None* the
65+
function simply returns *None*.
66+
sensitive_keys:
67+
Optional set of keys that should be hidden; defaults to a common list
68+
of OAuth-related secrets.
69+
"""
70+
71+
if data is None:
72+
return None
73+
74+
sensitive_keys = sensitive_keys or {
75+
"client_secret",
76+
"authorization",
77+
"access_token",
78+
"refresh_token",
79+
"code",
80+
}
81+
82+
redacted: dict[str, Any] = {}
83+
for key, value in data.items():
84+
if key.lower() in sensitive_keys:
85+
# Show a short prefix of auth codes; redact everything else
86+
if key.lower() == "code" and isinstance(value, str):
87+
redacted[key] = value[:8] + "..." if len(value) > 8 else "***"
88+
else:
89+
redacted[key] = "***"
90+
else:
91+
redacted[key] = value
92+
93+
return redacted

0 commit comments

Comments
 (0)