66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
/** Canonical path-overlap checks that keep workspace and temp capabilities separate. */
|
|
|
|
import { mkdirSync, mkdtempSync, rmSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
|
|
import { assertPrivateTempDisjoint, assertTempRootOutsideWorkspace } from '../src/path-boundary.ts'
|
|
|
|
describe('Windows ACL temp path boundary', () => {
|
|
const scratchDirs: string[] = []
|
|
|
|
afterEach(() => {
|
|
for (const dir of scratchDirs.splice(0)) rmSync(dir, { recursive: true, force: true })
|
|
})
|
|
|
|
function scratch(): string {
|
|
const dir = mkdtempSync(join(tmpdir(), 'dsh-acl-boundary-'))
|
|
scratchDirs.push(dir)
|
|
return dir
|
|
}
|
|
|
|
it('rejects a temp root equal to or below the workspace', () => {
|
|
const workspace = scratch()
|
|
const nested = join(workspace, 'temp')
|
|
mkdirSync(nested)
|
|
|
|
expect(() => {
|
|
assertTempRootOutsideWorkspace(workspace, workspace)
|
|
}).toThrow(/temp root must be outside the workspace/u)
|
|
expect(() => {
|
|
assertTempRootOutsideWorkspace(workspace, nested)
|
|
}).toThrow(/temp root must be outside the workspace/u)
|
|
})
|
|
|
|
it('accepts a temp parent above the workspace because a fresh child is a sibling', () => {
|
|
const tempRoot = scratch()
|
|
const workspace = join(tempRoot, 'workspace')
|
|
mkdirSync(workspace)
|
|
|
|
expect(() => {
|
|
assertTempRootOutsideWorkspace(workspace, tempRoot)
|
|
}).not.toThrow()
|
|
})
|
|
|
|
it('requires an actual private temp directory to be disjoint in either direction', () => {
|
|
const root = scratch()
|
|
const workspace = join(root, 'workspace')
|
|
const nestedTemp = join(workspace, 'temp')
|
|
const siblingTemp = join(root, 'sibling-temp')
|
|
mkdirSync(workspace)
|
|
mkdirSync(nestedTemp)
|
|
mkdirSync(siblingTemp)
|
|
|
|
expect(() => {
|
|
assertPrivateTempDisjoint([workspace], nestedTemp)
|
|
}).toThrow(/must be disjoint/u)
|
|
expect(() => {
|
|
assertPrivateTempDisjoint([nestedTemp], workspace)
|
|
}).toThrow(/must be disjoint/u)
|
|
expect(() => {
|
|
assertPrivateTempDisjoint([workspace], siblingTemp)
|
|
}).not.toThrow()
|
|
})
|
|
})
|