Dependabot is reporting 5 open high-severity alerts on main. I triaged each against the current codebase while investigating the v0.3.2 release pipeline. Below is the full picture so whoever picks this up isn't starting from scratch.
TL;DR
| # |
Package |
GHSA |
CVSS |
In-repo exploitability |
Action |
| 1 |
drizzle-orm@1.0.0-beta.12-a5629fb |
GHSA-gpj5-g38j-94v9 |
7.5 |
None reachable — local SQLite only, no sql.identifier()/.as() with user input |
Bump to 1.0.0-beta.21+ |
| 2 |
minimatch@10.0.3 |
GHSA-7r86-cg39-jmmj |
7.5 |
Low — patterns come from local config file |
Bump to 10.2.3 |
| 3 |
minimatch@10.0.3 |
GHSA-23c5-xmqv-rm74 |
7.5 |
Same as #2 |
Same bump clears it |
| 4 |
minimatch@10.0.3 |
GHSA-3ppc-4f35-3m26 |
(unscored, ReDoS) |
Same as #2 |
Same bump clears it |
| 5 |
@modelcontextprotocol/sdk@1.25.2 |
GHSA-345p-7cg4-v4c7 |
7.1 |
None — we're an MCP client, advisory is server-side |
Bump to 1.26.0+ for hygiene |
All three root packages live in packages/cli/package.json. None of the advisories are currently exploitable in production use of the CLI, but the versions are plain out-of-date and should be bumped.
Alert 1: drizzle-orm SQL injection via identifier escaping
- Advisory:
GHSA-gpj5-g38j-94v9 — Drizzle ORM improperly escapes quoted SQL identifiers in dialect-specific escapeName(). sql.identifier() / .as() with attacker-controlled input enables injection.
- Current:
drizzle-orm@1.0.0-beta.12-a5629fb in packages/cli/package.json, drizzle-kit@1.0.0-beta.12-a5629fb in packages/cli/package.json and the root package.json workspace catalog. Plus a pinned override "drizzle-orm": "1.0.0-beta.12-a5629fb" in packages/cli/package.json's overrides.
- Vulnerable ranges (from advisory):
< 0.45.2 → fixed in 0.45.2
>= 1.0.0-beta.2, < 1.0.0-beta.20 → fixed in 1.0.0-beta.20 ← we're in this range
- Target:
1.0.0-beta.21 (current beta dist-tag on npm). All three declarations need to stay in sync.
- Exploitability in this codebase:
grep -rn 'sql\.identifier\|\.as(' packages/cli/src/ returns zero hits. The CLI uses drizzle purely with hardcoded table definitions (sqliteTable(...), eq()) against a local bun-sqlite database. There is no dynamic identifier path reachable from user input or network.
- Why bump anyway: stale pinned betas are the wrong kind of boring; easy to miss if the exploitation surface changes later.
Alerts 2, 3, 4: minimatch ReDoS (three distinct patterns)
- Advisories:
GHSA-7r86-cg39-jmmj — multiple non-adjacent ** segments, O(C(n,k)) backtracking
GHSA-23c5-xmqv-rm74 — nested *() extglobs (most severe; 12-byte minimum trigger)
GHSA-3ppc-4f35-3m26 — long runs of * + non-matching literal, O(4^N)
- Current:
minimatch@10.0.3
- Target:
10.2.3 (all three advisories clear at this version — note GHSA-3ppc says fixed in 10.2.1, but the other two gate to 10.2.3, so 10.2.3 is the minimum to close all alerts)
- Usage surface:
packages/cli/src/util/glob.ts:32 — direct minimatch() call in Glob.match(pattern, filepath). Callers of Glob.match: only packages/cli/src/file/ignore.ts (Ignore.match). Callers of Ignore.match: zero. This is dead code.
packages/cli/src/util/glob.ts:24 and scanSync — delegate to the glob package which uses minimatch transitively. This is actively used (20+ call sites).
- Where do patterns come from?
- All
Glob.scan calls except two use hardcoded literal patterns ("**/*.ts", "storage/session/...", etc.)
packages/cli/src/util/filesystem.ts:198 Filesystem.globUp(pattern, ...) — pattern is a parameter
- Callers of
globUp: only packages/cli/src/session/instruction.ts:32,40, where the pattern is instruction from config.instructions (the user's local config file)
- Practical risk: to trigger a ReDoS, an attacker must edit the user's config file to add a catastrophic glob pattern. An attacker with local config-write access can already do much worse. Low priority for actual exploitability, but the dead
Glob.match path is worth deleting anyway while we're here.
Alert 5: @modelcontextprotocol/sdk cross-client data leak
- Advisory:
GHSA-345p-7cg4-v4c7 — two issues in stateless deployments:
- Reusing a single
StreamableHTTPServerTransport across multiple client requests (JSON-RPC message ID collisions leak responses)
- Reusing a single
McpServer/Server instance across multiple transports
- Current:
@modelcontextprotocol/sdk@1.25.2
- Target:
1.26.0 or later
- Exploitability in this codebase:
grep -rn 'StreamableHTTPServerTransport\|new McpServer\|new Server' packages/cli/src/ returns zero hits. The aictrl CLI is an MCP client — it connects to MCP servers configured by the user, it doesn't run one. The server-side instance-reuse bug simply doesn't apply.
- Why bump anyway: low-risk hygiene; defends against a future architecture change that introduces a server path.
Suggested plan
One PR, three coordinated bumps:
drizzle-orm → 1.0.0-beta.21 (or newer, wherever the beta dist-tag currently points) in all three declaration sites, keeping drizzle-kit in sync. Verify the overrides block still matches. Refresh bun.lock.
minimatch → 10.2.3 in packages/cli/package.json. Refresh bun.lock.
@modelcontextprotocol/sdk → 1.26.0+ in packages/cli/package.json. Refresh bun.lock.
- Run
bun turbo typecheck and the db migration tests — drizzle beta bumps are the most likely to break, since beta-track versions can ship breaking API changes between patches.
Optional but good hygiene while we're touching this: delete Glob.match + Ignore.match from util/glob.ts and file/ignore.ts since they're confirmed dead code (unrelated to the advisory fix, but surfaced during triage).
Investigation commands used
gh api repos/aictrl-dev/cli/dependabot/alerts --paginate # full alert list
grep -rn 'sql\.identifier\|\.as(' packages/cli/src/ # drizzle-orm exploitability
grep -rn 'Glob\.match\|minimatch(' packages/cli/src/ # minimatch reachability
grep -rn 'StreamableHTTPServerTransport' packages/cli/src/ # MCP server check
Dependabot is reporting 5 open high-severity alerts on
main. I triaged each against the current codebase while investigating the v0.3.2 release pipeline. Below is the full picture so whoever picks this up isn't starting from scratch.TL;DR
drizzle-orm@1.0.0-beta.12-a5629fbGHSA-gpj5-g38j-94v9sql.identifier()/.as()with user input1.0.0-beta.21+minimatch@10.0.3GHSA-7r86-cg39-jmmj10.2.3minimatch@10.0.3GHSA-23c5-xmqv-rm74minimatch@10.0.3GHSA-3ppc-4f35-3m26@modelcontextprotocol/sdk@1.25.2GHSA-345p-7cg4-v4c71.26.0+for hygieneAll three root packages live in
packages/cli/package.json. None of the advisories are currently exploitable in production use of the CLI, but the versions are plain out-of-date and should be bumped.Alert 1: drizzle-orm SQL injection via identifier escaping
GHSA-gpj5-g38j-94v9— Drizzle ORM improperly escapes quoted SQL identifiers in dialect-specificescapeName().sql.identifier()/.as()with attacker-controlled input enables injection.drizzle-orm@1.0.0-beta.12-a5629fbinpackages/cli/package.json,drizzle-kit@1.0.0-beta.12-a5629fbinpackages/cli/package.jsonand the rootpackage.jsonworkspace catalog. Plus a pinned override"drizzle-orm": "1.0.0-beta.12-a5629fb"inpackages/cli/package.json'soverrides.< 0.45.2→ fixed in0.45.2>= 1.0.0-beta.2, < 1.0.0-beta.20→ fixed in1.0.0-beta.20← we're in this range1.0.0-beta.21(currentbetadist-tag on npm). All three declarations need to stay in sync.grep -rn 'sql\.identifier\|\.as(' packages/cli/src/returns zero hits. The CLI uses drizzle purely with hardcoded table definitions (sqliteTable(...),eq()) against a localbun-sqlitedatabase. There is no dynamic identifier path reachable from user input or network.Alerts 2, 3, 4: minimatch ReDoS (three distinct patterns)
GHSA-7r86-cg39-jmmj— multiple non-adjacent**segments, O(C(n,k)) backtrackingGHSA-23c5-xmqv-rm74— nested*()extglobs (most severe; 12-byte minimum trigger)GHSA-3ppc-4f35-3m26— long runs of*+ non-matching literal, O(4^N)minimatch@10.0.310.2.3(all three advisories clear at this version — noteGHSA-3ppcsays fixed in10.2.1, but the other two gate to10.2.3, so10.2.3is the minimum to close all alerts)packages/cli/src/util/glob.ts:32— directminimatch()call inGlob.match(pattern, filepath). Callers ofGlob.match: onlypackages/cli/src/file/ignore.ts(Ignore.match). Callers ofIgnore.match: zero. This is dead code.packages/cli/src/util/glob.ts:24andscanSync— delegate to theglobpackage which usesminimatchtransitively. This is actively used (20+ call sites).Glob.scancalls except two use hardcoded literal patterns ("**/*.ts","storage/session/...", etc.)packages/cli/src/util/filesystem.ts:198Filesystem.globUp(pattern, ...)— pattern is a parameterglobUp: onlypackages/cli/src/session/instruction.ts:32,40, where the pattern isinstructionfromconfig.instructions(the user's local config file)Glob.matchpath is worth deleting anyway while we're here.Alert 5: @modelcontextprotocol/sdk cross-client data leak
GHSA-345p-7cg4-v4c7— two issues in stateless deployments:StreamableHTTPServerTransportacross multiple client requests (JSON-RPC message ID collisions leak responses)McpServer/Serverinstance across multiple transports@modelcontextprotocol/sdk@1.25.21.26.0or latergrep -rn 'StreamableHTTPServerTransport\|new McpServer\|new Server' packages/cli/src/returns zero hits. The aictrl CLI is an MCP client — it connects to MCP servers configured by the user, it doesn't run one. The server-side instance-reuse bug simply doesn't apply.Suggested plan
One PR, three coordinated bumps:
drizzle-orm→1.0.0-beta.21(or newer, wherever thebetadist-tag currently points) in all three declaration sites, keepingdrizzle-kitin sync. Verify theoverridesblock still matches. Refreshbun.lock.minimatch→10.2.3inpackages/cli/package.json. Refreshbun.lock.@modelcontextprotocol/sdk→1.26.0+inpackages/cli/package.json. Refreshbun.lock.bun turbo typecheckand the db migration tests — drizzle beta bumps are the most likely to break, since beta-track versions can ship breaking API changes between patches.Optional but good hygiene while we're touching this: delete
Glob.match+Ignore.matchfromutil/glob.tsandfile/ignore.tssince they're confirmed dead code (unrelated to the advisory fix, but surfaced during triage).Investigation commands used