import { describe, it, expect } from 'vitest'; import { psContentBlock } from './powershell-destructive.mjs'; // NB: for-of + it() (не it.each) — активный пол tdd-real-test-verifier распознаёт только it(. // M7 Task 1.2 (V1-PS, реоткрытие v3.8 F1): PS-нативные глаголы НЕ матчат unix-regex // classify-destructive → отдельный набор content-block для PowerShell-tool. describe('psContentBlock (V1-PS, реоткрытие v3.8 F1)', () => { const BLOCKED = [ 'Remove-Item -Recurse -Force C:\\x', 'rm -r -fo C:\\x', 'Invoke-WebRequest https://e.rf', 'iwr https://e.rf', 'curl https://e.rf', 'Invoke-Expression $x', 'iex $x', 'Get-Content x | Out-File y', 'echo x > y', 'echo x >> y', 'Start-Process node', 'Start-Process powershell', ]; for (const cmd of BLOCKED) { it(`blocks PS content: ${cmd}`, () => { expect(psContentBlock(cmd)).toBe(true); }); } const ALLOWED = ['Get-ChildItem', 'Get-Content x', 'Test-Path x', 'Write-Output ok']; for (const cmd of ALLOWED) { it(`does NOT block safe PS: ${cmd}`, () => { expect(psContentBlock(cmd)).toBe(false); }); } }); // sharp-edges (после 1.4): Remove-Item алиасы (ri/del/rd/rmdir/erase) обходят литеральный глагол. describe('psContentBlock — Remove-Item алиасы (sharp-edges)', () => { const BLOCKED = [ 'del -Recurse -Force C:\\x', 'ri -r -fo C:\\x', 'rd -Recurse -Force C:\\x', 'rmdir -r -f /tmp/x', 'erase -Recurse -Force C:\\x', ]; for (const cmd of BLOCKED) { it(`blocks Remove-Item alias: ${cmd}`, () => { expect(psContentBlock(cmd)).toBe(true); }); } // Контроль: алиас-токен без recurse+force флагов не over-блокируется. const ALLOWED = ['Get-Content del.txt', 'Write-Output "ri done"', 'Test-Path rd']; for (const cmd of ALLOWED) { it(`does NOT block alias-token без recurse+force: ${cmd}`, () => { expect(psContentBlock(cmd)).toBe(false); }); } });