Skip to content

ci: unpin the registry for the audit's advisory API, and clear the advisory it finds - #278

Merged
netanelgilad merged 2 commits into
mainfrom
claude/pr-272-failures-wvvpv6
Sep 7, 2026
Merged

ci: unpin the registry for the audit's advisory API, and clear the advisory it finds#278
netanelgilad merged 2 commits into
mainfrom
claude/pr-272-failures-wvvpv6

Conversation

@netanelgilad

@netanelgilad netanelgilad commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

The Security Audit job has failed on every run for three weeks, on main and on every PR. It was not reporting clean and it was not reporting a vulnerability: it was not reporting at all.

npm warn audit 400 Bad Request - POST https://registry.npmjs.org/-/npm/v1/security/audits/quick
{ statusCode: 400, error: 'Bad Request', message: 'Invalid request payload JSON format' }
npm error audit endpoint returned an error

Two commits: the first makes the gate report again, the second clears what it then reports.

1. Why the gate stopped reporting

.github/actions/wix-gateway-proxy pins registry.npmjs.org in /etc/hosts, which routes the entire host through the embargo gateway, npm's advisory API included. npm POSTs to /-/npm/v1/security/advisories/bulk first and falls back to the retired /-/npm/v1/security/audits/quick when that fails, logging the first error only at --loglevel silly so it never appears. The fallback then 400s and the job exits 1 before reading a single advisory.

#247 called this out in advance: "security-audit.yml runs npm audit, which POSTs to the registry's bulk-advisory endpoint through the pinned gateway. If the gateway doesn't proxy that endpoint, the weekly audit will fail loudly."

Timeline, from the workflow's run history:

