v0.6.84: redis pub/sub SNI override, security hardening, copilot reads trimmed#4641
Conversation
* fix(redis): apply TLS SNI override to pub/sub clients too Pub/sub clients in lib/events/pubsub.ts build their own ioredis instances directly via new Redis(redisUrl, ...) because pub/sub needs dedicated connections (can't multiplex on the shared client from getRedisClient). That path skipped the resolveTlsOptions helper added for trigger.dev's PrivateLink VPCE IP, so every pub/sub channel hit 'Hostname/IP does not match certificate's altnames' on connect. Export the helper as resolveRedisTlsOptions and use it from pubsub.ts. * refactor(redis): share connection defaults via one helper Extract keepAlive/connectTimeout/enableOfflineQueue + TLS SNI into a single getRedisConnectionDefaults helper. Main client and pub/sub clients both spread it; caller-specific retry/timeout policy stays per-caller (pub/sub still needs maxRetriesPerRequest: null and a different retry strategy for SUBSCRIBE). * fix(pubsub): surface TLS config errors instead of silently degrading resolveRedisTlsOptions (via getRedisConnectionDefaults) throws if REDIS_TLS_SERVERNAME is missing for an IP-based rediss:// URL. Calling it inside the constructor let createPubSubChannel's try/catch swallow the error and fall back to in-process EventEmitter — silent cross-replica pub/sub breakage in prod. Resolve defaults before the try so config errors propagate; only catch genuine runtime construction failures.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Updates Reviewed by Cursor Bugbot for commit 4945d55. Bugbot is set up for automated code reviews on this repo. Configure here. |
… authz (#4639) * fix(security): KB fileUrl LFI, MCP/Agiloft SSRF pinning, form OTP, KB authz * fix(otp): don't leak caught error.message; fail-closed on DB retry exhaust - Chat/form OTP routes: replace `error.message || fallback` with generic `Failed to process request` in 500 responses (logger still captures detail). - otp.ts incrementOTPAttempts DB path: on MAX_RETRIES exhaustion, delete the verification row and return `'locked'` instead of trusting a possibly- undercounted final read. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(mcp): use undici fetch directly in pinned-fetch for typed dispatcher Replace `globalThis.fetch` + double-cast with `undici.fetch` so the `dispatcher` option is part of the real type contract. This guarantees pinning won't silently break if a future runtime swaps the underlying fetch implementation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(build): keep agiloft/grafana tool configs client-safe Tool config files are statically reachable from the client bundle (via tools/registry.ts → tools/{service}/index.ts). Importing `@/lib/core/security/input-validation.server` from these files pulled `node:dns/promises` into the Turbopack client bundle and broke the build. Split agiloft utils into client-safe (`utils.ts`, plain fetch + sync `validateExternalUrl`) and server-only (`utils.server.ts`, DNS-pinned variants). Routes that need TOCTOU protection import the pinned helpers; the executor-side tool path falls back to sync URL validation (matches the supabase precedent and pre-PR baseline). Grafana update tools likewise switch from `secureFetchWithValidation` (server-only) to inline sync `validateExternalUrl` + plain fetch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(knowledge): case-insensitive scheme checks for fileUrl Boundary schema accepted uppercase schemes (e.g. HTTPS://, DATA:) via the case-insensitive http regex, but the processor's case-sensitive startsWith('data:') / startsWith('http') / startsWith('https://') checks rejected them with a confusing "Unsupported fileUrl scheme" error. Aligns processor checks to the schema using case-insensitive regex per RFC 3986 §3.1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(mcp): annotate undici/DOM type-bridge double-casts in pinned-fetch Strict audit was failing on two new `as unknown as` casts in pinned-fetch.ts. They bridge DOM `RequestInit`/`Response` ↔ undici equivalents (structurally compatible at runtime since Node's global fetch is undici) and are required to satisfy the FetchLike contract. Annotate so they count as documented exemptions instead of new violations. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Greptile SummaryThis PR refactors shared Redis connection options (keepAlive, connectTimeout, enableOfflineQueue, and TLS SNI override) into a new exported
Confidence Score: 5/5Safe to merge — the change is a clean refactor plus a targeted bug fix with no unintended side effects. Both files receive identical connection options to what they had before, with the addition of the TLS SNI override that was previously missing from the pub/sub clients. The error-surfacing behavior change in createPubSubChannel is intentional, well-commented, and consistent with how getRedisClient() already handled the same case before this PR. No files require special attention; both changed files are straightforward and the logic is easy to follow. Important Files Changed
Sequence DiagramsequenceDiagram
participant Caller
participant createPubSubChannel
participant getRedisConnectionDefaults
participant resolveRedisTlsOptions
participant RedisPubSubChannel
participant Redis as ioredis (pub + sub)
Caller->>createPubSubChannel: createPubSubChannel(config)
createPubSubChannel->>getRedisConnectionDefaults: getRedisConnectionDefaults(redisUrl)
getRedisConnectionDefaults->>resolveRedisTlsOptions: resolveRedisTlsOptions(url)
alt rediss plus IP host plus REDIS_TLS_SERVERNAME set
resolveRedisTlsOptions-->>getRedisConnectionDefaults: servername
getRedisConnectionDefaults-->>createPubSubChannel: keepAlive connectTimeout enableOfflineQueue tls
else rediss plus IP host plus REDIS_TLS_SERVERNAME missing
resolveRedisTlsOptions-->>createPubSubChannel: throws Error surfaces to Caller
else DNS host or non-TLS
resolveRedisTlsOptions-->>getRedisConnectionDefaults: undefined
getRedisConnectionDefaults-->>createPubSubChannel: keepAlive connectTimeout enableOfflineQueue
end
createPubSubChannel->>RedisPubSubChannel: new RedisPubSubChannel(redisUrl connectionDefaults config)
RedisPubSubChannel->>Redis: new Redis pub connection with SNI
RedisPubSubChannel->>Redis: new Redis sub connection with SNI
Redis-->>RedisPubSubChannel: connections established TLS SNI applied
RedisPubSubChannel-->>createPubSubChannel: instance
createPubSubChannel-->>Caller: PubSubChannel
Reviews (1): Last reviewed commit: "fix(security): KB fileUrl LFI, MCP/Agilo..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.