원클릭으로
credential-leak-audit
Find and fix credential leaks in log/display output — the URL sanitization pattern from PRs
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Find and fix credential leaks in log/display output — the URL sanitization pattern from PRs
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Systematic approach to rebasing a stale PR branch onto a diverged upstream main — from PRs
Receive, verify, and respond to PR review feedback — especially hermes-sweeper automated reviews.
Hermes Ops Kit workflows for provider routing, secret and key lifecycle, preflight plugin scanning, MCP auditing, cost governance, and operator diagnostics.
Use Hermes Ops Kit with Vaultwarden/Bitwarden secret storage, preferring the Bitwarden CLI (`bw`) for item-level CRUD and verification.
| name | credential-leak-audit |
| description | Find and fix credential leaks in log/display output — the URL sanitization pattern from PRs |
Pattern for finding and fixing credential leaks in Python code that logs or displays configuration values to terminals, log files, or structured output.
When code reads a base_url from config and displays it without sanitization, the URL
may carry embedded credentials:
https://user:pass@api.example.com/v1 # userinfo in netloc
https://api.example.com/v1?api_key=sk-abc # query-string API token
https://api.example.com/v1#fragment # rarely sensitive, but strip anyway
These leak through:
logger.info("... %s ...", base_url) — log files, aggregatorsprint(f"base_url: {base_url}") — terminal output, CI logscheck_info(f"base_url: {base_url}") — diagnostic commandsSearch for config values that are interpolated into output without a sanitizer:
# Find base_url references in log/print calls
rg -n 'base_url.*f"|f".*base_url|logger\.\w+\(.*base_url|print\(.*base_url' --glob '!tests/**'
# Find API key references (should NEVER be in output)
rg -n 'api_key.*f"|f".*api_key|logger\.\w+\(.*api_key|print\(.*api_key' --glob '!tests/**'
If API keys are found in output: HIGH severity — fix immediately.
Add a sanitization function that strips sensitive URL components:
def _sanitize_url_for_display(url: str) -> str:
"""Strip userinfo, query, and fragment from a URL for terminal display."""
if not url:
return url
try:
from urllib.parse import urlparse, urlunparse
parsed = urlparse(url)
# Python's ParseResult has no `userinfo` field — split netloc manually
netloc = parsed.netloc
if "@" in netloc:
netloc = netloc.split("@")[-1]
sanitized = parsed._replace(netloc=netloc, query="", fragment="")
return urlunparse(sanitized)
except Exception:
return "<url-redacted>" # never return raw on failure
Apply it at every display site:
# Before (LEAKS credentials)
check_info(f"base_url: {base_url}")
label += f" at {fb_url}"
# After (SAFE)
check_info(f"base_url: {_sanitize_url_for_display(base_url)}")
label += f" at {_sanitize_url_for_display(fb_url)}"
| Location | Approach |
|---|---|
| Same module, single use | Inline the function |
| Same module, multiple uses | Module-level helper |
| Multiple modules | Extract to a shared utility (e.g., utils.py) |
For hermes-agent, utils.py already exists and is imported widely — it's the natural home
for a shared _sanitize_url_for_logging.
Test with known-bad URLs:
tests = [
("https://user:pass@host/v1?key=sk-secret#f", "https://host/v1"),
("https://api.openai.com/v1", "https://api.openai.com/v1"),
("", ""),
]
for url, expected in tests:
assert sanitize(url) == expected
set_runtime_main() logged _RUNTIME_MAIN_BASE_URL directly via logger.info().
The base URL can come from OPENAI_BASE_URL env var, which users commonly set with
embedded credentials. Added _sanitize_url_for_logging() and applied it before
interpolation.
_show_verbose_route_details() and _show_verbose_fallback_chain() displayed
base_url from config.yaml via check_info(). Added _sanitize_url_for_display()
and applied at both call sites.