Two different changes on the npm registry are breaking audit right now, and almost every thread I have read mashes them into one bug. One is a planned retirement: the old audit endpoints return 410 Gone, which took out pnpm audit on all of 10.x and yarn audit on Yarn Classic. The other is newer and worse. The replacement bulk endpoint started shipping gzip-compressed bodies with no Content-Encoding header, so npm audit on 11.x and 12.x chokes on the first byte and prints a warning instead of an error. Same symptom, opposite fixes, and the second one can wave a broken audit straight through your CI gate.

One symptom, two registry bugs

The reason "my audit stopped working" is so confusing this month is that it now means two unrelated things depending on which client you run.

Cause one is a deliberate shutdown. Both /-/npm/v1/security/audits and /-/npm/v1/security/audits/quick now answer 410 Gone with the body "This endpoint is being retired. Use the bulk advisory endpoint instead." Per npm's community discussion #192768, the legacy endpoints went through a scheduled brownout and were fully retired after July 15, 2026, with pnpm and Yarn v1 named as impacted. The pnpm maintainers, in issue #11265, describe pnpm audit as "completely broken" on v10.33.0 and every prior 10.x release. This is the same registry surface that changed under the npm 12 install-script lockdown, so if you are already patching that, put audit on the same list.

Cause two is a fault on the new endpoint, and it is the one that should worry you. npm issue #9804, opened around July 26, 2026 and affecting 12.0.1 plus a string of 11.x releases, shows /-/npm/v1/security/advisories/bulk returning gzip bytes without a Content-Encoding: gzip header once the payload passes roughly 1 KB. npm cannot tell the body is compressed, tries to parse raw gzip as JSON, and emits npm warn audit invalid json response body ... reason: Unexpected token '\x1f'. 0x1f is the first byte of the gzip magic number 1f 8b. The error is npm reading a gzip header as text.

Why the 410 is a retirement, not an outage

Treating the 410 as a transient blip is the first trap. It is not going to clear on its own. The endpoint is gone by design, and the fix is to move to a client that calls the bulk advisory endpoint. pnpm v11+ already does. npm audit already did. yarn audit on Yarn Classic never will, because Yarn v1 is EOL and no one is porting it.

Downstream scanners inherited the break. The OWASP DependencyCheck project filed three separate issues, #8421, #8422, and #8423, to rip out its /quick-based analyzers for pnpm, npm-classic, and Yarn, because versions up to 12.2.0 wrap the retired endpoint. If your pipeline runs DependencyCheck against a Node lockfile and started erroring in PnpmAuditAnalyzer or YarnAuditAnalyzer, that is this, not your config.

The gzip bug that fails your CI open

Here is the part that changes how much you should trust a green pipeline. npm treats a parse failure as a warn, not an error. A warning does not fail the step. So npm audit on 11.x or 12.x can hit the unlabeled-gzip response, fail to parse it, print the warning, and still exit zero with an empty advisory set. Your security gate reports zero vulnerabilities and passes, and you cannot tell from the exit code whether that means "clean" or "the audit never ran."

The failure is size-gated, which is why it looks intermittent and per-project. Responses under about 1 KB come back as uncompressed JSON and succeed, so a tiny lockfile audits fine. A large dependency tree crosses the threshold, gets unlabeled gzip, and breaks. Setting Accept-Encoding: identity does not help, because the server ignores it. There is no client-side workaround, and upgrading npm changes nothing, because the bug lives on the registry.

pnpm handles the same class of bad response more safely: it surfaces ERR_PNPM_AUDIT_BAD_RESPONSE and exits non-zero. That turns your pipeline red, which is noisy, but a red build you can see beats a green one that lied.

The differential, so you fix the right thing

Read the URL and the status in the error before you touch anything. That one string tells you which bug you have and who owns the fix.

