From be78fbd70e448a8594d86679cb8987a7fb84124a Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Tue, 23 Jun 2026 23:58:43 -0700 Subject: [PATCH] Revert "fix(profiles): clone auth.json so OAuth credentials carry to cloned profiles (#51719)" (#51732) This reverts commit f504aecffe7fe8fdad9fb2baeae3839701929877. --- hermes_cli/profiles.py | 23 +++++------------------ tests/hermes_cli/test_profiles.py | 22 ---------------------- 2 files changed, 5 insertions(+), 40 deletions(-) diff --git a/hermes_cli/profiles.py b/hermes_cli/profiles.py index 6b5544ca093..025eff5176c 100644 --- a/hermes_cli/profiles.py +++ b/hermes_cli/profiles.py @@ -53,21 +53,9 @@ _PROFILE_DIRS = [ ] # Files copied during --clone (if they exist in the source) -# -# auth.json carries the per-profile credential pool — including OAuth tokens -# (Anthropic `claude /login`, Codex, xAI) that never land in .env. Cloning -# .env but not auth.json silently dropped those credentials from the clone, -# so a profile cloned from an OAuth-authenticated default resolved a -# different provider (or none) than the source. The global-root fallback in -# read_credential_pool only masks this while the clone's HERMES_HOME still -# resolves to the same default root and the user hasn't run `hermes auth add` -# locally. Copying it here makes selective --clone match `.env` semantics and -# the full --clone-all copytree (which already carries auth.json). Both are -# credential files and get tightened to owner-only (0o600) after copy. _CLONE_CONFIG_FILES = [ "config.yaml", ".env", - "auth.json", "SOUL.md", ] @@ -950,12 +938,11 @@ def create_profile( if src.exists(): dst = profile_dir / filename shutil.copy2(src, dst) - # Tighten credential files to owner-only after copy. - # shutil.copy2 preserves source mode bits, but if the - # source's .env / auth.json was loose (host umask 0o022 - # leaving 0o644), tighten explicitly so the clone doesn't - # inherit weak perms. - if filename in {".env", "auth.json"}: + # Tighten .env to owner-only after copy. shutil.copy2 + # preserves source mode bits, but if the source's .env + # was loose (host umask 0o022 leaving 0o644), tighten + # explicitly so the clone doesn't inherit weak perms. + if filename == ".env": try: os.chmod(str(dst), 0o600) except OSError: diff --git a/tests/hermes_cli/test_profiles.py b/tests/hermes_cli/test_profiles.py index edc5a82f86f..29840d8c728 100644 --- a/tests/hermes_cli/test_profiles.py +++ b/tests/hermes_cli/test_profiles.py @@ -7,7 +7,6 @@ and shell completion generation. import json import io -import os import tarfile from pathlib import Path from unittest.mock import patch, MagicMock @@ -216,27 +215,6 @@ class TestCreateProfile: assert (profile_dir / ".env").read_text().strip() == "KEY=val" assert (profile_dir / "SOUL.md").read_text() == "Be helpful." - def test_clone_config_copies_auth_json(self, profile_env): - # auth.json holds the credential pool (incl. OAuth tokens that never - # land in .env). Selective --clone must carry it so a profile cloned - # from an OAuth-authenticated source keeps the same credentials, - # matching --clone-all and .env semantics. - tmp_path = profile_env - default_home = tmp_path / ".hermes" - (default_home / "auth.json").write_text( - '{"credential_pool": {"anthropic": [{"access_token": "tok"}]}}' - ) - - profile_dir = create_profile("coder", clone_config=True, no_alias=True) - - cloned_auth = profile_dir / "auth.json" - assert cloned_auth.exists() - cloned = json.loads(cloned_auth.read_text()) - assert cloned["credential_pool"]["anthropic"][0]["access_token"] == "tok" - # Credential file must be tightened to owner-only, like .env. - if os.name == "posix": - assert (cloned_auth.stat().st_mode & 0o777) == 0o600 - def test_clone_config_migrates_legacy_config_version(self, profile_env): tmp_path = profile_env default_home = tmp_path / ".hermes"