test(sandbox): cover POSIX no-shebang fallback
This commit is contained in:
@@ -132,27 +132,52 @@ describe('partial Landlock runner-failure classification', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('keeps a real malformed executable ENOEXEC as an ordinary spawn failure', async () => {
|
it('keeps a real malformed executable ordinary across no-shebang spawn behavior', async () => {
|
||||||
const dir = await mkdtemp(join(tmpdir(), 'dsh-malformed-sandbox-runner-'))
|
const dir = await mkdtemp(join(tmpdir(), 'dsh-malformed-sandbox-runner-'))
|
||||||
tempDirs.push(dir)
|
tempDirs.push(dir)
|
||||||
const runner = join(dir, 'malformed-runner')
|
const runner = join(dir, 'malformed-runner')
|
||||||
await writeFile(runner, 'not a native executable or shebang script\n', { mode: 0o755 })
|
await writeFile(runner, 'not a native executable or shebang script\n', { mode: 0o755 })
|
||||||
const bash = await setupConfiguredRunner(runner)
|
const bash = await setupConfiguredRunner(runner)
|
||||||
|
const request = { command: 'true' }
|
||||||
|
|
||||||
const foreground = await bash.run(bash.resolve({ command: 'true' })).catch((value: unknown) => value)
|
// Node/libuv may expose execve's ENOEXEC directly (Darwin) or retry a
|
||||||
expect(foreground).toMatchObject({ code: 'ENOEXEC', syscall: 'spawn' })
|
// no-shebang executable through /bin/sh (Linux). Neither path supplies the
|
||||||
expect((foreground as { path?: unknown }).path).toBeUndefined()
|
// provenanced ENOENT/EACCES evidence required for runner attribution.
|
||||||
|
const foreground = await bash.run(bash.resolve(request)).catch((value: unknown) => value)
|
||||||
expect(foreground).not.toBeInstanceOf(SandboxUnavailableError)
|
expect(foreground).not.toBeInstanceOf(SandboxUnavailableError)
|
||||||
|
|
||||||
let background: unknown
|
if (foreground instanceof Error) {
|
||||||
try {
|
expect(foreground).toMatchObject({ code: 'ENOEXEC', syscall: 'spawn' })
|
||||||
bash.start(bash.resolve({ command: 'true' }))
|
expect((foreground as { path?: unknown }).path).toBeUndefined()
|
||||||
} catch (error) {
|
|
||||||
background = error
|
let background: unknown
|
||||||
|
try {
|
||||||
|
bash.start(bash.resolve(request))
|
||||||
|
} catch (error) {
|
||||||
|
background = error
|
||||||
|
}
|
||||||
|
expect(background).toMatchObject({ code: 'ENOEXEC', syscall: 'spawn' })
|
||||||
|
expect((background as { path?: unknown }).path).toBeUndefined()
|
||||||
|
expect(background).not.toBeInstanceOf(SandboxUnavailableError)
|
||||||
|
} else {
|
||||||
|
expect(foreground).toMatchObject({
|
||||||
|
exitCode: 127,
|
||||||
|
signal: null,
|
||||||
|
sandbox: { mode: 'read-only', denied: false, enforcement: 'full' },
|
||||||
|
})
|
||||||
|
expect((foreground as { stderr: { text: string } }).stderr.text).toMatch(/not.*not found/)
|
||||||
|
|
||||||
|
const background = bash.start(bash.resolve(request))
|
||||||
|
await background.done
|
||||||
|
expect(background.status).toBe('completed')
|
||||||
|
expect(background.exitCode).toBe(127)
|
||||||
|
expect(background.signal).toBeNull()
|
||||||
|
expect(background.sandbox).toEqual({ mode: 'read-only', denied: false, enforcement: 'full' })
|
||||||
|
const output = background.readOutput().delta
|
||||||
|
expect(output).toMatch(/\[stderr\]\n[\s\S]*not.*not found/)
|
||||||
|
expect(output).not.toContain('spawn failed:')
|
||||||
}
|
}
|
||||||
expect(background).toMatchObject({ code: 'ENOEXEC', syscall: 'spawn' })
|
|
||||||
expect((background as { path?: unknown }).path).toBeUndefined()
|
|
||||||
expect(background).not.toBeInstanceOf(SandboxUnavailableError)
|
|
||||||
const accounting = (bash as unknown as { processFacts: Map<unknown, unknown> }).processFacts
|
const accounting = (bash as unknown as { processFacts: Map<unknown, unknown> }).processFacts
|
||||||
expect(accounting.size).toBe(0)
|
expect(accounting.size).toBe(0)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user