You seeTool / versionRoot causeReal fix
ERR_PNPM_AUDIT_BAD_RESPONSE ... responded with 410pnpm 10.x and earlierLegacy endpoint retiredUpgrade to pnpm v11+ (uses bulk endpoint)
yarn audit fails with 410Yarn Classic v1Legacy endpoint retired, no migration comingMove audit to npm audit or Trivy / osv-scanner
npm warn audit invalid json response body ... '\x1f'npm 11.x / 12.xBulk endpoint serves unlabeled gzip (server bug)No client fix; do not let the warn pass your gate
PnpmAuditAnalyzer / YarnAuditAnalyzer errorsDependencyCheck ≤ 12.2.0Wraps the retired /quick endpointUpgrade DependencyCheck or switch to OSV data

The path through both failures looks like this:

audit commandwhich endpoint?410 Gonelegacy client, upgrade the toolpayload size?uncompressed JSON, audit worksunlabeled gzip bodyUnexpected token 0x1f, npm warns and exits 0"/security/audits or /quick""/security/advisories/bulk""under ~1 KB""over ~1 KB"

Why the circulating fix is cargo-cult

The top-voted answers under these threads are npm cache clean --force, "try again later," and "check your corporate proxy." None of them touch either root cause. A cache clean cannot un-retire a 410 endpoint, and it cannot re-add a Content-Encoding header the server chose to omit. Following that advice on the gzip bug is worse than doing nothing, because it burns time while your gate keeps passing un-audited builds. If an assistant hands you the cache-clean answer, it is working from a world before July 26 and does not know the second bug exists.

The honest counterpoint: for a brief window during the brownout, retrying did sometimes work, because the legacy endpoints were flapping before they went fully dark. That is over. After July 15 the 410 is permanent, and the gzip fault is deterministic on payload size, not luck.

What to run this week

Order these by what bites first.

  1. Assert the audit actually produced data. This is the urgent one, because it closes the fail-open hole today regardless of the registry. In CI, do not trust the exit code alone. Capture the JSON and check for a real result key before you call the step clean:
   npm audit --json > audit.json || true
   jq -e '(.vulnerabilities // .metadata.vulnerabilities // .advisories) != null' audit.json \
     || { echo "npm audit returned no advisory data; failing closed"; exit 1; }

If the gzip bug swallowed the response, audit.json will not carry a vulnerabilities block, and the step fails instead of passing empty.

  1. Upgrade off the retired endpoints. If the error contains /security/audits or /security/audits/quick with a 410, you are past the deadline. Move pnpm to v11+, bump DependencyCheck above 12.2.0, and migrate any yarn audit on Yarn Classic to npm audit or a scanner with its own database.
  2. Move the audit off the critical path until the bulk endpoint is fixed. Run npm audit as a non-blocking report and put the enforcing gate on a scanner that carries its own advisory data. Trivy or Grype, chosen by the job, or an SBOM scan where you filter Grype with a VEX statement, all pull from OSV or the GitHub Advisory Database rather than the registry endpoint that is currently broken. osv-scanner against your lockfile is the fastest drop-in.
  3. Stop treating one endpoint as your whole supply-chain gate. A control that depends on a single vendor endpoint has a single point of failure, and both of these bugs are that failure showing up. Pair audit with a second advisory source, and pair it with dependency cooldowns so a fresh malicious release cannot land in your tree between audit runs anyway. The same discipline that made the npm --allow-scripts change survivable applies here: assume the registry surface will move again and do not wire a single call into your only gate.

FAQ

Why does npm audit say 'invalid json response body' with an 0x1f token? The bulk advisory endpoint returns a gzip-compressed body with no Content-Encoding header once the payload passes about 1 KB. npm parses the raw gzip as JSON and chokes on 0x1f, the first byte of the gzip magic number. It is server-side, so upgrading npm does not fix it.

Why does pnpm audit or yarn audit return 410 Gone? npm retired the legacy /-/npm/v1/security/audits and /audits/quick endpoints. pnpm 10.x and Yarn Classic still call them. Upgrade to pnpm v11+, which uses the bulk endpoint; Yarn Classic is EOL and will not get one.

Does npm audit fail the build when this happens? No. It treats the parse failure as a warning, so the step can exit zero with an empty advisory set. Add an explicit assertion that the audit returned data, or the gate passes an un-audited build as clean.

Sources