Skip to content

fix(deps): undici 7.30.2, mongoose 6.13.12, MCP SDK 1.32.2 (+ tool-input limit), compress 1.20.2, brotli 1.2.7 - #6

Merged
gascity-infra-agent[bot] merged 1 commit into
gascity-ssofrom
fix/sec5-p2-deps
Nov 10, 2026
Merged

gascity-infra-agent[bot] merged 1 commit into
gascity-ssofrom
fix/sec5-p2-deps

Conversation

@gascity-infra-agent

@gascity-infra-agent gascity-infra-agent Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Advisories fixed

Node (root yarn.lock)

Go (packages/otel-collector, the all-in-one migrate tool)

Code change: MCP tool-input limit (GHSA-46jr-4wx8-v453)

The advisory says upgrading alone changes nothing. 1.32.0 adds an McpServer option, maxToolInputElements, that is off by default.

  • packages/api/src/mcp/mcpServer.ts now sets it to MAX_TOOL_INPUT_ELEMENTS = 100_000. That counts array elements plus object keys in one tools/call arguments, and it is far above any input a model generates.
  • A call over the limit gets an isError: true result.
  • New unit test: src/mcp/__tests__/toolInputLimit.test.ts. It fails without the option: the oversized call reaches the tool handler. It passes with it.

Exposure on this route:

  • /mcp runs validateUserAccessKey before the SDK, and the deployment sits behind the gate, so only authenticated callers can reach the validation path.
  • The second step the advisory recommends is lowering the request body limit. This PR does not do that. The body is already parsed by upstream's global express.json({ limit: '32mb' }) in api-app.ts, which applies to every route, and the SDK's own 4 MiB cap does not apply to a pre-parsed body. The SDK's 100-message batch cap does still apply.

The rest of the 1.29 → 1.32.2 changes are additive or client-side:

  • Same-origin redirects only on the HTTP client transports.
  • An OAuth issuer binding.
  • An opt-in expectedResource on requireBearerAuth.
  • Tasks scoped to their session.
  • SSE keep-alive frames.
  • Content-Type parsed as a media type.

The api uses none of taskStore, requireBearerAuth, the HTTP client transports or the OAuth client. All MCP unit suites pass unchanged.

Age gate

undici 7.30.2 was published 2026-11-05, which is inside npmMinimalAgeGate: 7d. .yarnrc.yml preapproves undici, with a TODO to remove the entry once the release ages out. This follows the existing nx pattern.

Verification (on this commit)

All Node steps ran in node:22.23.4-alpine3.24@sha256:fe4f6d74…, using the gascity-pr.yml steps.

Check Result
yarn install --immutable OK
yarn workspace @hyperdx/api run lint 0 errors (301 warnings; the budget is 302)
tsc --noEmit (api) clean
CI focused Jest (proxyHeaderAuth|proxyAuth*|config) 4 suites, 82/82
All non-integration MCP Jest suites (src/mcp/) 25 suites, 466/466
API build + production-symbol guard OK, 10/10
Prod image (--no-cache --target prod, CI build contexts, built from a pristine git archive) OK
In the image node v22.23.4; undici 7.30.2, mongoose 6.13.12, mquery 4.0.4, MCP SDK 1.32.2, @hono/node-server 2.1.6; image symbol guard 10/10; SDK server modules load
gascity/smoke against the image 76/76: auth 31 (default) + 31 (SMOKE_TELEMETRY=off), telemetry 4, failclosed 3, rotation 7; seed written and read back across containers; 0 restarts. The only warnings are the two [MONGOOSE] errors is a reserved schema pathname lines, which are identical on the deployed 17098cbf image
go build ./... && go vet ./... && go test ./... (otel-collector) OK
govulncheck (otel-collector, Go 1.26.10 like the golang:1.26 builder) before: GO-2026-6888, GO-2026-6865. After: No vulnerabilities found
osv-scanner (yarn.lock + go.mod) 19 advisory IDs removed, 0 added. Removed: every GHSA above plus GO-2026-5841, -6865 and -6888

osv-scanner does not yet know the six undici CVE-2026-116592-series advisories or the mongoose CVE-2026-1251xx records. For those, the evidence is the resolved versions in yarn.lock: undici 7.30.2 is the only undici entry, and mongoose is 6.13.12.

Rollout

  1. Merge. gascity-image publishes 2.42.0-gascity-<sha12>.
  2. Repin the digest in internal-services flux/apps/hyperdx/hyperdx.yaml. That is a separate PR.
  3. Flux rolls it out (Recreate, about a 20 s gap). Check /api/health and /ready, and confirm 0 restarts.

Dependabot alerts ClickHouse#246, ClickHouse#249 and the others listed above should auto-close once this is on gascity-sso. The Go changes only affect the all-in-one image's migrate binary. The prod image that we deploy does not contain it.

Rollback

Revert this PR, then repin the previous image digest (sha256:17098cbf…).

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

…put limit), compress/brotli

Node (root yarn.lock):
- undici 7.30.0 -> 7.30.2 (via @ai-sdk/provider-utils ^7.29.0, lockfile
  only): CVE-2026-116592, -120474, -120415, -120423, -120222, -116630.
  7.30.2 was published 2026-11-05, inside the 7d npmMinimalAgeGate, so
  .yarnrc.yml preapproves `undici` with a TODO to drop it once the release
  ages out (same pattern as the existing nx entry).
- mongoose ^6.13.10 -> ^6.13.12 (6.13.10 -> 6.13.12; mquery 4.0.3 -> 4.0.4):
  CVE-2026-125117, -125118, -125116.
