opencode-swarm 6.68.1 → 6.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +471 -40
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -42117,17 +42117,17 @@ function normalizeSeparators(filePath) {
|
|
|
42117
42117
|
}
|
|
42118
42118
|
function matchesDocPattern(filePath, patterns) {
|
|
42119
42119
|
const normalizedPath = normalizeSeparators(filePath);
|
|
42120
|
-
const
|
|
42120
|
+
const basename8 = path56.basename(filePath);
|
|
42121
42121
|
for (const pattern of patterns) {
|
|
42122
42122
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
42123
|
-
if (
|
|
42123
|
+
if (basename8 === pattern) {
|
|
42124
42124
|
return true;
|
|
42125
42125
|
}
|
|
42126
42126
|
continue;
|
|
42127
42127
|
}
|
|
42128
42128
|
if (pattern.startsWith("**/")) {
|
|
42129
42129
|
const filenamePattern = pattern.slice(3);
|
|
42130
|
-
if (
|
|
42130
|
+
if (basename8 === filenamePattern) {
|
|
42131
42131
|
return true;
|
|
42132
42132
|
}
|
|
42133
42133
|
continue;
|
|
@@ -59425,6 +59425,324 @@ function isInDeclaredScope(filePath, scopeEntries, cwd) {
|
|
|
59425
59425
|
return rel.length > 0 && !rel.startsWith("..") && !path41.isAbsolute(rel);
|
|
59426
59426
|
});
|
|
59427
59427
|
}
|
|
59428
|
+
var DC_MAX_UNWRAP_DEPTH = 5;
|
|
59429
|
+
var DC_SAFE_TARGETS = new Set([
|
|
59430
|
+
"node_modules",
|
|
59431
|
+
".git",
|
|
59432
|
+
"dist",
|
|
59433
|
+
"build",
|
|
59434
|
+
"coverage",
|
|
59435
|
+
".next",
|
|
59436
|
+
".turbo",
|
|
59437
|
+
".cache",
|
|
59438
|
+
".venv",
|
|
59439
|
+
"venv",
|
|
59440
|
+
"__pycache__",
|
|
59441
|
+
"target",
|
|
59442
|
+
"out",
|
|
59443
|
+
".parcel-cache",
|
|
59444
|
+
".svelte-kit",
|
|
59445
|
+
".nuxt",
|
|
59446
|
+
".output",
|
|
59447
|
+
".angular",
|
|
59448
|
+
".gradle",
|
|
59449
|
+
"vendor"
|
|
59450
|
+
]);
|
|
59451
|
+
var DC_BLOCKED_ABSOLUTE_PREFIXES = [
|
|
59452
|
+
"/root",
|
|
59453
|
+
"/home",
|
|
59454
|
+
"/Users",
|
|
59455
|
+
"/etc",
|
|
59456
|
+
"/var",
|
|
59457
|
+
"/usr",
|
|
59458
|
+
"/opt",
|
|
59459
|
+
"/bin",
|
|
59460
|
+
"/sbin",
|
|
59461
|
+
"/lib",
|
|
59462
|
+
"/boot",
|
|
59463
|
+
"/proc",
|
|
59464
|
+
"/sys",
|
|
59465
|
+
"/dev",
|
|
59466
|
+
"/run",
|
|
59467
|
+
"/System",
|
|
59468
|
+
"/Library",
|
|
59469
|
+
"/Applications",
|
|
59470
|
+
"C:\\Windows",
|
|
59471
|
+
"C:\\Users",
|
|
59472
|
+
"C:\\Program Files",
|
|
59473
|
+
"C:\\ProgramData",
|
|
59474
|
+
"C:/Windows",
|
|
59475
|
+
"C:/Users",
|
|
59476
|
+
"C:/Program Files",
|
|
59477
|
+
"C:/ProgramData"
|
|
59478
|
+
];
|
|
59479
|
+
var DC_FS_ROOTS = new Set(["/", "C:\\", "C:/", "D:\\", "D:/", "E:\\", "E:/"]);
|
|
59480
|
+
var DC_REMOTE_PREFIXES = [
|
|
59481
|
+
"\\\\",
|
|
59482
|
+
"/Volumes/",
|
|
59483
|
+
"/net/",
|
|
59484
|
+
"/nfs/",
|
|
59485
|
+
"/smb/",
|
|
59486
|
+
"/run/user/"
|
|
59487
|
+
];
|
|
59488
|
+
function dcNormalizeCommand(cmd) {
|
|
59489
|
+
let s = cmd.normalize("NFKC");
|
|
59490
|
+
s = s.replace(/`(.)/g, "$1");
|
|
59491
|
+
s = s.replace(/\^([a-zA-Z0-9 ])/g, "$1");
|
|
59492
|
+
s = s.replace(/""/g, "");
|
|
59493
|
+
s = s.replace(/''/g, "");
|
|
59494
|
+
return s;
|
|
59495
|
+
}
|
|
59496
|
+
function dcStripOneWrapper(cmd) {
|
|
59497
|
+
const t = cmd.trim();
|
|
59498
|
+
const cmdExeMatch = /^cmd(?:\.exe)?\s+\/[ckCK]\s+"?(.*?)"?\s*$/is.exec(t);
|
|
59499
|
+
if (cmdExeMatch)
|
|
59500
|
+
return cmdExeMatch[1].trim();
|
|
59501
|
+
const psCommandMatch = /^(?:powershell|pwsh)(?:\.exe)?\s+(?:-(?:Command|command|c)\s+)(.+)$/is.exec(t);
|
|
59502
|
+
if (psCommandMatch)
|
|
59503
|
+
return psCommandMatch[1].replace(/^["']|["']$/g, "").trim();
|
|
59504
|
+
const psEncMatch = /^(?:powershell|pwsh)(?:\.exe)?\s+(?:-(?:EncodedCommand|encodedcommand|enc|e)\s+)([A-Za-z0-9+/=]+)\s*$/.exec(t);
|
|
59505
|
+
if (psEncMatch) {
|
|
59506
|
+
try {
|
|
59507
|
+
const decoded = Buffer.from(psEncMatch[1], "base64").toString("utf16le");
|
|
59508
|
+
return decoded.trim();
|
|
59509
|
+
} catch {
|
|
59510
|
+
return t;
|
|
59511
|
+
}
|
|
59512
|
+
}
|
|
59513
|
+
const shellMatch = /^(?:bash|sh|zsh|dash|fish)(?:\.exe)?\s+-c\s+"?(.*?)"?\s*$/is.exec(t);
|
|
59514
|
+
if (shellMatch)
|
|
59515
|
+
return shellMatch[1].trim();
|
|
59516
|
+
const prefixMatch = /^(?:sudo|time|nohup)\s+(.+)$/is.exec(t) ?? /^env(?:\s+[A-Za-z_][A-Za-z0-9_]*=[^\s]*)*\s+(.+)$/is.exec(t) ?? /^nice\s+(?:-n\s+\d+\s+)?(.+)$/is.exec(t);
|
|
59517
|
+
if (prefixMatch)
|
|
59518
|
+
return prefixMatch[1].trim();
|
|
59519
|
+
const wslMatch = /^wsl(?:\.exe)?\s+(?:-e|--)\s+(.+)$/is.exec(t);
|
|
59520
|
+
if (wslMatch)
|
|
59521
|
+
return wslMatch[1].trim();
|
|
59522
|
+
const scriptBlockMatch = /^&\s*\{(.+)\}$/s.exec(t);
|
|
59523
|
+
if (scriptBlockMatch)
|
|
59524
|
+
return scriptBlockMatch[1].trim();
|
|
59525
|
+
const iexMatch = /^(?:Invoke-Expression|iex)\s+(.+)$/is.exec(t);
|
|
59526
|
+
if (iexMatch)
|
|
59527
|
+
return iexMatch[1].replace(/^["'`]|["'`]$/g, "").trim();
|
|
59528
|
+
const invokeCommandMatch = /^Invoke-Command\s+.*-ScriptBlock\s*\{(.+)\}$/is.exec(t);
|
|
59529
|
+
if (invokeCommandMatch)
|
|
59530
|
+
return invokeCommandMatch[1].trim();
|
|
59531
|
+
const callMatch = /^call\s+(.+)$/is.exec(t);
|
|
59532
|
+
if (callMatch)
|
|
59533
|
+
return callMatch[1].trim();
|
|
59534
|
+
return null;
|
|
59535
|
+
}
|
|
59536
|
+
function dcUnwrapWrappers(cmd) {
|
|
59537
|
+
let current = cmd.trim();
|
|
59538
|
+
for (let depth = 0;depth < DC_MAX_UNWRAP_DEPTH; depth++) {
|
|
59539
|
+
const inner = dcStripOneWrapper(current);
|
|
59540
|
+
if (inner === null || inner === current)
|
|
59541
|
+
break;
|
|
59542
|
+
current = inner.trim();
|
|
59543
|
+
}
|
|
59544
|
+
return current;
|
|
59545
|
+
}
|
|
59546
|
+
function dcSplitSegments(cmd) {
|
|
59547
|
+
const segments = [];
|
|
59548
|
+
let current = "";
|
|
59549
|
+
let inDoubleQuote = false;
|
|
59550
|
+
let inSingleQuote = false;
|
|
59551
|
+
for (let i2 = 0;i2 < cmd.length; i2++) {
|
|
59552
|
+
const ch = cmd[i2];
|
|
59553
|
+
const next = cmd[i2 + 1];
|
|
59554
|
+
if (ch === '"' && !inSingleQuote) {
|
|
59555
|
+
inDoubleQuote = !inDoubleQuote;
|
|
59556
|
+
current += ch;
|
|
59557
|
+
continue;
|
|
59558
|
+
}
|
|
59559
|
+
if (ch === "'" && !inDoubleQuote) {
|
|
59560
|
+
inSingleQuote = !inSingleQuote;
|
|
59561
|
+
current += ch;
|
|
59562
|
+
continue;
|
|
59563
|
+
}
|
|
59564
|
+
if (!inDoubleQuote && !inSingleQuote) {
|
|
59565
|
+
if (ch === "&" && next === "&" || ch === "|" && next === "|") {
|
|
59566
|
+
segments.push(current.trim());
|
|
59567
|
+
current = "";
|
|
59568
|
+
i2++;
|
|
59569
|
+
continue;
|
|
59570
|
+
}
|
|
59571
|
+
if (ch === "|" || ch === ";" || ch === `
|
|
59572
|
+
` || ch === "\r") {
|
|
59573
|
+
segments.push(current.trim());
|
|
59574
|
+
current = "";
|
|
59575
|
+
continue;
|
|
59576
|
+
}
|
|
59577
|
+
}
|
|
59578
|
+
current += ch;
|
|
59579
|
+
}
|
|
59580
|
+
if (current.trim())
|
|
59581
|
+
segments.push(current.trim());
|
|
59582
|
+
return segments.filter((s) => s.length > 0);
|
|
59583
|
+
}
|
|
59584
|
+
function dcHasUnresolvableVars(p) {
|
|
59585
|
+
return /(%[A-Za-z_][A-Za-z0-9_]*%|\$\{?[A-Za-z_]|\$env:)/i.test(p);
|
|
59586
|
+
}
|
|
59587
|
+
function dcIsRemotePath(p) {
|
|
59588
|
+
return DC_REMOTE_PREFIXES.some((pfx) => p.startsWith(pfx));
|
|
59589
|
+
}
|
|
59590
|
+
function dcLstatAncestorWalk(targetPath, cwd) {
|
|
59591
|
+
const normalizedTarget = path41.resolve(cwd, targetPath);
|
|
59592
|
+
const normalizedCwd = path41.resolve(cwd);
|
|
59593
|
+
const ancestors = [];
|
|
59594
|
+
let current = normalizedTarget;
|
|
59595
|
+
while (true) {
|
|
59596
|
+
ancestors.push(current);
|
|
59597
|
+
const parent = path41.dirname(current);
|
|
59598
|
+
if (parent === current)
|
|
59599
|
+
break;
|
|
59600
|
+
const rel = path41.relative(normalizedCwd, current);
|
|
59601
|
+
if (rel === "" || rel.startsWith(".."))
|
|
59602
|
+
break;
|
|
59603
|
+
current = parent;
|
|
59604
|
+
}
|
|
59605
|
+
for (const ancestor of ancestors) {
|
|
59606
|
+
let stat2 = null;
|
|
59607
|
+
try {
|
|
59608
|
+
stat2 = fsSync.lstatSync(ancestor);
|
|
59609
|
+
} catch (err2) {
|
|
59610
|
+
const code = err2.code;
|
|
59611
|
+
if (code === "ENOENT") {
|
|
59612
|
+
break;
|
|
59613
|
+
}
|
|
59614
|
+
return `lstat failed on "${ancestor}": ${String(err2)} \u2014 refusing to allow destructive operation on unverifiable path`;
|
|
59615
|
+
}
|
|
59616
|
+
if (stat2.isSymbolicLink()) {
|
|
59617
|
+
return `BLOCKED: "${ancestor}" is a symlink/junction \u2014 deleting recursively through it would destroy the link target. Use platform-specific junction deletion (fsutil reparsepoint delete, Remove-Item without -Recurse) instead.`;
|
|
59618
|
+
}
|
|
59619
|
+
}
|
|
59620
|
+
return null;
|
|
59621
|
+
}
|
|
59622
|
+
function dcValidateTargets(targets, cwd) {
|
|
59623
|
+
for (const raw of targets) {
|
|
59624
|
+
const t = raw.trim().replace(/^["']|["']$/g, "");
|
|
59625
|
+
if (!t || t === ".")
|
|
59626
|
+
continue;
|
|
59627
|
+
if (dcHasUnresolvableVars(t)) {
|
|
59628
|
+
return `BLOCKED: Destructive command targets path with unexpanded variable "${t}" \u2014 cannot verify safety. Resolve variables before using destructive operations.`;
|
|
59629
|
+
}
|
|
59630
|
+
if (dcIsRemotePath(t)) {
|
|
59631
|
+
return `BLOCKED: Destructive command targets remote/network filesystem path "${t}" \u2014 refusing to execute remote destructive operations.`;
|
|
59632
|
+
}
|
|
59633
|
+
if (/^\\\\/.test(t)) {
|
|
59634
|
+
return `BLOCKED: Destructive command targets UNC path "${t}" \u2014 UNC paths in destructive operations are not allowed.`;
|
|
59635
|
+
}
|
|
59636
|
+
const lstatBlock = dcLstatAncestorWalk(t, cwd);
|
|
59637
|
+
if (lstatBlock)
|
|
59638
|
+
return lstatBlock;
|
|
59639
|
+
const basename6 = path41.basename(t);
|
|
59640
|
+
if (t === basename6 && DC_SAFE_TARGETS.has(t)) {
|
|
59641
|
+
continue;
|
|
59642
|
+
}
|
|
59643
|
+
if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
|
|
59644
|
+
return `BLOCKED: Destructive command targets filesystem root "${t}"`;
|
|
59645
|
+
}
|
|
59646
|
+
if (path41.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
|
|
59647
|
+
for (const blocked of DC_BLOCKED_ABSOLUTE_PREFIXES) {
|
|
59648
|
+
if (t.startsWith(blocked)) {
|
|
59649
|
+
return `BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`;
|
|
59650
|
+
}
|
|
59651
|
+
}
|
|
59652
|
+
}
|
|
59653
|
+
}
|
|
59654
|
+
return null;
|
|
59655
|
+
}
|
|
59656
|
+
function dcCheckJunctionCreation(segment, cwd) {
|
|
59657
|
+
const mklinkMatch = /^mklink(?:\.exe)?\s+\/[JjDd]\s+"?([^"\s]+)"?\s+"?([^"\s]+)"?/i.exec(segment);
|
|
59658
|
+
if (mklinkMatch) {
|
|
59659
|
+
const target = mklinkMatch[2].trim();
|
|
59660
|
+
if (!dcHasUnresolvableVars(target)) {
|
|
59661
|
+
const resolved = path41.resolve(cwd, target);
|
|
59662
|
+
const rel = path41.relative(cwd, resolved);
|
|
59663
|
+
if (rel.startsWith("..") || path41.isAbsolute(rel)) {
|
|
59664
|
+
return `BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`;
|
|
59665
|
+
}
|
|
59666
|
+
}
|
|
59667
|
+
return null;
|
|
59668
|
+
}
|
|
59669
|
+
const newItemTypeMatch = /New-Item\b.*-ItemType\s+(?:Junction|SymbolicLink|HardLink)\b/i.test(segment);
|
|
59670
|
+
const newItemTargetMatch = /-Target\s+"?([^"\s;]+)"?/i.exec(segment);
|
|
59671
|
+
const newItemMatch = newItemTypeMatch ? newItemTargetMatch : null;
|
|
59672
|
+
if (newItemMatch) {
|
|
59673
|
+
const target = newItemMatch[1].trim();
|
|
59674
|
+
if (!dcHasUnresolvableVars(target)) {
|
|
59675
|
+
const resolved = path41.resolve(cwd, target);
|
|
59676
|
+
const rel = path41.relative(cwd, resolved);
|
|
59677
|
+
if (rel.startsWith("..") || path41.isAbsolute(rel)) {
|
|
59678
|
+
return `BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`;
|
|
59679
|
+
}
|
|
59680
|
+
}
|
|
59681
|
+
return null;
|
|
59682
|
+
}
|
|
59683
|
+
const lnMatch = /^ln\s+(?:-[sfnv]*s[sfnv]*|-s)\s+"?([^"\s]+)"?(?:\s+"?[^"\s]+"?)?\s*$/.exec(segment);
|
|
59684
|
+
if (lnMatch) {
|
|
59685
|
+
const target = lnMatch[1].trim();
|
|
59686
|
+
if (!dcHasUnresolvableVars(target)) {
|
|
59687
|
+
const resolved = path41.resolve(cwd, target);
|
|
59688
|
+
const rel = path41.relative(cwd, resolved);
|
|
59689
|
+
if (rel.startsWith("..") || path41.isAbsolute(rel)) {
|
|
59690
|
+
return `BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`;
|
|
59691
|
+
}
|
|
59692
|
+
}
|
|
59693
|
+
return null;
|
|
59694
|
+
}
|
|
59695
|
+
return null;
|
|
59696
|
+
}
|
|
59697
|
+
function dcExtractWindowsCmdTargets(segment) {
|
|
59698
|
+
const rmdirMatch = /^(?:rmdir|rd)(?:\.exe)?\s+(?:\/[sqSQ]\s+)*"?(.+?)"?\s*$/i.exec(segment);
|
|
59699
|
+
if (rmdirMatch)
|
|
59700
|
+
return [rmdirMatch[1].trim()];
|
|
59701
|
+
const delMatch = /^del(?:\.exe)?\s+(?:\/[sqfSQF]\s+)*"?(.+?)"?\s*$/i.exec(segment);
|
|
59702
|
+
if (delMatch)
|
|
59703
|
+
return [delMatch[1].trim()];
|
|
59704
|
+
return [];
|
|
59705
|
+
}
|
|
59706
|
+
function dcExtractPowerShellTargets(segment) {
|
|
59707
|
+
const verbMatch = /^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\s+/i.exec(segment);
|
|
59708
|
+
if (!verbMatch)
|
|
59709
|
+
return [];
|
|
59710
|
+
const rest = segment.slice(verbMatch[0].length);
|
|
59711
|
+
const tokens = rest.match(/"[^"]*"|'[^']*'|[^\s]+/g) ?? [];
|
|
59712
|
+
const targets = [];
|
|
59713
|
+
const valueFlags = new Set([
|
|
59714
|
+
"-literalpath",
|
|
59715
|
+
"-path",
|
|
59716
|
+
"-filter",
|
|
59717
|
+
"-include",
|
|
59718
|
+
"-exclude",
|
|
59719
|
+
"-lp"
|
|
59720
|
+
]);
|
|
59721
|
+
let skipNext = false;
|
|
59722
|
+
for (const tok of tokens) {
|
|
59723
|
+
if (skipNext) {
|
|
59724
|
+
skipNext = false;
|
|
59725
|
+
continue;
|
|
59726
|
+
}
|
|
59727
|
+
if (tok.startsWith("-")) {
|
|
59728
|
+
if (valueFlags.has(tok.toLowerCase())) {
|
|
59729
|
+
skipNext = true;
|
|
59730
|
+
const idx = tokens.indexOf(tok);
|
|
59731
|
+
if (idx !== -1 && idx + 1 < tokens.length) {
|
|
59732
|
+
const val = tokens[idx + 1].replace(/^["']|["']$/g, "");
|
|
59733
|
+
if (val)
|
|
59734
|
+
targets.push(val);
|
|
59735
|
+
skipNext = true;
|
|
59736
|
+
}
|
|
59737
|
+
}
|
|
59738
|
+
} else {
|
|
59739
|
+
const cleaned = tok.replace(/^["']|["']$/g, "");
|
|
59740
|
+
if (cleaned)
|
|
59741
|
+
targets.push(cleaned);
|
|
59742
|
+
}
|
|
59743
|
+
}
|
|
59744
|
+
return targets;
|
|
59745
|
+
}
|
|
59428
59746
|
function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
|
|
59429
59747
|
let guardrailsConfig;
|
|
59430
59748
|
if (directory && typeof directory === "object" && "enabled" in directory) {
|
|
@@ -59459,46 +59777,159 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
|
|
|
59459
59777
|
if (cfg.block_destructive_commands === false)
|
|
59460
59778
|
return;
|
|
59461
59779
|
const toolArgs = args2;
|
|
59462
|
-
const
|
|
59463
|
-
if (!
|
|
59780
|
+
const rawCommand = typeof toolArgs?.command === "string" ? toolArgs.command.trim() : "";
|
|
59781
|
+
if (!rawCommand)
|
|
59464
59782
|
return;
|
|
59783
|
+
const cwd = effectiveDirectory;
|
|
59784
|
+
const command = dcNormalizeCommand(rawCommand);
|
|
59465
59785
|
if (/:\s*\(\s*\)\s*\{[^}]*\|[^}]*:/.test(command)) {
|
|
59466
59786
|
throw new Error(`BLOCKED: Potentially destructive shell command detected: fork bomb pattern`);
|
|
59467
59787
|
}
|
|
59468
|
-
const
|
|
59469
|
-
const
|
|
59470
|
-
|
|
59471
|
-
|
|
59472
|
-
|
|
59473
|
-
|
|
59474
|
-
|
|
59475
|
-
|
|
59476
|
-
|
|
59788
|
+
const unwrapped = dcUnwrapWrappers(command);
|
|
59789
|
+
const outerSegments = dcSplitSegments(command);
|
|
59790
|
+
const innerSegments = dcSplitSegments(unwrapped);
|
|
59791
|
+
const perSegmentUnwrapped = outerSegments.map((s) => dcUnwrapWrappers(s));
|
|
59792
|
+
const allSegments = [
|
|
59793
|
+
...new Set([...outerSegments, ...innerSegments, ...perSegmentUnwrapped])
|
|
59794
|
+
];
|
|
59795
|
+
for (const segment of allSegments) {
|
|
59796
|
+
const seg = segment.trim();
|
|
59797
|
+
if (!seg)
|
|
59798
|
+
continue;
|
|
59799
|
+
const junctionBlock = dcCheckJunctionCreation(seg, cwd);
|
|
59800
|
+
if (junctionBlock)
|
|
59801
|
+
throw new Error(junctionBlock);
|
|
59802
|
+
const rmShortMatch = /^rm\s+(-[rRfF]+(?:\s+-[rRfF]+)*|-r\s+-f|-f\s+-r)\s+(.+)$/.exec(seg);
|
|
59803
|
+
const rmLongMatch = /^rm\s+(?:--(?:recursive|force)\s+){1,2}(.+)$/.exec(seg);
|
|
59804
|
+
const rmAnyMatch = rmShortMatch ?? rmLongMatch;
|
|
59805
|
+
if (rmAnyMatch) {
|
|
59806
|
+
const targetPart = rmAnyMatch[rmShortMatch ? 2 : 1].trim();
|
|
59807
|
+
const targets = targetPart.split(/\s+/);
|
|
59808
|
+
const validateBlock = dcValidateTargets(targets, cwd);
|
|
59809
|
+
if (validateBlock)
|
|
59810
|
+
throw new Error(validateBlock);
|
|
59811
|
+
const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.replace(/^["']|["']$/g, "").trim()));
|
|
59812
|
+
if (!allSafe) {
|
|
59813
|
+
throw new Error(`BLOCKED: Potentially destructive shell command: rm with recursive/force flags on unsafe path(s): ${targetPart}`);
|
|
59814
|
+
}
|
|
59815
|
+
}
|
|
59816
|
+
if (/^(?:rmdir|rd)(?:\.exe)?\s+.*\/[sS]/i.test(seg)) {
|
|
59817
|
+
const targets = dcExtractWindowsCmdTargets(seg);
|
|
59818
|
+
if (targets.length === 0) {
|
|
59819
|
+
throw new Error(`BLOCKED: Windows recursive directory delete (rmdir /s or rd /s) detected. Verify the target is not a junction/symlink.`);
|
|
59820
|
+
}
|
|
59821
|
+
const validateBlock = dcValidateTargets(targets, cwd);
|
|
59822
|
+
if (validateBlock)
|
|
59823
|
+
throw new Error(validateBlock);
|
|
59824
|
+
const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.trim()));
|
|
59825
|
+
if (!allSafe) {
|
|
59826
|
+
throw new Error(`BLOCKED: Windows recursive directory delete on unsafe path(s): ${targets.join(", ")}`);
|
|
59827
|
+
}
|
|
59828
|
+
}
|
|
59829
|
+
if (/^del(?:\.exe)?\s+.*\/[sS]/i.test(seg)) {
|
|
59830
|
+
const targets = dcExtractWindowsCmdTargets(seg);
|
|
59831
|
+
if (targets.length > 0) {
|
|
59832
|
+
const validateBlock = dcValidateTargets(targets, cwd);
|
|
59833
|
+
if (validateBlock)
|
|
59834
|
+
throw new Error(validateBlock);
|
|
59835
|
+
const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.trim()));
|
|
59836
|
+
if (!allSafe) {
|
|
59837
|
+
throw new Error(`BLOCKED: Windows recursive file delete (del /s) on unsafe path(s): ${targets.join(", ")}`);
|
|
59838
|
+
}
|
|
59839
|
+
}
|
|
59840
|
+
}
|
|
59841
|
+
if (/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]ecurse\b/i.test(seg) || /^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]\b/i.test(seg)) {
|
|
59842
|
+
const targets = dcExtractPowerShellTargets(seg);
|
|
59843
|
+
if (targets.length > 0) {
|
|
59844
|
+
const validateBlock = dcValidateTargets(targets, cwd);
|
|
59845
|
+
if (validateBlock)
|
|
59846
|
+
throw new Error(validateBlock);
|
|
59847
|
+
const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.trim()));
|
|
59848
|
+
if (!allSafe) {
|
|
59849
|
+
throw new Error(`BLOCKED: PowerShell recursive delete on unsafe path(s): ${targets.join(", ")}`);
|
|
59850
|
+
}
|
|
59851
|
+
} else {
|
|
59852
|
+
throw new Error(`BLOCKED: PowerShell Remove-Item with -Recurse detected \u2014 cannot verify target safety`);
|
|
59853
|
+
}
|
|
59854
|
+
}
|
|
59855
|
+
if (/Get-ChildItem\b.*\|\s*Remove-Item\b.*-[Rr]ecurse/i.test(seg) || /gci\b.*\|\s*ri\b.*-[Rr]ecurse/i.test(seg)) {
|
|
59856
|
+
throw new Error(`BLOCKED: PowerShell pipeline "Get-ChildItem | Remove-Item -Recurse" detected \u2014 verify target safety and avoid recursive deletion through symlinks/junctions`);
|
|
59857
|
+
}
|
|
59858
|
+
if (/^vssadmin(?:\.exe)?\s+delete\b/i.test(seg)) {
|
|
59859
|
+
throw new Error(`BLOCKED: "vssadmin delete" detected \u2014 deletes Volume Shadow Copies (ransomware-grade operation)`);
|
|
59860
|
+
}
|
|
59861
|
+
if (/^wbadmin(?:\.exe)?\s+delete\b/i.test(seg)) {
|
|
59862
|
+
throw new Error(`BLOCKED: "wbadmin delete" detected \u2014 deletes Windows backup catalog (ransomware-grade operation)`);
|
|
59863
|
+
}
|
|
59864
|
+
if (/^diskpart(?:\.exe)?$/i.test(seg)) {
|
|
59865
|
+
throw new Error(`BLOCKED: "diskpart" detected \u2014 interactive disk partitioning tool`);
|
|
59866
|
+
}
|
|
59867
|
+
if (/^bcdedit(?:\.exe)?\s+\/delete\b/i.test(seg)) {
|
|
59868
|
+
throw new Error(`BLOCKED: "bcdedit /delete" detected \u2014 modifies Windows boot configuration`);
|
|
59869
|
+
}
|
|
59870
|
+
if (/^sdelete(?:\.exe)?\s+/i.test(seg)) {
|
|
59871
|
+
throw new Error(`BLOCKED: "sdelete" detected \u2014 secure file deletion (Sysinternals)`);
|
|
59872
|
+
}
|
|
59873
|
+
if (/^fsutil(?:\.exe)?\s+reparsepoint\s+delete\b/i.test(seg) || /^fsutil(?:\.exe)?\s+file\s+setzerodata\b/i.test(seg)) {
|
|
59874
|
+
throw new Error(`BLOCKED: "fsutil" destructive subcommand detected`);
|
|
59875
|
+
}
|
|
59876
|
+
if (/^takeown(?:\.exe)?\s+.*\/[rR]\b/i.test(seg)) {
|
|
59877
|
+
throw new Error(`BLOCKED: "takeown /R" (recursive ownership takeover) detected \u2014 often precedes destructive operations`);
|
|
59878
|
+
}
|
|
59879
|
+
if (/^cipher(?:\.exe)?\s+\/[wW]\b/i.test(seg)) {
|
|
59880
|
+
throw new Error(`BLOCKED: "cipher /w" detected \u2014 overwrites free disk space (data wipe operation)`);
|
|
59881
|
+
}
|
|
59882
|
+
if (/^format\s+[A-Za-z]:/i.test(seg)) {
|
|
59883
|
+
throw new Error(`BLOCKED: Windows disk format command detected`);
|
|
59884
|
+
}
|
|
59885
|
+
if (/^robocopy(?:\.exe)?\s+.*\/(?:MIR|mir)\b/.test(seg)) {
|
|
59886
|
+
throw new Error(`BLOCKED: "robocopy /MIR" (mirror) detected \u2014 can delete files in the destination that don't exist in the source`);
|
|
59887
|
+
}
|
|
59888
|
+
if (/^chmod\s+.*-[rR]\b.*000\b/.test(seg)) {
|
|
59889
|
+
throw new Error(`BLOCKED: "chmod -R 000" detected \u2014 removes all permissions recursively`);
|
|
59890
|
+
}
|
|
59891
|
+
if (/^chattr\s+.*\+i\b/.test(seg)) {
|
|
59892
|
+
throw new Error(`BLOCKED: "chattr +i" detected \u2014 makes files immutable`);
|
|
59893
|
+
}
|
|
59894
|
+
if (/^icacls(?:\.exe)?\s+.*\/deny\b/i.test(seg)) {
|
|
59895
|
+
throw new Error(`BLOCKED: "icacls /deny" detected \u2014 denies filesystem permissions`);
|
|
59896
|
+
}
|
|
59897
|
+
if (/^dd\b.*\bif=\/dev\/(zero|null|urandom)\b/.test(seg)) {
|
|
59898
|
+
throw new Error(`BLOCKED: "dd" with /dev/zero, /dev/null, or /dev/urandom as input detected \u2014 data wipe operation`);
|
|
59899
|
+
}
|
|
59900
|
+
if (/^git\s+push\b.*?(--force|-f)\b/.test(seg)) {
|
|
59901
|
+
throw new Error(`BLOCKED: Force push detected \u2014 git push --force is not allowed`);
|
|
59902
|
+
}
|
|
59903
|
+
if (/^git\s+reset\s+--hard/.test(seg)) {
|
|
59904
|
+
throw new Error(`BLOCKED: "git reset --hard" detected \u2014 use --soft or --mixed with caution`);
|
|
59905
|
+
}
|
|
59906
|
+
if (/^git\s+reset\s+--mixed\s+\S+/.test(seg)) {
|
|
59907
|
+
throw new Error(`BLOCKED: "git reset --mixed" with a target branch/commit is not allowed`);
|
|
59908
|
+
}
|
|
59909
|
+
if (/^git\s+clean\s+.*-[fF].*[dD]/.test(seg)) {
|
|
59910
|
+
throw new Error(`BLOCKED: "git clean -fd" detected \u2014 permanently deletes untracked files and directories`);
|
|
59911
|
+
}
|
|
59912
|
+
if (/^git\s+worktree\s+remove\s+.*--force\b/i.test(seg)) {
|
|
59913
|
+
throw new Error(`BLOCKED: "git worktree remove --force" detected \u2014 can delete working tree contents`);
|
|
59914
|
+
}
|
|
59915
|
+
if (/^rsync\b.*--delete(?:-after|-before|-during|-delay)?\b/.test(seg)) {
|
|
59916
|
+
throw new Error(`BLOCKED: "rsync --delete" detected \u2014 can delete files in the destination. Verify source is not empty.`);
|
|
59917
|
+
}
|
|
59918
|
+
if (/^kubectl\s+delete\b/.test(seg)) {
|
|
59919
|
+
throw new Error(`BLOCKED: "kubectl delete" detected \u2014 destructive cluster operation`);
|
|
59920
|
+
}
|
|
59921
|
+
if (/^docker\s+system\s+prune\b/.test(seg)) {
|
|
59922
|
+
throw new Error(`BLOCKED: "docker system prune" detected \u2014 destructive container operation`);
|
|
59923
|
+
}
|
|
59924
|
+
if (/^\s*DROP\s+(TABLE|DATABASE|SCHEMA)\b/i.test(seg)) {
|
|
59925
|
+
throw new Error(`BLOCKED: SQL DROP command detected \u2014 destructive database operation`);
|
|
59926
|
+
}
|
|
59927
|
+
if (/^\s*TRUNCATE\s+TABLE\b/i.test(seg)) {
|
|
59928
|
+
throw new Error(`BLOCKED: SQL TRUNCATE command detected \u2014 destructive database operation`);
|
|
59929
|
+
}
|
|
59930
|
+
if (/^mkfs[./]/.test(seg)) {
|
|
59931
|
+
throw new Error(`BLOCKED: Disk format command (mkfs) detected \u2014 disk formatting operation`);
|
|
59477
59932
|
}
|
|
59478
|
-
}
|
|
59479
|
-
if (/^git\s+push\b.*?(--force|-f)\b/.test(command)) {
|
|
59480
|
-
throw new Error(`BLOCKED: Force push detected \u2014 git push --force is not allowed`);
|
|
59481
|
-
}
|
|
59482
|
-
if (/^git\s+reset\s+--hard/.test(command)) {
|
|
59483
|
-
throw new Error(`BLOCKED: "git reset --hard" detected \u2014 use --soft or --mixed with caution`);
|
|
59484
|
-
}
|
|
59485
|
-
if (/^git\s+reset\s+--mixed\s+\S+/.test(command)) {
|
|
59486
|
-
throw new Error(`BLOCKED: "git reset --mixed" with a target branch/commit is not allowed`);
|
|
59487
|
-
}
|
|
59488
|
-
if (/^kubectl\s+delete\b/.test(command)) {
|
|
59489
|
-
throw new Error(`BLOCKED: "kubectl delete" detected \u2014 destructive cluster operation`);
|
|
59490
|
-
}
|
|
59491
|
-
if (/^docker\s+system\s+prune\b/.test(command)) {
|
|
59492
|
-
throw new Error(`BLOCKED: "docker system prune" detected \u2014 destructive container operation`);
|
|
59493
|
-
}
|
|
59494
|
-
if (/^\s*DROP\s+(TABLE|DATABASE|SCHEMA)\b/i.test(command)) {
|
|
59495
|
-
throw new Error(`BLOCKED: SQL DROP command detected \u2014 destructive database operation`);
|
|
59496
|
-
}
|
|
59497
|
-
if (/^\s*TRUNCATE\s+TABLE\b/i.test(command)) {
|
|
59498
|
-
throw new Error(`BLOCKED: SQL TRUNCATE command detected \u2014 destructive database operation`);
|
|
59499
|
-
}
|
|
59500
|
-
if (/^mkfs[./]/.test(command)) {
|
|
59501
|
-
throw new Error(`BLOCKED: Disk format command (mkfs) detected \u2014 disk formatting operation`);
|
|
59502
59933
|
}
|
|
59503
59934
|
}
|
|
59504
59935
|
async function checkGateLimits(params) {
|
|
@@ -68884,7 +69315,7 @@ function countCodeLines(content) {
|
|
|
68884
69315
|
return lines.length;
|
|
68885
69316
|
}
|
|
68886
69317
|
function isTestFile(filePath) {
|
|
68887
|
-
const
|
|
69318
|
+
const basename10 = path65.basename(filePath);
|
|
68888
69319
|
const _ext = path65.extname(filePath).toLowerCase();
|
|
68889
69320
|
const testPatterns = [
|
|
68890
69321
|
".test.",
|
|
@@ -68900,7 +69331,7 @@ function isTestFile(filePath) {
|
|
|
68900
69331
|
".spec.jsx"
|
|
68901
69332
|
];
|
|
68902
69333
|
for (const pattern of testPatterns) {
|
|
68903
|
-
if (
|
|
69334
|
+
if (basename10.includes(pattern)) {
|
|
68904
69335
|
return true;
|
|
68905
69336
|
}
|
|
68906
69337
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.69.0",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|