fix(auth): read .env as utf-8-sig in the dotenv-vs-shell detector - #60895
fix(auth): read .env as utf-8-sig in the dotenv-vs-shell detector#60895solyanviktor-star wants to merge 1 commit into
Conversation
falkoro
left a comment
There was a problem hiding this comment.
Community review — verified this against the codebase and reproduced the bug locally.
The canonical .env readers already use encoding="utf-8-sig", errors="replace" (two sites in hermes_cli/config.py, with a comment about Notepad BOMs), so this brings the dotenv-vs-shell detector in line with them. Repro with a BOM'd first line (b'\xef\xbb\xbfDEEPSEEK_API_KEY=...'): the current reader fails to find the var (startswith sees \ufeffDEEPSEEK...), the patched reader finds it — exactly the misreported shell-export hint from the issue. read_text() with no encoding also decodes via the system locale (cp1252/GBK on Windows), so this fixes non-ASCII values in .env as a bonus. The regression test covers the BOM'd-first-line case specifically. LGTM from a community perspective.
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Comment (token read-only)
PR 60895 fixes .env file reading with UTF-8-sig encoding (BOM). Ensures the dotenv-vs-shell detector properly handles BOM-encoded .env files. Well-scoped (2 files, 52 additions, 1 deletion). No security issues or debug artifacts detected.
LGTM - awaiting maintainer approval.
|
Thanks for the focused regression fix. Current Automated hermes-sweeper review. |
_remove_env_source() decides whether a credential var lives in ~/.hermes/.env
or the shell by scanning the .env with env_path.read_text(errors="replace") —
no encoding. read_text() with no encoding falls back to the system locale
(cp1252/GBK on Windows) and never strips a BOM.
The canonical .env readers in hermes_cli/config.py all use
encoding="utf-8-sig" precisely because 'users may edit .env in Notepad which
adds one' (a BOM), and doctor.py documents that .env is written as UTF-8
everywhere. This sibling reader diverged: on a Notepad-edited .env the BOM
prefixes the first line, so line.strip().startswith(f"{env_var}=") is False
for the first variable — the detector reports a .env-backed key as a phantom
shell export and prints a misleading 'still set in your shell environment'
hint on .
Match the canonical reader (utf-8-sig + errors=replace). Adds a regression
test with a BOM'd .env.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
456e28e to
1b6f5b4
Compare
|
Rebased onto current main after the #71078 class sweep (and thanks for salvaging my four sibling PRs there — much appreciated!). One detail survived the sweep at this site: 75e0d52 pinned this reader to plain This PR is now the minimal delta on top of the sweep: |
Graph note (no action implied — a maintainer has already reviewed this thread). Our triage graph places this PR in a complex with 1 related pull request ( Full neighbourhood: https://hermes-triage.gottz.de/?node=60895 This note exists so the relationship stays discoverable from the thread itself. |
|
Merged in #81967 with authorship (dotenv-vs-shell detector utf-8-sig; test regrafted). Thanks! |
Problem
_remove_env_source()inagent/credential_sources.pydecides whether a credential variable lives in~/.hermes/.envor in the shell environment, to give the righthermes auth removehint. It scans the .env like this:read_text()with noencodingfalls back to the system locale (cp1252/GBK on Windows) and never strips a BOM. This diverges from the documented codebase invariant:hermes_cli/config.pyreads .env withencoding="utf-8-sig"in every canonical path, with the explicit comment: "tolerate BOM via utf-8-sig since users may edit .env in Notepad which adds one."hermes_cli/doctor.py: ".env files are written as UTF-8 everywhere in the codebase, while Path.read_text() defaults to the system locale — which crashes on non-UTF-8 Windows locales."So on a Notepad-edited .env (UTF-8 BOM), the BOM prefixes the first line —
"\ufeffOPENAI_API_KEY=..."— andstartswith("OPENAI_API_KEY=")is False for the first variable in the file. The detector then concludes the var isn't in .env and prints a misleading hint that it's "still set in your shell environment" when it is not.Repro (Windows, cp1251)
Fix
Read the .env with
encoding="utf-8-sig", errors="replace", matching the canonical readers inconfig.py.Tests
Added
test_auth_remove_env_seeded_dotenv_with_bom_no_shell_hint: a BOM'd .env with the target var on the first line — asserts the removal clears it from .env and does not print the phantom shell-export warning. Verified it fails on the pre-fix reader and passes after.python -m pytest tests/hermes_cli/test_auth_commands.py— 53 passed.🤖 Generated with Claude Code