- @modelcontextprotocol/sdk ^1.27.1 -> ^1.32.2 (1.29.0 -> 1.32.2):
  CVE-2026-111768 / GHSA-46jr-4wx8-v453, CVE-2026-111769 /
  GHSA-6prh-2h8m-c8cw, and GHSA-22jm-h49p-29qw, GHSA-rvq5-wwqv-78pq,
  GHSA-6qxp-vccf-f47h, GHSA-f897-62hf-6gxq. The SDK widened its
  @hono/node-server range to ^1.19.9 || ^2.0.5, so that moves
  1.19.17 -> 2.1.6, which also clears GHSA-rmxm-3fg6-px4f (no 1.x fix).
- GHSA-46jr-4wx8-v453 is not fixed by the upgrade alone: the new
  maxToolInputElements option is off by default. Set it on the /mcp
  McpServer to 100,000 (far above any model-generated tool input) and
  add a unit test that an over-limit tools/call gets an isError result.

Go (packages/otel-collector, the all-in-one migrate tool):
- github.com/klauspost/compress v1.18.3 -> v1.20.2 (GO-2026-6865 /
  GHSA-fpmh-frq8-7rj8 / CVE-2026-116591; also GHSA-259r-337f-4rfw).
- github.com/andybalholm/brotli v1.2.0 -> v1.2.7 (GO-2026-6888).
  Targeted go get of the two indirect deps; no other module moved.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@gascity-infra-agent gascity-infra-agent Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Max-effort review: no HIGH or MED findings. Merging.

Everything below was re-verified on head a48d5181 against base ab064cce, which is unchanged.

Advisories

  • Resolved versions:
    • undici 7.30.2. It is the only copy, in both node_modules trees of the image.
    • mongoose 6.13.12, with mquery 4.0.4.
    • @modelcontextprotocol/sdk 1.32.2.
    • @hono/node-server 2.1.6.
  • Each is at or above the fixed version in the advisory records.
  • otel-collector: govulncheck v1.9.0 (go1.26.10, the builder's Go) reports no vulnerabilities. GO-2026-6865 and GO-2026-6888 are both gone.
  • The new go.sum lines match sum.golang.org.

Lockfile. yarn install --immutable against a cold cache recomputed every checksum.

CI-equivalent. I ran the gascity-pr steps from a pristine git archive, in node:22.23.4-alpine3.24@fe4f6d74…:

  • lint: 0 errors (301 warnings)
  • tsc: clean
  • focused jest: 82/82
  • all src/mcp jest suites: 25 suites, 466/466, with retries off
  • API build plus symbol guard: 10/10

Prod image. Built with --no-cache --target prod and the CI build contexts:

  • Node v22.23.4.
  • Symbol guard 10/10, and maxToolInputElements is present in build/mcp/mcpServer.js.
  • gascity/smoke: 76/76, in two runs. The deployed 17098cbf image also scores 76/76, with identical outcome lines.
  • The Go migrate binary is not in the prod target.

MCP over real HTTP. The MCP unit suites use InMemoryTransport, so they never exercise StreamableHTTPServerTransport → @hono/node-server 2.x. I drove /api/mcp (through the Next proxy) and the API port's /mcp with a personal access key, as an A/B against 17098cbf.

Identical on both images:

  • initialize (SSE, protocol 2025-06-18)
  • notifications/initialized → 202
  • tools/list (31 tools) and a tools/call
  • 401 / 405 / 406 / 415 responses
  • a Content-Type with charset
  • 40 early client disconnects, with 0 restarts

The differences are all intended SDK changes:

  • A tools/call with 100,001 argument elements now returns isError: true ("more than the maximum of 100000 elements"). The at-limit call still runs the tool.
  • A JSON-RPC batch over 100 messages now gets 400.
  • text/plain; x=application/json now gets 415.
  • SSE responses now carry Cache-Control: no-cache, no-transform and X-Accel-Buffering: no. As a result, compression() no longer gzips them, which is fine for SSE.

Follow-ups (LOW, non-blocking)

  1. Advisory step 2, a lower body limit, is not applied. The global express.json({ limit: '32mb' }) still parses /mcp bodies. In this deployment /mcp is reachable only through the SSO gate and with a personal access key, so what remains is an authenticated-user DoS. Consider mounting a /mcp-scoped express.json({ limit }) before the global parser, and lowering MAX_TOOL_INPUT_ELEMENTS (the advisory's example is 10,000).

  2. Nothing protects the new fork line from a silent rebase drop:

    • The gascity-pr focused-jest regex doesn't run toolInputLimit.test.ts.
    • Neither symbol guard checks maxToolInputElements.
    • GASCITY-FORK.md doesn't list it.

    Add the test to the regex, or build/mcp/mcpServer.js:maxToolInputElements to both guards, and record it in GASCITY-FORK.md.

  3. The .yarnrc.yml undici preapproval matches every undici version. It isn't needed for --immutable installs; with it removed, the immutable install still passes. Narrow it to undici@7.30.2 (Yarn 4.13 accepts descriptors there), or drop it after 2026-11-12 as its TODO says.

Pre-existing on both images, not from this PR

  • The API port's /mcp with a non-localhost Host returns 403. That's the SDK's default DNS-rebinding guard in createMcpExpressApp().
  • After a client hangs up mid-response on the app port, the next /api/mcp request through the Next proxy can get 400. It recovers within about 2 s.

🤖 Generated with Claude Code

@gascity-infra-agent
gascity-infra-agent Bot merged commit 59a28cb into gascity-sso Nov 10, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant