Files
brain/tools/enforce-powershell-gate.test.mjs

99 lines
3.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from 'vitest';
import { tokenizePowerShell, matchPsHardBlacklist } from './enforce-powershell-gate.mjs';
describe('tokenizePowerShell', () => {
it('splits on ; and | into segments', () => {
const segs = tokenizePowerShell('Get-Content a | Select-String x ; Get-Item b');
expect(segs.map((s) => s.cmd)).toEqual(['get-content', 'select-string', 'get-item']);
});
});
describe('matchPsHardBlacklist — keep', () => {
it.each([
'Remove-Item x',
'ri x',
'del x',
'Move-Item a b',
'Copy-Item a b',
'Set-Content x "y"',
'Add-Content x "y"',
'Out-File -FilePath x',
'cmd > out.txt',
'Invoke-Expression $x',
'iex $x',
'Start-Process notepad',
'[System.IO.File]::Delete("x")',
'Stop-Process -Name node',
'Set-ExecutionPolicy Bypass',
'icacls x /grant y',
])('blocks %s', (cmd) => {
expect(matchPsHardBlacklist(cmd)).toBeTruthy();
});
});
describe('matchPsHardBlacklist — v4.1 G10', () => {
it.each([
'$env:PATH = "x"',
'$env:ROUTER_LLM_KEY="leak"',
'[System.Environment]::SetEnvironmentVariable("X","Y")',
'Set-Item -Path Env:FOO -Value bar',
'New-PSDrive -Name X -PSProvider FileSystem -Root C:\\',
'Get-AzVM',
'New-AzResourceGroup x',
'Get-AWSCredential',
'gcloud auth login',
])('blocks %s', (cmd) => {
expect(matchPsHardBlacklist(cmd)).toBeTruthy();
});
});
describe('matchPsHardBlacklist — allows benign', () => {
it.each(['Get-ChildItem', 'Get-Content app/x.php', 'Select-String x file', 'git status'])('allows %s', (cmd) => {
expect(matchPsHardBlacklist(cmd)).toBe(null);
});
});
import { classifyPowerShellCommand } from './enforce-powershell-gate.mjs';
describe('classifyPowerShellCommand', () => {
const now = 4_000_000;
it('allows whitelisted reading cmdlet', () => {
expect(classifyPowerShellCommand('Get-ChildItem -Path app', {}).result).toBe('allow');
});
it('allows alias gci', () => {
expect(classifyPowerShellCommand('gci', {}).result).toBe('allow');
});
it('blocks hard-blacklisted Remove-Item', () => {
expect(classifyPowerShellCommand('Remove-Item x', {}).result).toBe('block');
});
it('blocks G10 $env set', () => {
expect(classifyPowerShellCommand('$env:PATH="x"', {}).result).toBe('block');
});
it('blocks reading a protected path', () => {
expect(classifyPowerShellCommand('Get-Content ~/.claude/settings.json', {}).result).toBe('block');
});
it('routes git through shared classifier (block unapproved commit)', () => {
expect(classifyPowerShellCommand('git commit -m "x"', { approvedGitOps: [], now }).result).toBe('block');
});
it('allows readonly git through PowerShell', () => {
expect(classifyPowerShellCommand('git status', {}).result).toBe('allow');
});
it('default-denies unknown cmdlet', () => {
expect(classifyPowerShellCommand('Frobnicate-Thing', {}).result).toBe('block');
});
});
// M7 PS single-source: powershell-gate ре-экспортирует матчер из единого дома shell-content-rules.
// Идентичность ссылки доказывает «единый источник, не копия» (зеркало Bash P-1). content-floor (М5)
// импортирует ТОТ ЖЕ матчер → дрейф подмножествами невозможен по конструкции.
import { matchPsHardBlacklist as PG_MATCH, PS_HARD_BLACKLIST as PG_LIST } from './enforce-powershell-gate.mjs';
import { matchPsHardBlacklist as SCR_PS_MATCH, PS_HARD_BLACKLIST as SCR_PS_LIST } from './shell-content-rules.mjs';
describe('powershell-gate re-exports single-source PS matcher (M7)', () => {
it('matchPsHardBlacklist is the SAME reference as shell-content-rules', () => {
expect(PG_MATCH).toBe(SCR_PS_MATCH);
});
it('PS_HARD_BLACKLIST is the SAME reference as shell-content-rules', () => {
expect(PG_LIST).toBe(SCR_PS_LIST);
});
});