feat: add config toggle to disable secret redaction
New config option:
security:
redact_secrets: false # default: true
When set to false, API keys, tokens, and passwords are shown in
full in read_file, search_files, and terminal output. Useful for
debugging auth issues where you need to verify the actual key value.
Bridged to both CLI and gateway via HERMES_REDACT_SECRETS env var.
The check is in redact_sensitive_text() itself, so all call sites
(terminal, file tools, log formatter) respect it.
This commit is contained in:
parent
7af33accf1
commit
57b48a81ca
4 changed files with 21 additions and 0 deletions
|
|
@ -8,6 +8,7 @@ the first 6 and last 4 characters for debuggability.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
@ -73,9 +74,12 @@ def redact_sensitive_text(text: str) -> str:
|
||||||
"""Apply all redaction patterns to a block of text.
|
"""Apply all redaction patterns to a block of text.
|
||||||
|
|
||||||
Safe to call on any string -- non-matching text passes through unchanged.
|
Safe to call on any string -- non-matching text passes through unchanged.
|
||||||
|
Disabled when security.redact_secrets is false in config.yaml.
|
||||||
"""
|
"""
|
||||||
if not text:
|
if not text:
|
||||||
return text
|
return text
|
||||||
|
if os.getenv("HERMES_REDACT_SECRETS", "").lower() in ("0", "false", "no", "off"):
|
||||||
|
return text
|
||||||
|
|
||||||
# Known prefixes (sk-, ghp_, etc.)
|
# Known prefixes (sk-, ghp_, etc.)
|
||||||
text = _PREFIX_RE.sub(lambda m: _mask_token(m.group(1)), text)
|
text = _PREFIX_RE.sub(lambda m: _mask_token(m.group(1)), text)
|
||||||
|
|
|
||||||
7
cli.py
7
cli.py
|
|
@ -364,6 +364,13 @@ def load_cli_config() -> Dict[str, Any]:
|
||||||
if model:
|
if model:
|
||||||
os.environ[model_env] = model
|
os.environ[model_env] = model
|
||||||
|
|
||||||
|
# Security settings
|
||||||
|
security_config = defaults.get("security", {})
|
||||||
|
if isinstance(security_config, dict):
|
||||||
|
redact = security_config.get("redact_secrets")
|
||||||
|
if redact is not None:
|
||||||
|
os.environ["HERMES_REDACT_SECRETS"] = str(redact).lower()
|
||||||
|
|
||||||
return defaults
|
return defaults
|
||||||
|
|
||||||
# Load configuration at module startup
|
# Load configuration at module startup
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,12 @@ if _config_path.exists():
|
||||||
_tz_cfg = _cfg.get("timezone", "")
|
_tz_cfg = _cfg.get("timezone", "")
|
||||||
if _tz_cfg and isinstance(_tz_cfg, str) and "HERMES_TIMEZONE" not in os.environ:
|
if _tz_cfg and isinstance(_tz_cfg, str) and "HERMES_TIMEZONE" not in os.environ:
|
||||||
os.environ["HERMES_TIMEZONE"] = _tz_cfg.strip()
|
os.environ["HERMES_TIMEZONE"] = _tz_cfg.strip()
|
||||||
|
# Security settings
|
||||||
|
_security_cfg = _cfg.get("security", {})
|
||||||
|
if isinstance(_security_cfg, dict):
|
||||||
|
_redact = _security_cfg.get("redact_secrets")
|
||||||
|
if _redact is not None:
|
||||||
|
os.environ["HERMES_REDACT_SECRETS"] = str(_redact).lower()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Non-fatal; gateway can still run with .env values
|
pass # Non-fatal; gateway can still run with .env values
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,10 @@ DEFAULT_CONFIG = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"security": {
|
||||||
|
"redact_secrets": True, # Mask API keys, tokens, passwords in tool output
|
||||||
|
},
|
||||||
|
|
||||||
"display": {
|
"display": {
|
||||||
"compact": False,
|
"compact": False,
|
||||||
"personality": "kawaii",
|
"personality": "kawaii",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue