"""Diagnostic tool to inspect environment variables (secrets redacted)."""
import jsonutil as json
import os
import re
TOOL_NAME = "check_env"
TOOL_DESCRIPTION = (
"Show current environment variables with secrets redacted. "
"Useful for diagnosing configuration and deployment issues."
)
TOOL_PARAMETERS = {
"type": "object",
"properties": {},
}
_SECRET_SUBSTRINGS = (
"KEY",
"SECRET",
"TOKEN",
"PASSWORD",
"CREDENTIAL",
"AUTH",
"PRIVATE",
"BEARER",
"APIKEY",
"API_KEY",
)
def _looks_like_secret_value(val: str) -> bool:
"""Heuristically decide whether an environment value looks like a secret.
Applies several conservative regular-expression heuristics to a raw
environment-variable value so that opaque credentials can be redacted even
when their variable name does not contain an obvious secret substring. A
value is treated as secret-looking when it matches an ``Authorization:
Bearer ...`` header, when it is a long (>= 24 character) opaque base64/base64url
blob, or when it embeds a JWT-style ``eyJ...`` payload.
This is a pure, self-contained predicate: it performs no I/O and has no
side effects, relying only on the ``re`` module. It is called by
:func:`run` in this module while building the redacted snapshot of
``os.environ``; no other internal callers were found.
Args:
val: The candidate environment-variable value to inspect. ``None`` and
empty/whitespace-only strings are treated as non-secrets.
Returns:
bool: ``True`` if the value resembles a secret and should be redacted,
``False`` otherwise.
"""
v = (val or "").strip()
if not v:
return False
if re.fullmatch(r"Bearer\s+[\w\-._~+/]+=*", v, re.I):
return True
if len(v) >= 24 and re.fullmatch(r"[A-Za-z0-9+/=_-]+", v):
return True
if re.search(r"(eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{5,})", v):
return True
return False
[docs]
async def run(**_kwargs) -> str:
"""Execute this tool and return the result.
Returns:
str: Result string.
"""
env = dict(os.environ)
safe_env: dict[str, str] = {}
for k, v in env.items():
if any(s in k.upper() for s in _SECRET_SUBSTRINGS):
continue
if _looks_like_secret_value(v):
safe_env[k] = "<redacted>"
else:
safe_env[k] = v
return json.dumps(safe_env, indent=2)