@wrongstack/tools 0.276.4 → 0.277.1

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/exec.js CHANGED
@@ -809,16 +809,28 @@ function resolveWin32Command(cmd) {
809
809
  }
810
810
  return cmd;
811
811
  }
812
- var WIN32_SHELL_META = /[&|<>\r\n\0]/;
812
+ var WIN32_SHELL_META = /[&|<>"\r\n\0]/;
813
813
  function assertSafeWin32ShellArgs(args) {
814
- for (const a of args) {
815
- if (typeof a === "string" && WIN32_SHELL_META.test(a)) {
814
+ for (const arg of args) {
815
+ if (typeof arg === "string" && WIN32_SHELL_META.test(arg)) {
816
816
  throw new Error(
817
- "win32 shell spawn: argument contains a shell metacharacter (one of & | < > or a newline) that could enable command injection through the .cmd/.bat wrapper \u2014 refusing to run. Offending argument: " + JSON.stringify(a)
817
+ 'win32 cmd shim spawn: argument contains a shell metacharacter (one of & | < > ", or a newline) that could enable command injection through the .cmd/.bat wrapper - refusing to run. Offending argument: ' + JSON.stringify(arg)
818
818
  );
819
819
  }
820
820
  }
821
821
  }
822
+ function buildWin32CmdShimInvocation(command, args = []) {
823
+ assertSafeWin32ShellArgs([command, ...args]);
824
+ const line = ["call", quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(" ");
825
+ return {
826
+ command: process.env["COMSPEC"] ?? "cmd.exe",
827
+ args: ["/d", "/c", line],
828
+ windowsVerbatimArguments: true
829
+ };
830
+ }
831
+ function quoteWin32CmdArg(arg) {
832
+ return `"${arg}"`;
833
+ }
822
834
 
823
835
  // src/exec.ts
824
836
  var isWin = process.platform === "win32";
@@ -889,10 +901,20 @@ var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
889
901
  // C / C++ / native build
890
902
  "make",
891
903
  "cmake",
904
+ "ninja",
905
+ "clang",
906
+ "clang-cl",
907
+ "gcc",
908
+ "g++",
909
+ "link",
910
+ "msbuild",
892
911
  // containers / orchestration
893
912
  "docker",
894
913
  "podman",
895
914
  "kubectl",
915
+ // network (read-only intent; destructive ops still blocked by BLOCKED_ARG_PATTERNS)
916
+ "curl",
917
+ "wget",
896
918
  // common POSIX file/text utilities
897
919
  "pwd",
898
920
  "ls",
@@ -912,7 +934,509 @@ var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
912
934
  "cp",
913
935
  "mv",
914
936
  "rm",
915
- "touch"
937
+ "touch",
938
+ "tar",
939
+ // Windows-native tooling (win32). All non-destructive binaries; per-arg
940
+ // safety is still enforced by BLOCKED_ARG_PATTERNS + the destructive-ops
941
+ // gate in bash-kill-guard.ts. `gh` is included even though it lives at
942
+ // "C:\Program Files\GitHub CLI\gh.exe" — resolveWin32Command handles the
943
+ // space in the path.
944
+ "gh",
945
+ "where",
946
+ "tasklist",
947
+ "systeminfo",
948
+ "wmic",
949
+ "sc",
950
+ "netstat",
951
+ "ipconfig",
952
+ "nslookup",
953
+ "tracert",
954
+ "pathping",
955
+ // Windows shell interpreters. Without these, `exec` cannot run cmd builtins
956
+ // (`dir`, `type`, `copy`, …) or any PowerShell cmdlet on Windows — a major
957
+ // gap since those are the platform's primary shells. Arbitrary execution
958
+ // through `cmd /c …` / `powershell -c …` is NOT a new hole: the permission
959
+ // policy reconstructs the full command line (shellCommandLineFromInput) and
960
+ // still runs it through the YOLO destructive classifier, so a genuinely
961
+ // destructive `cmd /c del /s /q C:\…` continues to require confirmation.
962
+ "cmd",
963
+ "cmd.exe",
964
+ "powershell",
965
+ "powershell.exe",
966
+ "pwsh",
967
+ "pwsh.exe",
968
+ // [core] Extended default allowlist (added 4b3d18d1 + this commit). All
969
+ // non-destructive, broadly-used dev binaries. Per-arg safety is still
970
+ // enforced by BLOCKED_ARG_PATTERNS + bash-kill-guard.ts.
971
+ // --- Archives & compression ---
972
+ "7z",
973
+ "7za",
974
+ "bzip2",
975
+ "gzip",
976
+ "xz",
977
+ "unzip",
978
+ "zip",
979
+ "gtar",
980
+ "bsdtar",
981
+ "star",
982
+ "pax",
983
+ "cpio",
984
+ // --- Android / mobile dev ---
985
+ "adb",
986
+ "fastboot",
987
+ "sdkmanager",
988
+ // --- DevOps / config mgmt ---
989
+ "ansible",
990
+ "ansible-playbook",
991
+ "ansible-vault",
992
+ "ansible-lint",
993
+ "ansible-galaxy",
994
+ "molecule",
995
+ // --- Cloud CLIs ---
996
+ "aws",
997
+ "aws-vault",
998
+ "awslocal",
999
+ "az",
1000
+ "azcopy",
1001
+ "gcloud",
1002
+ "gsutil",
1003
+ "doctl",
1004
+ "linode-cli",
1005
+ // --- Native / C / C++ / linker tools ---
1006
+ "clang++",
1007
+ "clang-format",
1008
+ "clang-tidy",
1009
+ "clangd",
1010
+ "lld",
1011
+ "lldb",
1012
+ "ctest",
1013
+ "gmake",
1014
+ "meson",
1015
+ "conan",
1016
+ "vcpkg",
1017
+ "cl",
1018
+ "rc",
1019
+ "mt",
1020
+ "dumpbin",
1021
+ "dotnet-format",
1022
+ // --- Image / media / binary tools ---
1023
+ "convert",
1024
+ "ffmpeg",
1025
+ "ffprobe",
1026
+ "magick",
1027
+ "gs",
1028
+ "exiftool",
1029
+ // --- HTTP / fetch ---
1030
+ "wget2",
1031
+ "aria2c",
1032
+ "axel",
1033
+ "httpie",
1034
+ "hey",
1035
+ "ab",
1036
+ "wrk",
1037
+ "http",
1038
+ // --- Diff / patch / merge ---
1039
+ "diff",
1040
+ "diff3",
1041
+ "patch",
1042
+ "meld",
1043
+ "kdiff3",
1044
+ "kompare",
1045
+ // --- Encoding / file inspection ---
1046
+ "dos2unix",
1047
+ "unix2dos",
1048
+ "iconv",
1049
+ "file",
1050
+ "stat",
1051
+ "xxd",
1052
+ "hexdump",
1053
+ "od",
1054
+ "base64",
1055
+ // --- SSH / crypto / signing ---
1056
+ "ssh",
1057
+ "ssh-add",
1058
+ "ssh-keygen",
1059
+ "ssh-keyscan",
1060
+ "scp",
1061
+ "sftp",
1062
+ "rsync",
1063
+ "gpg",
1064
+ "gpg2",
1065
+ "gpg-agent",
1066
+ "openssl",
1067
+ "step",
1068
+ "keytool",
1069
+ // --- Search ---
1070
+ "egrep",
1071
+ "fgrep",
1072
+ "ag",
1073
+ "ack",
1074
+ "sift",
1075
+ "ugrep",
1076
+ "fd",
1077
+ "fdfind",
1078
+ "jq",
1079
+ "yq",
1080
+ "xq",
1081
+ "fx",
1082
+ "gron",
1083
+ // --- K8s / container ecosystem ---
1084
+ "kubectl.exe",
1085
+ "kubeadm",
1086
+ "kubelet",
1087
+ "helm",
1088
+ "k9s",
1089
+ "kustomize",
1090
+ "skaffold",
1091
+ "tilt",
1092
+ "minikube",
1093
+ "kind",
1094
+ "k3d",
1095
+ "k3s",
1096
+ "docker-compose",
1097
+ "buildah",
1098
+ "skopeo",
1099
+ "nerdctl",
1100
+ "ctr",
1101
+ "ctr.exe",
1102
+ // --- Databases ---
1103
+ "sqlite3",
1104
+ "sqlite",
1105
+ "psql",
1106
+ "pg_dump",
1107
+ "pg_restore",
1108
+ "mysql",
1109
+ "mysqladmin",
1110
+ "mysqldump",
1111
+ "mariadb",
1112
+ "mariadb-dump",
1113
+ "redis-cli",
1114
+ "redis-server",
1115
+ "memcached",
1116
+ "etcdctl",
1117
+ "consul",
1118
+ "vault",
1119
+ "nomad",
1120
+ "mongosh",
1121
+ "mongo",
1122
+ "mongoexport",
1123
+ "mongoimport",
1124
+ "mongodump",
1125
+ "mongorestore",
1126
+ // --- Windows extended (read-mostly ops) ---
1127
+ "taskkill",
1128
+ "gpupdate",
1129
+ "gpresult",
1130
+ "hostname",
1131
+ "whoami",
1132
+ "who",
1133
+ "net",
1134
+ "net1",
1135
+ // --- VCS ecosystem ---
1136
+ "glab",
1137
+ "hub",
1138
+ "tea",
1139
+ "git-lfs",
1140
+ "tig",
1141
+ "lazygit",
1142
+ // --- POSIX text utilities (extended; duplicates of pwd/ls/cat/head/tail/wc/
1143
+ // grep/find/echo/awk/mkdir/cp/mv/rm/touch from the base list above are
1144
+ // omitted — the Set is de-duplicated at runtime but a clean literal is
1145
+ // easier to maintain) ---
1146
+ "gawk",
1147
+ "tr",
1148
+ "cut",
1149
+ "paste",
1150
+ "join",
1151
+ "comm",
1152
+ "expand",
1153
+ "unexpand",
1154
+ "fold",
1155
+ "fmt",
1156
+ "nl",
1157
+ "pr",
1158
+ "column",
1159
+ "tsort",
1160
+ "tty",
1161
+ "ul",
1162
+ "units",
1163
+ "factor",
1164
+ "seq",
1165
+ "shuf",
1166
+ "look",
1167
+ "yes",
1168
+ "true",
1169
+ "false",
1170
+ "test",
1171
+ "[",
1172
+ "printf",
1173
+ "env",
1174
+ "tree",
1175
+ "locate",
1176
+ "which",
1177
+ "whereis",
1178
+ "type",
1179
+ "hash",
1180
+ "pushd",
1181
+ "popd",
1182
+ "dirs",
1183
+ "history",
1184
+ "fc",
1185
+ "jobs",
1186
+ "bg",
1187
+ "fg",
1188
+ "wait",
1189
+ "ulimit",
1190
+ "umask",
1191
+ "nice",
1192
+ "nohup",
1193
+ "timeout",
1194
+ "time",
1195
+ "trap",
1196
+ "exit",
1197
+ "return",
1198
+ "source",
1199
+ ".",
1200
+ "alias",
1201
+ "unalias",
1202
+ "set",
1203
+ "unset",
1204
+ "export",
1205
+ "readonly",
1206
+ "typeset",
1207
+ "declare",
1208
+ "local",
1209
+ "eval",
1210
+ "exec",
1211
+ // --- Process / system inspection ---
1212
+ "htop",
1213
+ "top",
1214
+ "atop",
1215
+ "glances",
1216
+ "iotop",
1217
+ "nethogs",
1218
+ "iftop",
1219
+ "lsof",
1220
+ "strace",
1221
+ "ltrace",
1222
+ "sysstat",
1223
+ "vmstat",
1224
+ "iostat",
1225
+ "mpstat",
1226
+ "sar",
1227
+ "free",
1228
+ "df",
1229
+ "du",
1230
+ "mount",
1231
+ "umount",
1232
+ "lsblk",
1233
+ "blkid",
1234
+ "kill",
1235
+ "killall",
1236
+ "pkill",
1237
+ "pgrep",
1238
+ "pidof",
1239
+ "ps",
1240
+ "ps.exe",
1241
+ // --- Network inspection ---
1242
+ "ip",
1243
+ "ss",
1244
+ "route",
1245
+ "arp",
1246
+ "arping",
1247
+ "ping",
1248
+ "ping6",
1249
+ "hping3",
1250
+ "mtr",
1251
+ "tracepath",
1252
+ "tcpdump",
1253
+ "nmap",
1254
+ "netcat",
1255
+ "nc",
1256
+ "ncat",
1257
+ "socat",
1258
+ // --- Sync / backup ---
1259
+ "rclone",
1260
+ "restic",
1261
+ "borg",
1262
+ "duplicati",
1263
+ "duplicacy",
1264
+ "syncthing",
1265
+ "syncthing-cli",
1266
+ // --- Permissions / users / ACLs (POSIX) ---
1267
+ "useradd",
1268
+ "userdel",
1269
+ "usermod",
1270
+ "groupadd",
1271
+ "groupdel",
1272
+ "groupmod",
1273
+ "chown",
1274
+ "chmod",
1275
+ "chgrp",
1276
+ "getfacl",
1277
+ "setfacl",
1278
+ "setcap",
1279
+ "getcap",
1280
+ // --- Crypto / cert mgmt (extended) ---
1281
+ "certbot",
1282
+ "mkcert",
1283
+ "jarsigner",
1284
+ // --- Editors ---
1285
+ "subl",
1286
+ "code",
1287
+ "code-insiders",
1288
+ "cursor",
1289
+ "atom",
1290
+ "nano",
1291
+ "vim",
1292
+ "nvim",
1293
+ "vi",
1294
+ "emacs",
1295
+ "helix",
1296
+ "hx",
1297
+ "micro",
1298
+ "jed",
1299
+ "ed",
1300
+ "ex",
1301
+ "mg",
1302
+ // --- Terminal multiplexers ---
1303
+ "asciinema",
1304
+ "script",
1305
+ "scriptreplay",
1306
+ "expect",
1307
+ "screen",
1308
+ "tmux",
1309
+ "byobu",
1310
+ "dtach",
1311
+ "abduco",
1312
+ // --- Calculators / REPLs / scientific ---
1313
+ "bc",
1314
+ "dc",
1315
+ "calc",
1316
+ "qalc",
1317
+ "genius",
1318
+ "octave",
1319
+ "R",
1320
+ "Rscript",
1321
+ "julia",
1322
+ "irb",
1323
+ "pry",
1324
+ "ghci",
1325
+ "stack",
1326
+ "cabal",
1327
+ "ghc",
1328
+ // --- PHP / Lua / Perl / Ruby ecosystem (extended) ---
1329
+ "php8",
1330
+ "php7",
1331
+ "phpcs",
1332
+ "phpcbf",
1333
+ "phpmd",
1334
+ "phpstan",
1335
+ "psalm",
1336
+ "lua",
1337
+ "lua5.1",
1338
+ "lua5.2",
1339
+ "lua5.3",
1340
+ "lua5.4",
1341
+ "luarocks",
1342
+ "perl",
1343
+ "cpan",
1344
+ "prove",
1345
+ "plackup",
1346
+ "rake",
1347
+ "rspec",
1348
+ "jekyll",
1349
+ "node-gyp",
1350
+ "node-pre-gyp",
1351
+ // --- JS / TS toolchain (extended) ---
1352
+ "electron",
1353
+ "electron-builder",
1354
+ "electron-forge",
1355
+ "vite-preview",
1356
+ "swc",
1357
+ "swc-cli",
1358
+ "swcpack",
1359
+ "mocha",
1360
+ "chai",
1361
+ "jasmine",
1362
+ "puppeteer",
1363
+ "lighthouse",
1364
+ // --- Linters / formatters (extended) ---
1365
+ "tslint",
1366
+ "stylelint",
1367
+ "htmlhint",
1368
+ "jshint",
1369
+ "jslint",
1370
+ "jscs",
1371
+ // --- Document conversion ---
1372
+ "pandoc",
1373
+ "weasyprint",
1374
+ "wkhtmltopdf",
1375
+ "wkhtmltoimage",
1376
+ "prince",
1377
+ "mdp",
1378
+ "markdown",
1379
+ "multimarkdown",
1380
+ "cmark",
1381
+ "cmark-gfm",
1382
+ // --- Office / spreadsheet ---
1383
+ "soffice",
1384
+ "libreoffice",
1385
+ "unoconv",
1386
+ "abiword",
1387
+ "gnumeric",
1388
+ // --- Spell / grammar ---
1389
+ "aspell",
1390
+ "hunspell",
1391
+ "enchant",
1392
+ "languagetool",
1393
+ // --- Source-highlight / diff tools ---
1394
+ "delta",
1395
+ "bat",
1396
+ "ccat",
1397
+ "hl",
1398
+ "highlight",
1399
+ "source-highlight",
1400
+ "ansifilter",
1401
+ // --- Job schedulers ---
1402
+ "pueue",
1403
+ "task-spooler",
1404
+ "ts",
1405
+ "at",
1406
+ "atd",
1407
+ "anacron",
1408
+ "fcron",
1409
+ "cronie",
1410
+ "systemd-run",
1411
+ "systemd-cat",
1412
+ // --- Plotting / visualization ---
1413
+ "gnuplot",
1414
+ "gnuplot-nox",
1415
+ "veusz",
1416
+ "scidavis",
1417
+ "grace",
1418
+ "xmgrace",
1419
+ "labplot",
1420
+ // --- Security / recon (network + web) ---
1421
+ "masscan",
1422
+ "zmap",
1423
+ "rustscan",
1424
+ "amass",
1425
+ "subfinder",
1426
+ "httpx",
1427
+ "nuclei",
1428
+ "naabu",
1429
+ "katana",
1430
+ "dnsx",
1431
+ "assetfinder",
1432
+ "findomain",
1433
+ "gau",
1434
+ "waybackurls",
1435
+ "httprobe",
1436
+ "meg",
1437
+ "subjack",
1438
+ "sublert",
1439
+ "chaos"
916
1440
  ]);
917
1441
  var allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);
918
1442
  var normalizeCmd = (c) => c.trim();
@@ -1135,17 +1659,18 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
1135
1659
  const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT });
1136
1660
  const resolved = resolveWin32Command(cmd);
1137
1661
  const needsShell = isWin && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
1138
- const spawnCmd = needsShell ? cmd : resolved;
1139
- if (needsShell) assertSafeWin32ShellArgs(args);
1662
+ const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
1663
+ const spawnCmd = shim?.command ?? resolved;
1664
+ const spawnArgs = shim?.args ?? args;
1140
1665
  let child;
1141
1666
  try {
1142
- child = spawn(spawnCmd, args, {
1667
+ child = spawn(spawnCmd, spawnArgs, {
1143
1668
  cwd,
1144
1669
  env: buildChildEnv(sessionId),
1145
1670
  stdio: ["ignore", "pipe", "pipe"],
1146
1671
  windowsHide: true,
1147
1672
  ...isWin ? {} : { signal },
1148
- ...needsShell ? { shell: true, windowsVerbatimArguments: true } : {}
1673
+ ...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}
1149
1674
  });
1150
1675
  } catch (err) {
1151
1676
  spool.finalize();