@atbash/cli 0.5.15 → 0.6.1-dev.2

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.
Files changed (66) hide show
  1. package/README.md +389 -2
  2. package/dist/bin/atbash.js +39 -4
  3. package/dist/bin/atbash.js.map +1 -1
  4. package/dist/commands/config-cmd.js +15 -15
  5. package/dist/commands/config-cmd.js.map +1 -1
  6. package/dist/commands/connect.d.ts +115 -1
  7. package/dist/commands/connect.js +292 -73
  8. package/dist/commands/connect.js.map +1 -1
  9. package/dist/commands/github-scan.d.ts +104 -0
  10. package/dist/commands/github-scan.js +1054 -0
  11. package/dist/commands/github-scan.js.map +1 -0
  12. package/dist/commands/held.js +7 -2
  13. package/dist/commands/held.js.map +1 -1
  14. package/dist/commands/history.js +4 -1
  15. package/dist/commands/history.js.map +1 -1
  16. package/dist/commands/judge-options.d.ts +21 -0
  17. package/dist/commands/judge-options.js +24 -0
  18. package/dist/commands/judge-options.js.map +1 -0
  19. package/dist/commands/judge.js +5 -2
  20. package/dist/commands/judge.js.map +1 -1
  21. package/dist/commands/mcp-cmd.d.ts +13 -0
  22. package/dist/commands/mcp-cmd.js +216 -0
  23. package/dist/commands/mcp-cmd.js.map +1 -0
  24. package/dist/commands/policy.js +4 -1
  25. package/dist/commands/policy.js.map +1 -1
  26. package/dist/commands/scan.d.ts +45 -0
  27. package/dist/commands/scan.js +301 -0
  28. package/dist/commands/scan.js.map +1 -0
  29. package/dist/commands/setup.d.ts +533 -0
  30. package/dist/commands/setup.js +2653 -0
  31. package/dist/commands/setup.js.map +1 -0
  32. package/dist/commands/stats.js +3 -1
  33. package/dist/commands/stats.js.map +1 -1
  34. package/dist/commands/status.js +4 -1
  35. package/dist/commands/status.js.map +1 -1
  36. package/dist/commands/tier.js +4 -1
  37. package/dist/commands/tier.js.map +1 -1
  38. package/dist/commands/tools.js +11 -4
  39. package/dist/commands/tools.js.map +1 -1
  40. package/dist/commands/whoami.js +4 -1
  41. package/dist/commands/whoami.js.map +1 -1
  42. package/dist/lib/grade-llm.d.ts +38 -0
  43. package/dist/lib/grade-llm.js +64 -0
  44. package/dist/lib/grade-llm.js.map +1 -0
  45. package/dist/lib/llm.d.ts +34 -0
  46. package/dist/lib/llm.js +101 -0
  47. package/dist/lib/llm.js.map +1 -0
  48. package/dist/lib/policy.d.ts +40 -0
  49. package/dist/lib/policy.js +94 -0
  50. package/dist/lib/policy.js.map +1 -0
  51. package/dist/lib/risk.d.ts +112 -0
  52. package/dist/lib/risk.js +288 -0
  53. package/dist/lib/risk.js.map +1 -0
  54. package/dist/lib/threats-llm.d.ts +39 -0
  55. package/dist/lib/threats-llm.js +72 -0
  56. package/dist/lib/threats-llm.js.map +1 -0
  57. package/dist/shared/atbash-targets.d.ts +49 -0
  58. package/dist/shared/atbash-targets.js +63 -0
  59. package/dist/shared/atbash-targets.js.map +1 -0
  60. package/dist/shared/openclaw-runtime.d.ts +221 -0
  61. package/dist/shared/openclaw-runtime.js +476 -0
  62. package/dist/shared/openclaw-runtime.js.map +1 -0
  63. package/dist/shared/win-exec.d.ts +63 -0
  64. package/dist/shared/win-exec.js +147 -0
  65. package/dist/shared/win-exec.js.map +1 -0
  66. package/package.json +4 -3
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isWindowsShim = isWindowsShim;
7
+ exports.quoteArg = quoteArg;
8
+ exports.escapeForCmd = escapeForCmd;
9
+ exports.cmdLineFor = cmdLineFor;
10
+ exports.spawnPortable = spawnPortable;
11
+ exports.pickExecutable = pickExecutable;
12
+ /**
13
+ * Launching an npm-installed CLI on Windows, without opening a shell seam.
14
+ *
15
+ * `openclaw`, `hermes`, `npm` and every other Node CLI arrive on Windows as a
16
+ * `.cmd` shim, and a `.cmd` is not an executable — CreateProcess cannot run one.
17
+ * Node used to paper over that; since 18.20.2 / 20.12.2 (the CVE-2024-27980 fix)
18
+ * it refuses outright, and `spawnSync("openclaw.cmd", …)` fails with EINVAL
19
+ * unless the call goes through a shell. That is why every `openclaw` probe
20
+ * answered "could not run" on Windows while working everywhere else: detection
21
+ * did not misread the machine, it never reached the binary at all.
22
+ *
23
+ * ⚠️ THE OBVIOUS REPAIR, `shell: true`, IS THE WRONG ONE HERE. It concatenates
24
+ * the command and its arguments into ONE string for `cmd.exe` to re-parse, so a
25
+ * `&`, `|` or `%VAR%` anywhere in an argument — or in the install path, which is
26
+ * read off `where` and was never written by us — stops being data and becomes
27
+ * another command. This tool governs whether an agent's actions are allowed to
28
+ * happen; it does not get to introduce shell injection into its own probe path.
29
+ *
30
+ * So a shim is routed through `cmd.exe /d /s /c` explicitly, with the command
31
+ * line built here: each token is quoted for the child's own CRT parser and then
32
+ * caret-escaped for the `cmd.exe` pass that happens first. `shell: true` skips
33
+ * that second step, which is exactly the part that matters.
34
+ *
35
+ * Everything off Windows, and every real `.exe`, is spawned directly as before.
36
+ */
37
+ const child_process_1 = require("child_process");
38
+ const path_1 = __importDefault(require("path"));
39
+ /** Batch shims — the two extensions `cmd.exe` must interpret for us. */
40
+ const SHIM = /\.(cmd|bat)$/i;
41
+ /**
42
+ * What `cmd.exe` acts on before the child ever sees the line.
43
+ *
44
+ * `%` is in here because `%FOO%` is expanded during that pass, which would
45
+ * otherwise substitute an environment variable into an argument — or blank it.
46
+ */
47
+ const CMD_META = /[()%!^"<>&|]/g;
48
+ /** Does this command need `cmd.exe` to run at all? */
49
+ function isWindowsShim(command) {
50
+ return process.platform === "win32" && SHIM.test(command);
51
+ }
52
+ /**
53
+ * Quote one token the way the child's C runtime will parse it back.
54
+ *
55
+ * The backslash rule is the unobvious half: a backslash is literal EXCEPT in the
56
+ * run immediately before a quote, where each one must be doubled. `C:\dir\` as
57
+ * the last token would otherwise end `"C:\dir\"` — an escaped quote, which
58
+ * swallows the rest of the line.
59
+ */
60
+ function quoteArg(arg) {
61
+ if (arg === "")
62
+ return '""';
63
+ if (!/[\s"\\]/.test(arg))
64
+ return arg;
65
+ const escaped = arg
66
+ .replace(/(\\*)"/g, '$1$1\\"') // double the run before a real quote, then escape it
67
+ .replace(/(\\*)$/, "$1$1"); // and the run before the quote we are about to add
68
+ return `"${escaped}"`;
69
+ }
70
+ /**
71
+ * Caret-escape a token for the `cmd.exe` parse.
72
+ *
73
+ * The quotes added by {@link quoteArg} are escaped too, deliberately. An escaped
74
+ * quote is literal text to `cmd.exe`, so it does not open a quoted section
75
+ * there, and arrives at the child as the plain `"` its CRT is expecting.
76
+ */
77
+ function escapeForCmd(token) {
78
+ return token.replace(CMD_META, "^$&");
79
+ }
80
+ /** Build the full `cmd.exe` command line for a shim and its arguments. */
81
+ function cmdLineFor(command, args) {
82
+ return [command, ...args].map((a) => escapeForCmd(quoteArg(a))).join(" ");
83
+ }
84
+ /**
85
+ * `spawnSync`, but a Windows `.cmd`/`.bat` shim actually runs.
86
+ *
87
+ * Identical to `spawnSync` in every other case — same arguments, same return —
88
+ * so it is a drop-in at the call sites that probe an external CLI.
89
+ */
90
+ function spawnPortable(command, args, options = {}) {
91
+ if (process.platform !== "win32") {
92
+ return (0, child_process_1.spawnSync)(command, args, options);
93
+ }
94
+ // A bare name like `openclaw` or `hermes` hides the problem rather than
95
+ // avoiding it: the PATH search resolves it to the same `.cmd`, and the launch
96
+ // fails just as hard, only without an extension to recognize it by. Resolve
97
+ // first, then decide.
98
+ const resolved = resolveOnWindows(command);
99
+ if (!isWindowsShim(resolved)) {
100
+ return (0, child_process_1.spawnSync)(resolved, args, options);
101
+ }
102
+ // `/d` skips AutoRun commands from the registry — someone else's startup script
103
+ // has no business running inside a read-only probe. `/s` fixes the quote rule to
104
+ // "strip the first and last", which is what makes the wrapping pair below safe.
105
+ const comspec = process.env.ComSpec || process.env.COMSPEC || "cmd.exe";
106
+ return (0, child_process_1.spawnSync)(comspec, ["/d", "/s", "/c", `"${cmdLineFor(resolved, args)}"`], {
107
+ ...options,
108
+ // Node must pass our line through untouched — it is already quoted correctly,
109
+ // and a second round of Node's own quoting would break the escaping above.
110
+ windowsVerbatimArguments: true,
111
+ });
112
+ }
113
+ /**
114
+ * Turn a bare command name into the file Windows will actually launch.
115
+ *
116
+ * Anything already carrying a path is left alone — the caller has resolved it,
117
+ * and re-resolving could pick a different install off PATH than the one they
118
+ * meant. A name with no path goes through `where`, which is the same lookup the
119
+ * shell would do, so the answer matches what the operator sees.
120
+ */
121
+ function resolveOnWindows(command) {
122
+ if (path_1.default.isAbsolute(command) || command.includes("\\") || command.includes("/"))
123
+ return command;
124
+ const where = (0, child_process_1.spawnSync)("where", [command], { encoding: "utf8" });
125
+ if (where.status !== 0)
126
+ return command;
127
+ return pickExecutable((where.stdout ?? "").split(/\r?\n/)) ?? command;
128
+ }
129
+ /**
130
+ * Pick the runnable match out of `where` output.
131
+ *
132
+ * `where openclaw` lists BOTH the extensionless POSIX-style script npm writes for
133
+ * Git Bash and the `openclaw.cmd` Windows actually uses, in that order. Taking
134
+ * the first line — which is what this did — hands back the one file on the list
135
+ * that Windows cannot execute.
136
+ */
137
+ function pickExecutable(lines) {
138
+ const found = lines.map((l) => l.trim()).filter(Boolean);
139
+ if (found.length === 0)
140
+ return undefined;
141
+ const runnable = (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD")
142
+ .split(";")
143
+ .map((e) => e.trim().toLowerCase())
144
+ .filter(Boolean);
145
+ return found.find((f) => runnable.some((ext) => f.toLowerCase().endsWith(ext))) ?? found[0];
146
+ }
147
+ //# sourceMappingURL=win-exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"win-exec.js","sourceRoot":"","sources":["../../src/shared/win-exec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atbash/cli",
3
- "version": "0.5.15",
3
+ "version": "0.6.1-dev.2",
4
4
  "description": "Atbash CLI — control boundary before the last irreversible step in an agent workflow",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://atbash.ai",
@@ -26,13 +26,14 @@
26
26
  "scripts": {
27
27
  "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
28
28
  "build": "npm run clean && tsc",
29
- "test": "node -r ts-node/register --test test/*.test.js",
29
+ "typecheck": "tsc --noEmit",
30
+ "test": "node scripts/run-tests.mjs",
30
31
  "dev": "ts-node src/bin/atbash.ts",
31
32
  "release": "npm version patch --no-git-tag-version && npm run build && npx npm@10 publish --access public",
32
33
  "release:dev": "npm version prerelease --preid dev --no-git-tag-version && npm run build && npx npm@10 publish --tag dev --access public"
33
34
  },
34
35
  "dependencies": {
35
- "@atbash/sdk": "^0.7.1",
36
+ "@atbash/sdk": "0.13.0-dev.0",
36
37
  "@iarna/toml": "2.2.5",
37
38
  "chalk": "^4.1.2",
38
39
  "commander": "^12.0.0",