From 31ee1024c5bda4ea2dd49057a45c96604b664cf7 Mon Sep 17 00:00:00 2001 From: Jochen Meyer Date: Wed, 15 Apr 2026 09:57:48 +0200 Subject: [PATCH] fix: restrict ~/.claude-mem/.env permissions to owner-only (0600) (#1770) * fix: restrict .env file permissions to owner-only (0600) API keys stored in ~/.claude-mem/.env were created without explicit permissions, defaulting to umask-dependent mode. On systems with a permissive umask (e.g. 0022), the file would be world-readable. - Set directory permissions to 0700 on creation - Set file permissions to 0600 via writeFileSync mode option - Call chmodSync after write to fix permissions on pre-existing files Signed-off-by: Jochen Meyer * fix: also restrict pre-existing directory permissions to 0700 The initial fix only set directory mode on creation. Pre-existing ~/.claude-mem/ directories from earlier installs remained world-readable. Add chmodSync for the directory alongside the existing file chmod, and document the Windows limitation (ACLs, not POSIX permissions). --------- Signed-off-by: Jochen Meyer --- src/shared/EnvManager.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/shared/EnvManager.ts b/src/shared/EnvManager.ts index eca3120e..6bfad6b8 100644 --- a/src/shared/EnvManager.ts +++ b/src/shared/EnvManager.ts @@ -9,7 +9,7 @@ * causing memory operations to bill personal API accounts instead of CLI subscription. */ -import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'; +import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } from 'fs'; import { join, dirname } from 'path'; import { homedir } from 'os'; import { logger } from '../utils/logger.js'; @@ -132,10 +132,13 @@ export function loadClaudeMemEnv(): ClaudeMemEnv { */ export function saveClaudeMemEnv(env: ClaudeMemEnv): void { try { - // Ensure directory exists + // Ensure directory exists with restricted permissions (owner only) if (!existsSync(DATA_DIR)) { - mkdirSync(DATA_DIR, { recursive: true }); + mkdirSync(DATA_DIR, { recursive: true, mode: 0o700 }); } + // Fix permissions on pre-existing directories (mode: is only applied on creation) + // Note: On Windows, chmod has no effect — permissions are controlled via ACLs. + chmodSync(DATA_DIR, 0o700); // Load existing to preserve any extra keys const existing = existsSync(ENV_FILE_PATH) @@ -175,7 +178,11 @@ export function saveClaudeMemEnv(env: ClaudeMemEnv): void { } } - writeFileSync(ENV_FILE_PATH, serializeEnvFile(updated), 'utf-8'); + writeFileSync(ENV_FILE_PATH, serializeEnvFile(updated), { encoding: 'utf-8', mode: 0o600 }); + // Explicitly set permissions in case the file already existed before this fix. + // writeFileSync's mode option only applies on file creation (O_CREAT), not on overwrites. + // Note: On Windows, chmod has no effect — permissions are controlled via ACLs. + chmodSync(ENV_FILE_PATH, 0o600); } catch (error) { logger.error('ENV', 'Failed to save .env file', { path: ENV_FILE_PATH }, error as Error); throw error;