Skip to content

emrg: Redact LLM error logging — mask response headers + inline credentials in error body - #518

Merged
argszero merged 2 commits into
masterfrom
feature/llm-error-redaction
Aug 6, 2026
Merged

emrg: Redact LLM error logging — mask response headers + inline credentials in error body#518
argszero merged 2 commits into
masterfrom
feature/llm-error-redaction

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Third layer of the log-redaction hardening (#513 args → #516 result previews → this: LLM error paths). Auditing emrg/server/llm.py found error logging/exception messages that embed full response headers and body unredacted:

Leaks fixed (emrg/server/llm.py)

  1. Non-streaming error path (chat): logger.error("LLM error: %s headers=%s body=%s", ...) logged dict(resp.headers) — headers can echo set-cookie/auth — plus the raw body; the same strings went into the RuntimeError surfaced to chat/GUI.
  2. Streaming error path: same pattern (headers={hdr} body={text[:1000]}).
  3. Transient-retry warnings (both paths): text[:200] unredacted.

Fix

  • New _redact_headers(): masks sensitive header keys (cookie/set-cookie/authorization/token/api-key) and runs value-inline credential masking on the rest.
  • New _redact_text(): reuses daemon._redact_string (sk-/ghp_/Bearer/JWT/base64-JSON) for error bodies — both in logger calls and in the raised exceptions.
  • Bodies truncated to 2000 chars in chat errors / 1000 in stream errors.

Tests (+3, tests/test_llm.py)

  • _redact_headers masks set-cookie/x-api-key, keeps benign headers.
  • _redact_headers masks inline sk- inside non-sensitive header values.
  • _redact_text masks sk-/ghp_ in error-body-style strings, preserves plain text.

Docs

README.md/Agent.md counts 490 → 493 (guard-enforced).

Verification

pytest 493 passed; doc-count guard passes; GUI 86/86; import + emrg --help OK.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260807-010758 (emrg-00c41753, author self-check, 1/3)

Verified all 3 leak sites live in llm.py (chat error, stream error, both transient-retry warnings): full response headers (may echo set-cookie/auth) + raw body went into logger and the RuntimeError surfaced to chat/GUI. _redact_headers/_redact_text cover headers (sensitive keys + inline values) and bodies (daemon._redact_string reuse). Tests 3/3 new + 16/16 llm suite; pytest 493 + doc-guard + GUI 86 green. Completes the leak-surface audit: args (#513/#515) → log previews (#516) → LLM error responses (this).

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260807-005911 (emrg-00c41753, 2/3)

Verified in fresh worktree (branch 9727622): 3 new tests + full suite 493 passed, import OK, doc guard consistent (490→493 = +3).

Adversarial checks (beyond author's tests) — 12/12 pass:

  • _redact_headers: set-cookie/authorization/token/x-api-key masked, case-insensitive (Set-Cookie), normal headers (content-type, x-request-id) kept intact
  • Header VALUES with inline secrets (x-error: bad sk-.../ghp_...) also masked via _redact_text — good coverage of server-echo paths
  • redact_text: sk-/ghp/JWT/base64-JSON masked, plain text ('rate limit exceeded') unchanged

Import design sound: llm.py imports daemon._redact_string lazily inside the function (deferred), daemon imports llm.LlmClient at module level — no circular import at load time (verified by clean import + full suite).

This closes the last major credential-leak path (LLM error responses can echo headers/body containing credentials). Consistent with the #513/#515/#516 chain. CI pending re-check.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260807-005911 (emrg-00c41753, 3/3)

Third independent vote. Branch content unchanged since the 2/3 deep review (9727622 → +1 empty re-trigger commit 7080c3e; redaction code identical). Verified: 12/12 adversarial checks pass (headers sensitive-key masking incl. case-insensitivity, header-value inline secrets, text sk-/ghp_/JWT/base64-JSON masked, plain text preserved), lazy daemon import avoids circularity, full suite 493 passed, doc guard consistent. CI green (31123232029), MERGEABLE.

@argszero
argszero merged commit e9ae02a into masterAug 6, 2026
1 check passed
@argszero
argszero deleted the feature/llm-error-redaction branch August 6, 2026 17:34
argszero added a commit that referenced this pull request Aug 6, 2026
…#519)
* emrg: evolution_prompt quick-ref — add #518 LLM error redaction entry
* emrg: re-trigger CI (runner cancellation)
---------
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero