Add mount security allowlist for external directory access (#14)
* Add secure mount allowlist validation Addresses arbitrary host mount vulnerability by validating additional mounts against an external allowlist stored at ~/.config/nanoclaw/. This location is never mounted into containers, making it tamper-proof. Security measures: - Allowlist cached in memory (edits require process restart) - Real path resolution (blocks symlink and .. traversal attacks) - Blocked patterns for sensitive paths (.ssh, .gnupg, .aws, etc.) - Non-main groups forced to read-only when nonMainReadOnly is true - Container path validation prevents /workspace/extra escape https://claude.ai/code/session_01BPqdNy4EAHHJcdtZ27TXkh * Add mount allowlist setup to /setup skill Interactive walkthrough that asks users: - Whether they want agents to access external directories - Which directories to allow (with paths) - Read-write vs read-only for each - Whether non-main groups should be restricted to read-only Creates ~/.config/nanoclaw/mount-allowlist.json based on answers. https://claude.ai/code/session_01BPqdNy4EAHHJcdtZ27TXkh --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
DATA_DIR
|
||||
} from './config.js';
|
||||
import { RegisteredGroup } from './types.js';
|
||||
import { validateAdditionalMounts } from './mount-security.js';
|
||||
|
||||
const logger = pino({
|
||||
level: process.env.LOG_LEVEL || 'info',
|
||||
@@ -151,22 +152,14 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount
|
||||
}
|
||||
}
|
||||
|
||||
// Additional mounts validated against external allowlist (tamper-proof from containers)
|
||||
if (group.containerConfig?.additionalMounts) {
|
||||
for (const mount of group.containerConfig.additionalMounts) {
|
||||
const hostPath = mount.hostPath.startsWith('~')
|
||||
? path.join(homeDir, mount.hostPath.slice(1))
|
||||
: mount.hostPath;
|
||||
|
||||
if (fs.existsSync(hostPath)) {
|
||||
mounts.push({
|
||||
hostPath,
|
||||
containerPath: `/workspace/extra/${mount.containerPath}`,
|
||||
readonly: mount.readonly !== false // Default to readonly for safety
|
||||
});
|
||||
} else {
|
||||
logger.warn({ hostPath }, 'Additional mount path does not exist, skipping');
|
||||
}
|
||||
}
|
||||
const validatedMounts = validateAdditionalMounts(
|
||||
group.containerConfig.additionalMounts,
|
||||
group.name,
|
||||
isMain
|
||||
);
|
||||
mounts.push(...validatedMounts);
|
||||
}
|
||||
|
||||
return mounts;
|
||||
|
||||
Reference in New Issue
Block a user