Fix Windows volume sandbox check on Linux CI.
Treat drive-letter mount sources with path.win32 so C:\ paths are not nested under the workspace on POSIX hosts.
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import path from 'node:path';
|
||||||
import Docker from 'dockerode';
|
import Docker from 'dockerode';
|
||||||
import { config } from '../../config.js';
|
import { config } from '../../config.js';
|
||||||
import { resolveWorkspacePath, SandboxViolationError } from '../../lib/sandbox.js';
|
import { resolveWorkspacePath, SandboxViolationError } from '../../lib/sandbox.js';
|
||||||
@@ -157,6 +158,10 @@ export function parseVolumeMountSpec(spec: string): { source: string; target: st
|
|||||||
/**
|
/**
|
||||||
* Validates that a volume mount specification keeps the source path inside the
|
* Validates that a volume mount specification keeps the source path inside the
|
||||||
* workspace root. Rejects Docker socket mounts, host-relative escapes, etc.
|
* workspace root. Rejects Docker socket mounts, host-relative escapes, etc.
|
||||||
|
*
|
||||||
|
* Windows drive-letter sources are checked with path.win32 so POSIX hosts do not
|
||||||
|
* treat `C:\\...` as a relative segment under the workspace (which would falsely
|
||||||
|
* allow mounts like `C:\\Windows\\System32` in Linux CI).
|
||||||
*/
|
*/
|
||||||
export function validateVolumeMount(spec: string): { source: string; target: string; mode: string } {
|
export function validateVolumeMount(spec: string): { source: string; target: string; mode: string } {
|
||||||
const { source, target, mode } = parseVolumeMountSpec(spec);
|
const { source, target, mode } = parseVolumeMountSpec(spec);
|
||||||
@@ -168,6 +173,20 @@ export function validateVolumeMount(spec: string): { source: string; target: str
|
|||||||
) {
|
) {
|
||||||
throw new SandboxViolationError(`Refusing to mount the Docker socket: "${source}".`);
|
throw new SandboxViolationError(`Refusing to mount the Docker socket: "${source}".`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (/^[A-Za-z]:[\\/]/.test(source)) {
|
||||||
|
const absoluteSource = path.win32.resolve(source);
|
||||||
|
const absoluteRoot = path.win32.resolve(config.workspaceRoot);
|
||||||
|
const rootNorm = absoluteRoot.toLowerCase();
|
||||||
|
const sourceNorm = absoluteSource.toLowerCase();
|
||||||
|
if (sourceNorm !== rootNorm && !sourceNorm.startsWith(rootNorm + '\\')) {
|
||||||
|
throw new SandboxViolationError(
|
||||||
|
`Refusing to access "${source}": it resolves outside the workspace root (${config.workspaceRoot}).`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return { source: absoluteSource, target, mode };
|
||||||
|
}
|
||||||
|
|
||||||
const absoluteSource = resolveWorkspacePath(config.workspaceRoot, source);
|
const absoluteSource = resolveWorkspacePath(config.workspaceRoot, source);
|
||||||
return { source: absoluteSource, target, mode };
|
return { source: absoluteSource, target, mode };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user