Fix 16 HIGH/MEDIUM security bugs across API
HIGH fixes: - TOTP disable now requires valid code verification - TOTP secret removed from plaintext file storage - Container ID validated before update/check-update/logs operations - DNS server parameter restricted to configured servers (SSRF prevention) - Backup export no longer includes encryption key - Backup restore of sensitive files requires TOTP re-authentication MEDIUM fixes: - Session cookie Secure flag added - Caddy reload errors no longer leaked to client - saveConfig uses atomic locked updates via configStateManager - Log file path traversal prevented via symlink resolution - Credential cache entries now expire after 5 minutes - _httpFetch enforces 10MB response size limit - External URL path injection into Caddyfile blocked - Custom volume host paths validated against allowed roots - Error logs endpoint no longer returns stack traces - Logo delete path traversal prevented via path.basename() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -129,7 +129,22 @@ module.exports = function(ctx) {
|
||||
const parts = vol.split(':');
|
||||
const containerPath = parts.slice(1).join(':');
|
||||
const override = config.customVolumes.find(cv => cv.containerPath === containerPath);
|
||||
if (override && override.hostPath) return `${toDockerDesktopPath(override.hostPath)}:${containerPath}`;
|
||||
if (override && override.hostPath) {
|
||||
// Validate host path is under allowed roots (docker data dir or media paths)
|
||||
const normalizedHost = path.resolve(override.hostPath);
|
||||
const allowedRoots = [path.resolve(platformPaths.dockerData)];
|
||||
if (config.mediaPath) {
|
||||
config.mediaPath.split(',').map(p => p.trim()).filter(Boolean).forEach(p => allowedRoots.push(path.resolve(p)));
|
||||
}
|
||||
const isAllowed = allowedRoots.some(root =>
|
||||
normalizedHost === root || normalizedHost.startsWith(root + path.sep)
|
||||
);
|
||||
if (!isAllowed) {
|
||||
ctx.log.warn('deploy', 'Custom volume host path rejected', { hostPath: override.hostPath, allowed: allowedRoots });
|
||||
return vol; // Keep original volume, don't apply unsafe override
|
||||
}
|
||||
return `${toDockerDesktopPath(override.hostPath)}:${containerPath}`;
|
||||
}
|
||||
return vol;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user