Run Date Result
201 3 Aug success (last green)
12 Aug gateway lands (#248)
203 16 Aug failure (first run after)
204-261 16 Aug - 6 Sep failure, all of them, identically

Not an npm-version problem: the audit code in npm 10.8.2 (this runner) and 10.9.7 is byte-identical (prepareBulkData and _getReport both diff clean), and the same command against the public registry resolves the bulk endpoint and reports normally. A Node 24 bump does not fix it.

The fix drops the /etc/hosts pin after npm ci, so only the audit steps resolve the registry publicly. This does not weaken the embargo: auditing downloads no package code, and npm ci is the only step in this job that fetches tarballs, so every byte that reaches disk still comes through the gateway, in the same order, from the same lockfile. .github/scripts/check_wix_proxy_steps.py enforces that the action runs as step 2 of every job, which it still does.

2. What it then reported

With the endpoint reachable, the gating step immediately found a high-severity advisory that had been sitting on main invisibly for the whole outage:

socket.io-parser  4.0.0 - 4.2.6
Severity: high
Socket.IO: Zero-attachment Memory Exhaustion — GHSA-2m8v-j782-fhvr

It arrives via socket.io-client, a production dependency, so --omit=dev does not skip it — and it ships to consumers of the SDK, where it lands in their own scans.

socket.io-client@4.8.3 declares socket.io-parser: ~4.2.4, so 4.2.7 is already in range. The second commit refreshes that one lockfile entry: no package.json change, no range change, no new package, three lines in a single entry.

Verified rather than assumed:

  • The tarball's sha512 was computed locally and matches the integrity the lockfile now records, so the hash is not just the registry's own claim
  • 4.2.7 was published 2026-07-15, 54 days ago, well past the 14-day min-release-age cooldown in .npmrc (npm 10.x ignores that setting, so the age was checked by hand rather than left to the resolver)
  • The resolved URL stays on registry.npmjs.org, as do all 394 entries

Verification

Check Result
check_wix_proxy_steps.py verified 8 of 8 jobs
test_check_wix_proxy_steps.py 11 tests, OK
npm ci installs socket.io-client@4.8.3 → socket.io-parser@4.2.7
npm run lint clean
npm test 286 passed (24 files)
npm audit --omit=dev --audit-level=high 0 vulnerabilities, exit 0

The intermediate commit is genuinely useful history here: CI on it shows the failure message changing from audit endpoint returned an error to a real advisory report, which is the proof the unpin works, independently of the dependency fix. Each commit is revertable on its own.

Not fixed here

The informational all-deps step (continue-on-error: true, does not gate) now reports 7 high advisories in dev dependenciesbrace-expansion, browserslist, js-yaml, linkify-it, nanoid, postcss, @humanfs/node. These accumulated unseen during the outage and are the first thing anyone has been able to see about them in three weeks. Left for their own change rather than widening this one.

Follow-up

Reported to the embargo gateway owners. The durable fix is theirs: proxy POST /-/npm/v1/security/* faithfully (preserving Content-Encoding: gzip, which npm sets on both audit requests) or pass those paths through. The gateway does forward these POSTs upstream today — the 400 and the retirement notice both come from npm itself — so the body is arriving mangled rather than being refused by policy. The unpin step comes out once that lands; the comment in the workflow says so.

Worth knowing for triage: javascript-sdk is the only repo of the twelve in this org's set that runs npm audit in CI at all, so nobody else will report this and it will likely be triaged low.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sw4VYAkAmuJkff162j1hbv

The Security Audit job has failed on every run since the Wix embargo
gateway landed in #248. The last green run predates it (run 201, 3 Aug;
the gateway merged 12 Aug; run 203, the first run after, was red and so
has every run since). Both audit steps fail identically:

    npm warn audit 400 Bad Request - POST
      https://registry.npmjs.org/-/npm/v1/security/audits/quick
    { statusCode: 400, error: 'Bad Request',
      message: 'Invalid request payload JSON format' }
    npm error audit endpoint returned an error

The gateway action pins registry.npmjs.org in /etc/hosts, which routes
the whole host through the gateway, npm's advisory API included. npm
POSTs to /-/npm/v1/security/advisories/bulk first and falls back to the
retired /-/npm/v1/security/audits/quick when that fails, swallowing the
first error at silly log level. The fallback then 400s, so the job exits
1 without reading a single advisory: the gate has been reporting nothing
for three weeks rather than reporting clean.

It is not npm's version. The audit code in npm 10.8.2 (this runner) and
10.9.7 is byte-identical, and the same command against the public
registry resolves the bulk endpoint and reports normally.

So drop the pin after the install. Auditing downloads no package code,
and `npm ci` is the only step here that fetches tarballs, so every byte
that reaches disk still comes through the gateway and the embargo is
unchanged. .github/scripts/check_wix_proxy_steps.py enforces that the
action runs as step 2 of every job, which it still does.

This makes the gate report again; it does not make it pass. The audit
finds socket.io-parser 4.2.6 (GHSA-2m8v-j782-fhvr, high) via
socket.io-client, a production dependency, so --omit=dev does not skip
it. A one-line lockfile bump to 4.2.7 clears it, in range of the
existing ~4.2.4 declaration, and is in flight separately on
sdk-audit-fix. Left out of this change so the CI fix and the dependency
fix stay separately revertable.

Reported upstream to the gateway owners: the fix there is to proxy
/-/npm/v1/security/* faithfully, after which this step comes out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sw4VYAkAmuJkff162j1hbv
@netanelgilad netanelgilad self-assigned this Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/sdk@0.8.46-pr.278.d5b4fe4

Prefer not to change any import paths? Install using npm alias so your code still imports @base44/sdk:

npm i "@base44/sdk@npm:@base44-preview/sdk@0.8.46-pr.278.d5b4fe4"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "@base44/sdk": "npm:@base44-preview/sdk@0.8.46-pr.278.d5b4fe4"
  }
}

Preview published to npm registry — try new features instantly!

With the previous commit the audit reaches the advisory API again, and
the first thing it reports is a high-severity advisory that has been on
main the whole time the gate was broken:

    socket.io-parser  4.0.0 - 4.2.6
    Socket.IO: Zero-attachment Memory Exhaustion
    GHSA-2m8v-j782-fhvr

It reaches us through socket.io-client, a production dependency, so
--omit=dev does not skip it and the gating step exits 1. It also ships to
consumers of the SDK, where it lands in their own scans.

socket.io-client 4.8.3 declares socket.io-parser ~4.2.4, so 4.2.7 is
already in range: this refreshes the one lockfile entry and nothing else.
No package.json change, no range change, no new package, and the diff is
three lines in a single entry.

Verified rather than assumed:

- The tarball's sha512 was computed locally and matches the integrity the
  lockfile now records, so the hash is not just the registry's own claim.
- 4.2.7 was published 2026-07-15, 54 days ago, well past the 14-day
  min-release-age cooldown in .npmrc (npm 10.x ignores that setting, so
  the age was checked by hand rather than left to the resolver).
- The resolved URL stays on registry.npmjs.org, as do all 394 entries.
- npm ci installs it (socket.io-client 4.8.3 -> socket.io-parser 4.2.7),
  eslint is clean, and all 286 tests across 24 files pass.
- npm audit --omit=dev --audit-level=high: 0 vulnerabilities, exit 0.

The report-only step still lists 7 high advisories in dev dependencies,
which accumulated unseen while the gate was down. They do not gate and
are left for their own change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sw4VYAkAmuJkff162j1hbv
@netanelgilad netanelgilad changed the title ci: unpin the registry for the audit's advisory API ci: unpin the registry for the audit's advisory API, and clear the advisory it finds Sep 7, 2026
@netanelgilad
netanelgilad merged commit 3b1f27f into main Sep 7, 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.

3 participants