diff --git a/src/commands/doctor-state-integrity.ts b/src/commands/doctor-state-integrity.ts index bccb04964eb..2e31da8e76a 100644 --- a/src/commands/doctor-state-integrity.ts +++ b/src/commands/doctor-state-integrity.ts @@ -261,8 +261,15 @@ export async function noteStateIntegrity( } if (stateDirExists && process.platform !== "win32") { try { - const stat = fs.statSync(stateDir); - if ((stat.mode & 0o077) !== 0) { + const dirLstat = fs.lstatSync(stateDir); + const isDirSymlink = dirLstat.isSymbolicLink(); + // For symlinks, check the resolved target permissions instead of the + // symlink itself (which always reports 777). Skip the warning only when + // the target lives in a known immutable store (e.g. /nix/store/). + const stat = isDirSymlink ? fs.statSync(stateDir) : dirLstat; + const resolvedDir = isDirSymlink ? fs.realpathSync(stateDir) : stateDir; + const isImmutableStore = resolvedDir.startsWith("/nix/store/"); + if (!isImmutableStore && (stat.mode & 0o077) !== 0) { warnings.push( `- State directory permissions are too open (${displayStateDir}). Recommend chmod 700.`, ); @@ -282,10 +289,14 @@ export async function noteStateIntegrity( if (configPath && existsFile(configPath) && process.platform !== "win32") { try { - const linkStat = fs.lstatSync(configPath); - const stat = fs.statSync(configPath); - const isSymlink = linkStat.isSymbolicLink(); - if (!isSymlink && (stat.mode & 0o077) !== 0) { + const configLstat = fs.lstatSync(configPath); + const isSymlink = configLstat.isSymbolicLink(); + // For symlinks, check the resolved target permissions. Skip the warning + // only when the target lives in an immutable store (e.g. /nix/store/). + const stat = isSymlink ? fs.statSync(configPath) : configLstat; + const resolvedConfig = isSymlink ? fs.realpathSync(configPath) : configPath; + const isImmutableConfig = resolvedConfig.startsWith("/nix/store/"); + if (!isImmutableConfig && (stat.mode & 0o077) !== 0) { warnings.push( `- Config file is group/world readable (${displayConfigPath ?? configPath}). Recommend chmod 600.`, );