llm-cli-gateway 1.5.30 → 1.5.31
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/CHANGELOG.md +11 -0
- package/README.md +15 -1
- package/dist/claude-mcp-config.js +1 -1
- package/dist/config.js +1 -1
- package/dist/executor.js +7 -2
- package/dist/model-registry.js +1 -1
- package/package.json +3 -2
- package/socket.yml +49 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the llm-cli-gateway project.
|
|
4
4
|
|
|
5
|
+
## [1.5.31] - 2026-05-25
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Replace direct dependency on `toml@3.0.0` (single-maintainer, last released 2020) with `smol-toml@^1.6.1` (actively maintained, TypeScript-native, zero deps). Same `parse(text)` API, drop-in across `src/config.ts`, `src/claude-mcp-config.ts`, and `src/model-registry.ts`.
|
|
10
|
+
|
|
11
|
+
### Security
|
|
12
|
+
|
|
13
|
+
- Add `socket.yml` documenting the rationale for Socket's behavioural alerts (`networkAccess`, `shellAccess`, `usesEval`). Alerts are left visible — not silenced — so downstream consumers can see the maintainer's review context.
|
|
14
|
+
- Expand README "Security Considerations" with a per-alert breakdown mapping each Socket signal to where it lives in the code and why it is bounded.
|
|
15
|
+
|
|
5
16
|
## [1.5.30] - 2026-05-25
|
|
6
17
|
|
|
7
18
|
### Fixed
|
package/README.md
CHANGED
|
@@ -1005,8 +1005,22 @@ The gateway supports concurrent requests across different CLIs. Each request spa
|
|
|
1005
1005
|
|
|
1006
1006
|
- **Input Validation**: All prompts are validated (min 1 char, max 100k chars)
|
|
1007
1007
|
- **Command Execution**: Uses `spawn` with separate arguments (not shell execution)
|
|
1008
|
-
- **No Eval**: No dynamic code evaluation
|
|
1008
|
+
- **No Eval**: No dynamic code evaluation in our source (see "Socket alerts" below for the transitive `ajv` codegen case)
|
|
1009
1009
|
- **Sandboxing**: Consider running in containers for production use
|
|
1010
|
+
- **Provenance**: Releases are published with [npm provenance](https://docs.npmjs.com/generating-provenance-statements) via OIDC trusted publishing from GitHub Actions
|
|
1011
|
+
|
|
1012
|
+
### Socket alerts — context for reviewers
|
|
1013
|
+
|
|
1014
|
+
If you're vetting `llm-cli-gateway` through [Socket](https://socket.dev/npm/package/llm-cli-gateway) or a similar supply-chain scanner, you'll see three behavioural alerts and some dependency-ownership alerts. They are accurate descriptions of what the package does and what it depends on; we've left them visible (not silenced in `socket.yml`) so you don't have to take our word for it. Here's the context for each:
|
|
1015
|
+
|
|
1016
|
+
| Alert | Where | Why it's bounded |
|
|
1017
|
+
|---|---|---|
|
|
1018
|
+
| **Network access** | `src/http-transport.ts` opens an HTTP MCP transport when started via `npm run start:http`. `src/endpoint-exposure.ts` issues a HEAD probe to verify configured public/tunnel URLs. | The transport binds to `127.0.0.1` by default and requires `LLM_GATEWAY_AUTH_TOKEN` to be set. The default stdio MCP entry point (`npm start`) opens no sockets. |
|
|
1019
|
+
| **Shell access** | `src/executor.ts` uses `child_process.spawn(cmd, args, …)` to invoke the underlying LLM CLIs. | `spawn` is called with an argument array and **never** `shell: true`, so there is no shell interpolation path for caller input. The command name is restricted to an allow-list of known CLI binaries (`claude`, `codex`, `gemini`, `grok`, `vibe`). |
|
|
1020
|
+
| **Uses eval** | None in our source. Transitive: `@modelcontextprotocol/sdk` → `ajv@8` uses `new Function(...)` in `ajv/dist/compile/index.js` to compile JSON Schema validators. | This is ajv's standard codegen path. Only known schemas (defined in our source and the MCP SDK) flow into it; no caller-supplied data ever reaches the compiled function body. |
|
|
1021
|
+
| **Dependency ownership** | A handful of small transitive packages (e.g. `bindings` via `better-sqlite3`, `media-typer` via `@modelcontextprotocol/sdk`) trip Socket's "unstable ownership" or "obfuscated code" heuristics. | These are pinned, well-known micro-deps in the Node ecosystem with no known issues. We pin direct override versions of `content-type` and `type-is` in `package.json#overrides`. Our previous direct dependency on `toml@3.0.0` (also single-maintainer, last released 2020) was replaced with the actively-maintained `smol-toml` to reduce inherited risk. |
|
|
1022
|
+
|
|
1023
|
+
See [`socket.yml`](./socket.yml) for the same context in machine-readable form.
|
|
1010
1024
|
|
|
1011
1025
|
## Contributing
|
|
1012
1026
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, renameSync, openSync, fsyncSync, closeSync, chmodSync, } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
|
-
import { parse as parseToml } from "toml";
|
|
4
|
+
import { parse as parseToml } from "smol-toml";
|
|
5
5
|
export const CLAUDE_MCP_SERVER_NAMES = ["sqry", "exa", "ref_tools", "trstr"];
|
|
6
6
|
function asStringArray(value) {
|
|
7
7
|
if (!Array.isArray(value)) {
|
package/dist/config.js
CHANGED
|
@@ -108,7 +108,7 @@ function readPersistenceFile(configPath, logger) {
|
|
|
108
108
|
}
|
|
109
109
|
try {
|
|
110
110
|
const require = createRequire(import.meta.url);
|
|
111
|
-
const TOML = require("toml");
|
|
111
|
+
const TOML = require("smol-toml");
|
|
112
112
|
const text = readFileSync(configPath, "utf-8");
|
|
113
113
|
const parsed = TOML.parse(text);
|
|
114
114
|
return { raw: parsed?.persistence, sourcePath: configPath };
|
package/dist/executor.js
CHANGED
|
@@ -152,10 +152,15 @@ const WINDOWS_CMD_META_CHARS = /([()\][%!^"`<>&|;, *?])/g;
|
|
|
152
152
|
function escapeWindowsCmdCommand(value) {
|
|
153
153
|
return win32.normalize(value).replace(WINDOWS_CMD_META_CHARS, "^$1");
|
|
154
154
|
}
|
|
155
|
+
// CommandLineToArgvW rules: a run of N backslashes before a literal " must be
|
|
156
|
+
// doubled and followed by \" (yielding 2N+1 backslashes total, so the parser
|
|
157
|
+
// strips N and keeps the quote as literal); a run of N backslashes immediately
|
|
158
|
+
// before the closing " must be doubled (2N) so the quote still terminates the
|
|
159
|
+
// arg. Then wrap in quotes and caret-escape cmd.exe metacharacters.
|
|
155
160
|
function escapeWindowsCmdArgument(value) {
|
|
156
161
|
let arg = `${value}`;
|
|
157
|
-
arg = arg.replace(/(
|
|
158
|
-
arg = arg.replace(/(
|
|
162
|
+
arg = arg.replace(/(\\*)"/g, '$1$1\\"');
|
|
163
|
+
arg = arg.replace(/(\\*)$/, "$1$1");
|
|
159
164
|
arg = `"${arg}"`;
|
|
160
165
|
return arg.replace(WINDOWS_CMD_META_CHARS, "^$1");
|
|
161
166
|
}
|
package/dist/model-registry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { parse as parseToml } from "toml";
|
|
4
|
+
import { parse as parseToml } from "smol-toml";
|
|
5
5
|
const FALLBACK_INFO = {
|
|
6
6
|
claude: {
|
|
7
7
|
description: "Anthropic's Claude Code CLI - best for code generation, analysis, and agentic coding tasks",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-cli-gateway",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.31",
|
|
4
4
|
"mcpName": "io.github.verivus-oss/llm-cli-gateway",
|
|
5
5
|
"description": "MCP server providing unified access to Claude Code, Codex, Gemini, Grok, and Mistral Vibe CLIs with session management, retry logic, async job orchestration, durable job results, and cross-LLM validation.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"setup/status.schema.json",
|
|
50
50
|
"README.md",
|
|
51
51
|
"CHANGELOG.md",
|
|
52
|
+
"socket.yml",
|
|
52
53
|
"LICENSE"
|
|
53
54
|
],
|
|
54
55
|
"scripts": {
|
|
@@ -83,7 +84,7 @@
|
|
|
83
84
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
84
85
|
"better-sqlite3": "^12.10.0",
|
|
85
86
|
"content-type": "1.0.5",
|
|
86
|
-
"toml": "^
|
|
87
|
+
"smol-toml": "^1.6.1",
|
|
87
88
|
"type-is": "2.0.1",
|
|
88
89
|
"zod": "^3.23.0"
|
|
89
90
|
},
|
package/socket.yml
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
# Socket alerts on llm-cli-gateway
|
|
4
|
+
# ---------------------------------
|
|
5
|
+
# This package intentionally triggers three of Socket's behavioural alerts.
|
|
6
|
+
# We do NOT disable them — they are accurate descriptions of what the package
|
|
7
|
+
# does, and silencing them would hide useful signal from anyone evaluating
|
|
8
|
+
# this dependency. The rationale for each is documented inline below and in
|
|
9
|
+
# detail under "Security Considerations" in README.md.
|
|
10
|
+
#
|
|
11
|
+
# networkAccess
|
|
12
|
+
# src/http-transport.ts opens an HTTP MCP transport (createServer/listen).
|
|
13
|
+
# Defaults to 127.0.0.1, auth-token gated (LLM_GATEWAY_AUTH_TOKEN).
|
|
14
|
+
# src/endpoint-exposure.ts also issues a HEAD probe when verifying
|
|
15
|
+
# tunnel reachability — opt-in via the start:http entry point only.
|
|
16
|
+
#
|
|
17
|
+
# shellAccess
|
|
18
|
+
# src/executor.ts uses child_process.spawn(cmd, args, { ... }) with a
|
|
19
|
+
# fixed allow-list of CLI binaries (claude / codex / gemini / grok /
|
|
20
|
+
# vibe). shell:true is never set; arguments are passed as an array, so
|
|
21
|
+
# there is no shell interpolation path for user input. Spawning these
|
|
22
|
+
# CLIs is the entire purpose of the package.
|
|
23
|
+
#
|
|
24
|
+
# usesEval
|
|
25
|
+
# Not in our source. Transitive via @modelcontextprotocol/sdk → ajv@8,
|
|
26
|
+
# which compiles JSON Schema validators using `new Function(...)`.
|
|
27
|
+
# This is ajv's standard codegen path; no caller-supplied data flows
|
|
28
|
+
# into the compiled function body.
|
|
29
|
+
|
|
30
|
+
issueRules:
|
|
31
|
+
# Defaults from Socket. Listed explicitly so future contributors see what
|
|
32
|
+
# is enforced rather than relying on implicit defaults.
|
|
33
|
+
malware: true
|
|
34
|
+
troll: true
|
|
35
|
+
didYouMean: true
|
|
36
|
+
installScripts: true
|
|
37
|
+
telemetry: true
|
|
38
|
+
hasNativeCode: true # better-sqlite3 — known and expected
|
|
39
|
+
shellScriptOverride: true
|
|
40
|
+
gitDependency: true
|
|
41
|
+
httpDependency: true
|
|
42
|
+
invalidPackageJSON: true
|
|
43
|
+
unresolvedRequire: true
|
|
44
|
+
|
|
45
|
+
githubApp:
|
|
46
|
+
enabled: true
|
|
47
|
+
pullRequestAlertsEnabled: true
|
|
48
|
+
dependencyOverviewEnabled: true
|
|
49
|
+
projectReportsEnabled: true
|