Files
portal/tools/powershell-destructive.test.mjs
T
Дмитрий 183733835f harden(m7-floor): PS-алиасы forge+delete (sharp-edges после 1.4)
Строгий sharp-edges-гейт после Task 1.4 вскрыл обход через PowerShell-алиасы:
- forge P-3: `sc`/`cpi`/`ni` (алиасы Set-Content/Copy-Item/New-Item) писали в
  ~/.claude/runtime/.env мимо литеральных глаголов → подделка escape-гранта.
  Закрытие: PS_WRITE_VERB_RE += sc/ac/cpi/copy/mi/move/ni/tee (path-gated, FP только
  с протектед-путём; контроль `sc query` не over-блокируется).
- delete: `del`/`ri`/`rd`/`rmdir`/`erase` -Recurse -Force обходили литеральный
  Remove-Item. Закрытие: PS_CONTENT_BLOCK_RE алиасы для long+short флагов.

154 GREEN (floor + powershell-destructive + enforce-floor + supreme-gate).
Отложено в Фазу 8 §5 (карты покрытия): `&` call-operator, Invoke-Command (icm),
PS sub-expression $(), полная enumeration алиасов — coverage, не структурный класс.
2026-06-08 09:12:38 +03:00

48 lines
2.0 KiB
JavaScript

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);
});
}
});