diff --git a/lib/alerts.ts b/lib/alerts.ts index b31c2ebb..c2d7d62f 100644 --- a/lib/alerts.ts +++ b/lib/alerts.ts @@ -1,6 +1,4 @@ -import { httpRequest } from '@socketsecurity/lib/http-request/request' - -import { buildJsonApiHeaders } from './http-helpers.ts' +import { buildJsonApiHeaders, socketHttpRequest } from './http-helpers.ts' export interface AlertsFilters { // Comma-separated subset of: low,medium,high,critical @@ -85,7 +83,9 @@ export async function fetchAlerts( const qs = buildAlertsQuery(options.filters).toString() const url = `${baseUrl}/v0/orgs/${encodeURIComponent(options.orgSlug)}/alerts${qs ? `?${qs}` : ''}` - const res = await httpRequest(url, { headers: buildJsonApiHeaders(options) }) + const res = await socketHttpRequest(url, { + headers: buildJsonApiHeaders(options), + }) if (!res.ok) { throw new Error(`alerts endpoint ${res.status}: ${res.text()}`) } diff --git a/lib/blob.ts b/lib/blob.ts index 81e249b5..ad7132e4 100644 --- a/lib/blob.ts +++ b/lib/blob.ts @@ -1,4 +1,4 @@ -import { httpRequest } from '@socketsecurity/lib/http-request/request' +import { socketHttpRequest } from './http-helpers.ts' export interface BlobResult { bytes: number @@ -188,7 +188,7 @@ export async function fetchRawBytes( options.onRequest?.(url) let res try { - res = await httpRequest(url, { headers }) + res = await socketHttpRequest(url, { headers }) } catch (e) { throw new Error(`blob request to ${url} failed: ${(e as Error).message}`) } diff --git a/lib/files.ts b/lib/files.ts index 33a48980..07c83a57 100644 --- a/lib/files.ts +++ b/lib/files.ts @@ -1,6 +1,4 @@ -import { httpRequest } from '@socketsecurity/lib/http-request/request' - -import { buildJsonApiHeaders } from './http-helpers.ts' +import { buildJsonApiHeaders, socketHttpRequest } from './http-helpers.ts' export function buildTree(entries: FileListEntry[]): TreeNode { const root: TreeNode = { name: '', isFile: false, children: new Map() } @@ -126,7 +124,7 @@ export async function fetchFileList( options.onRequest?.(url) let res try { - res = await httpRequest(url, { headers }) + res = await socketHttpRequest(url, { headers }) } catch (e) { throw new Error( `file-list request to ${url} failed: ${(e as Error).message}`, diff --git a/lib/http-helpers.ts b/lib/http-helpers.ts index fdb1cf3e..cdded939 100644 --- a/lib/http-helpers.ts +++ b/lib/http-helpers.ts @@ -2,6 +2,9 @@ import readline from 'node:readline' import type { IncomingMessage, ServerResponse } from 'node:http' import { errorMessage } from '@socketsecurity/lib/errors' +import { httpRequest } from '@socketsecurity/lib/http-request/request' +import type { HttpRequestOptions } from '@socketsecurity/lib/http-request/request-types' +import type { HttpResponse } from '@socketsecurity/lib/http-request/response-types' import { getTrustProxy } from './env.ts' import { logger } from './logger.ts' @@ -193,6 +196,26 @@ export function parseJsonObject( } } +// `@socketsecurity/lib@6.0.6`'s `httpRequest` advertises `Accept-Encoding: +// gzip, br` but never decompresses the response on its main path — only the +// unused `readIncomingResponse` bypass decodes. A `Content-Encoding: br` reply +// (e.g. the Socket file-list endpoint) then reaches `.json()`/`.text()` as raw +// compressed bytes and fails to parse with `Unexpected token '�'`. Until +// the lib decodes on its main path, force `Accept-Encoding: identity` so the +// server returns uncompressed bodies. The override is appended last so it wins +// the lib's header merge (and any caller header) regardless of order. Route +// every Socket-bound request through this wrapper so no call site can fall +// back onto the broken decode path. +export function socketHttpRequest( + url: string, + options: HttpRequestOptions = {}, +): Promise { + return httpRequest(url, { + ...options, + headers: { ...options.headers, 'Accept-Encoding': 'identity' }, + }) +} + // Helper for emitting JSON HTTP responses with a consistent Content-Type // and optional extra headers (used by writeOAuthError to attach // WWW-Authenticate). diff --git a/lib/oauth.ts b/lib/oauth.ts index 8edcc6f1..34adf57f 100644 --- a/lib/oauth.ts +++ b/lib/oauth.ts @@ -6,7 +6,6 @@ import { } from './env.ts' import { getSocketDebug } from '@socketsecurity/lib/env/socket' import { errorMessage } from '@socketsecurity/lib/errors' -import { httpRequest } from '@socketsecurity/lib/http-request/request' import { envAsBoolean } from '@socketsecurity/lib-stable/env/boolean' import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js' import type { IncomingMessage, ServerResponse } from 'node:http' @@ -14,6 +13,7 @@ import { assertSafeHttpUrl, getRequestHeaderValue, parseJsonObject, + socketHttpRequest, writeJson, writeOAuthError, } from './http-helpers.ts' @@ -230,7 +230,7 @@ export async function loadOAuthMetadata( 'SOCKET_OAUTH_ISSUER', ALLOW_LOCAL_OAUTH, ) - const response = await httpRequest( + const response = await socketHttpRequest( new URL(OAUTH_WELL_KNOWN_PATH, issuerUrl).href, ) const responseText = response.text() @@ -344,7 +344,7 @@ export async function verifyAccessToken( 'OAuth introspection_endpoint', ALLOW_LOCAL_OAUTH, ).href - const response = await httpRequest(introspectionUrl, { + const response = await socketHttpRequest(introspectionUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', diff --git a/lib/threat-feed.ts b/lib/threat-feed.ts index 8a37cc9a..0b4231f1 100644 --- a/lib/threat-feed.ts +++ b/lib/threat-feed.ts @@ -1,6 +1,4 @@ -import { httpRequest } from '@socketsecurity/lib/http-request/request' - -import { buildJsonApiHeaders } from './http-helpers.ts' +import { buildJsonApiHeaders, socketHttpRequest } from './http-helpers.ts' export interface ThreatFeedFilters { // 1..100. API caps at 100 and defaults to 30. @@ -98,7 +96,9 @@ export async function fetchThreatFeed( const qs = buildThreatFeedQuery(options.filters).toString() const url = `${baseUrl}/v0/orgs/${encodeURIComponent(options.orgSlug)}/threat-feed${qs ? `?${qs}` : ''}` - const res = await httpRequest(url, { headers: buildJsonApiHeaders(options) }) + const res = await socketHttpRequest(url, { + headers: buildJsonApiHeaders(options), + }) if (!res.ok) { throw new Error(`threat-feed endpoint ${res.status}: ${res.text()}`) } diff --git a/lib/tool-depscore.ts b/lib/tool-depscore.ts index a0757689..f5c33b8f 100644 --- a/lib/tool-depscore.ts +++ b/lib/tool-depscore.ts @@ -3,11 +3,10 @@ import { Type } from '@sinclair/typebox' import { getSocketDebug } from '@socketsecurity/lib/env/socket' import { errorMessage } from '@socketsecurity/lib/errors' import { envAsBoolean } from '@socketsecurity/lib-stable/env/boolean' -import { httpRequest } from '@socketsecurity/lib/http-request/request' import { deduplicateArtifacts } from './artifacts.ts' import { getSocketApiUrl } from './env.ts' -import { buildSocketHeaders } from './http-helpers.ts' +import { buildSocketHeaders, socketHttpRequest } from './http-helpers.ts' import { logger } from './logger.ts' import { buildPurl } from './purl.ts' import { AUTH_REQUIRED_MSG, errorResult, resolveAuthToken } from './server.ts' @@ -139,7 +138,7 @@ export async function handleDepscore( let response try { - response = await httpRequest(SOCKET_API_URL, { + response = await socketHttpRequest(SOCKET_API_URL, { method: 'POST', headers: buildSocketHeaders(accessToken), body: JSON.stringify({ components }), diff --git a/package.json b/package.json index 5e3d6851..b015668d 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,8 @@ "@sinclair/typebox": "catalog:", "@socketregistry/packageurl-js": "catalog:", "@socketregistry/packageurl-js-stable": "catalog:", - "@socketsecurity/lib": "npm:@socketsecurity/lib@6.0.3", - "@socketsecurity/lib-stable": "npm:@socketsecurity/lib@6.0.3", + "@socketsecurity/lib": "npm:@socketsecurity/lib@6.0.7", + "@socketsecurity/lib-stable": "npm:@socketsecurity/lib@6.0.7", "@socketsecurity/sdk": "catalog:", "@socketsecurity/sdk-stable": "catalog:", "@types/node": "^24.12.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6457a282..03ab57f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,7 +42,7 @@ catalogs: overrides: '@socketregistry/packageurl-js': 1.4.2 - '@socketsecurity/lib': 6.0.6 + '@socketsecurity/lib': 6.0.7 '@socketsecurity/registry': 2.0.2 '@socketsecurity/sdk': 4.0.1 semver@>=5.0.0 <7.6.0: 7.8.1 @@ -82,11 +82,11 @@ importers: specifier: 'catalog:' version: '@socketregistry/packageurl-js@1.4.2' '@socketsecurity/lib': - specifier: 6.0.6 - version: 6.0.6 + specifier: 6.0.7 + version: 6.0.7 '@socketsecurity/lib-stable': - specifier: npm:@socketsecurity/lib@6.0.3 - version: '@socketsecurity/lib@6.0.3' + specifier: npm:@socketsecurity/lib@6.0.7 + version: '@socketsecurity/lib@6.0.7' '@socketsecurity/sdk': specifier: 4.0.1 version: 4.0.1 @@ -813,19 +813,9 @@ packages: resolution: {integrity: sha512-yt9UfUzD02wZ7kwb67oe4jxG2D9JtgPqjrK/ans2BovFyeie0w8hvRR0MuOWM4mUt2371oFPp7NB6O5ZjYJmlw==} engines: {node: '>=18.20.8', pnpm: '>=11.0.0-rc.0'} - '@socketsecurity/lib@6.0.3': - resolution: {integrity: sha512-m6Rb7K+QQcwZehe8QOaO1aG6z1fVRtbVrlMmT5Luqelfrjppta3PuA5hfa2HDJ4hojrt+hAIpWbPZN5JBYrtkw==} - engines: {node: '>=22', pnpm: '>=11.3.0'} - hasBin: true - peerDependencies: - typescript: '>=5.0.0' - peerDependenciesMeta: - typescript: - optional: true - - '@socketsecurity/lib@6.0.6': - resolution: {integrity: sha512-PpQmnoqKnBONOtimHWB1Mp/qzJhpPXIN4hwQUS99F015DiG1VGNNW5nARPVvHfxOSADCdK5mvtMM+Gl8giGOFg==} - engines: {node: '>=22', npm: '>=11.16.0', pnpm: '>=11.4.0'} + '@socketsecurity/lib@6.0.7': + resolution: {integrity: sha512-W7lhNnZ6areTQLWG2Bh3r3hs2F9hvRqtUp1zj79KxBFGB39KUvO3Mc9Kqqvwlu9T91qQtIxf00JlzLbVd16KMg==} + engines: {node: '>=22', npm: '>=11.16.0', pnpm: '>=11.5.1'} hasBin: true peerDependencies: typescript: '>=5.0.0' @@ -2736,9 +2726,7 @@ snapshots: '@socketregistry/packageurl-js@1.4.2': {} - '@socketsecurity/lib@6.0.3': {} - - '@socketsecurity/lib@6.0.6': {} + '@socketsecurity/lib@6.0.7': {} '@socketsecurity/sdk@4.0.1': {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e8447be6..38b7548a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -14,8 +14,8 @@ catalog: '@sinclair/typebox': 0.34.49 '@socketregistry/packageurl-js': 1.4.2 '@socketregistry/packageurl-js-stable': npm:@socketregistry/packageurl-js@1.4.2 - '@socketsecurity/lib': 6.0.6 - '@socketsecurity/lib-stable': npm:@socketsecurity/lib@6.0.6 + '@socketsecurity/lib': 6.0.7 + '@socketsecurity/lib-stable': npm:@socketsecurity/lib@6.0.7 '@socketsecurity/registry': 2.0.2 '@socketsecurity/registry-stable': npm:@socketsecurity/registry@2.0.2 '@socketsecurity/sdk': 4.0.1