mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-02 07:11:49 +00:00
fix(security): tighten .env file permissions to 0600 at all creation sites
.env holds API keys and secrets. Multiple creation sites used `cp` / `touch` / `shutil.copy2` which obey the process umask — commonly 0o022, leaving the file at 0o644 (world-readable). Apply chmod 0o600 explicitly at every site that creates or copies .env. Sites covered: - docker/stage2-hook.sh: after the seed_one '.env' call, applied unconditionally (not just on first-seed) so a host-mounted .env with loose perms gets tightened on every container restart - hermes_cli/doctor.py: 'hermes doctor --fix' touches an empty .env when missing - hermes_cli/profiles.py: 'hermes profile create --clone' copies .env from the source profile; shutil.copy2 preserves source mode, so a source .env at 0o644 was being cloned into 0o644 - setup-hermes.sh: in-tree setup script's cp .env.example .env path, plus the already-exists branch (mirror of install.sh which already chmods 600 unconditionally on line 1442) scripts/install.sh was NOT changed — it already chmod 600's the .env unconditionally after the create/already-exists branches (line 1442). Salvaged from PR #25726 by @dusterbloom. The docker/entrypoint.sh portion of the original PR was dropped because main switched to an s6-overlay shim — the .env creation logic moved to stage2-hook.sh, which is where the chmod now lives. Closes #25497 (subset — install.sh + setup-hermes.sh) and #8448 (subset — install.sh only) as superseded. Co-authored-by: teknium1 <127238744+teknium1@users.noreply.github.com>
This commit is contained in:
parent
4cb3eb03c7
commit
79fc92e9cb
4 changed files with 32 additions and 1 deletions
|
|
@ -111,6 +111,14 @@ seed_one ".env" ".env.example"
|
|||
seed_one "config.yaml" "cli-config.yaml.example"
|
||||
seed_one "SOUL.md" "docker/SOUL.md"
|
||||
|
||||
# .env holds API keys and secrets — restrict to owner-only access. Applied
|
||||
# unconditionally (not only on first-seed) so a host-mounted .env that was
|
||||
# created with a permissive umask gets tightened on every container start.
|
||||
if [ -f "$HERMES_HOME/.env" ]; then
|
||||
chown hermes:hermes "$HERMES_HOME/.env" 2>/dev/null || true
|
||||
chmod 600 "$HERMES_HOME/.env" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# auth.json: bootstrap from env on first boot only. Same semantics as the
|
||||
# pre-s6 entrypoint — the [ ! -f ] guard is critical to avoid clobbering
|
||||
# rotated refresh tokens on container restart.
|
||||
|
|
|
|||
|
|
@ -569,6 +569,13 @@ def run_doctor(args):
|
|||
if should_fix:
|
||||
env_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
env_path.touch()
|
||||
# .env holds API keys — restrict to owner-only access from
|
||||
# creation. touch() obeys umask which is commonly 0o022,
|
||||
# leaving the file world-readable; tighten explicitly.
|
||||
try:
|
||||
os.chmod(str(env_path), 0o600)
|
||||
except OSError:
|
||||
pass
|
||||
check_ok(f"Created empty {_DHH}/.env")
|
||||
check_info("Run 'hermes setup' to configure API keys")
|
||||
fixed_count += 1
|
||||
|
|
|
|||
|
|
@ -723,7 +723,17 @@ def create_profile(
|
|||
for filename in _CLONE_CONFIG_FILES:
|
||||
src = source_dir / filename
|
||||
if src.exists():
|
||||
shutil.copy2(src, profile_dir / filename)
|
||||
dst = profile_dir / filename
|
||||
shutil.copy2(src, dst)
|
||||
# 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:
|
||||
pass
|
||||
|
||||
# Clone installed skills from the source profile. The dashboard's
|
||||
# "clone from default" flow is expected to preserve both bundled
|
||||
|
|
|
|||
|
|
@ -329,9 +329,15 @@ fi
|
|||
if [ ! -f ".env" ]; then
|
||||
if [ -f ".env.example" ]; then
|
||||
cp .env.example .env
|
||||
# .env holds API keys — restrict to owner-only access (matches
|
||||
# scripts/install.sh which already chmods 600 after creation).
|
||||
chmod 600 .env 2>/dev/null || true
|
||||
echo -e "${GREEN}✓${NC} Created .env from template"
|
||||
fi
|
||||
else
|
||||
# Tighten an existing .env's perms in case it was created elsewhere
|
||||
# under a permissive umask.
|
||||
chmod 600 .env 2>/dev/null || true
|
||||
echo -e "${GREEN}✓${NC} .env exists"
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue