Skip to content

fix(api): reject non-multipart uploads with 400, harden CI key recipes - #10

Merged
albanm merged 4 commits into
mainfrom
fix-missing-content-type
Aug 31, 2026
Merged

albanm merged 4 commits into
mainfrom
fix-missing-content-type

Conversation

@albanm

@albanm albanm commented Aug 31, 2026

Copy link
Copy Markdown
Member

Production logs showed Error: Missing Content-Type 500s from the upload endpoints, paired with client Parse Errors. Root cause: an API key pasted into a CI secret with a trailing newline lands verbatim in the x-api-key header and corrupts the HTTP request — the registry then sees the upload without its multipart Content-Type header, and busboy's constructor throws a plain Error that surfaced as a 500.

  • POST /artefacts/npm/:id and /artefacts/file/:name now validate the Content-Type before constructing busboy and map any remaining synchronous busboy constructor throw (wrong type, missing boundary) to a 400 with a readable message. Regression tests cover missing and non-multipart Content-Type on both endpoints.
  • The publish-plugin shared action and all five documented CI recipes strip whitespace from the key before the curl call, and the gotcha is documented at the key-copy step.
  • Dev-env chores: nodemon now ignores data-upstream/ (the upstream registry's scan-cache extractions were restarting both dev APIs mid-test, causing ECONNRESET flakes in the sync spec), plus regenerated ui auto-imports (unrelated drift, no functional change).

Regression risks:

  • Malformed uploads now return 400 instead of 500 — alerting keyed on these 500s goes quiet, and clients retrying on 5xx will stop retrying (intended).
  • Busboy constructor messages are forwarded verbatim in the 400 body — wording is coupled to busboy internals, nothing sensitive.
  • Well-formed multipart uploads are untouched; full artefacts + federation-sync api specs pass.

albanm and others added 4 commits August 31, 2026 15:15
Busboy's constructor throws a plain synchronous Error (seen in production
as "Missing Content-Type") when an upload request lacks a multipart
Content-Type header; it also throws for a wrong content type or a missing
boundary. These surfaced as 500 "failure while serving http request" logs.

Validate the Content-Type before constructing busboy in both upload
helpers and map any remaining constructor throw to a 400.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HsLRNvcquWp1ZKjfJUuET3
A key pasted into a CI secret with a trailing line break lands verbatim
in the x-api-key header and corrupts the HTTP request — depending on
curl/server versions the header block is terminated early, so the
registry sees the upload without its multipart Content-Type header
(the "Missing Content-Type" 500s seen in production).

Sanitize the key with `tr -d '[:space:]'` before the curl call in the
publish-plugin composite action and in all five documented CI recipes,
and document the gotcha in the API key setup section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HsLRNvcquWp1ZKjfJUuET3
@albanm
albanm merged commit 7489264 into main Aug 31, 2026
4 checks passed
@github-actions github-actions Bot added the fix label Aug 31, 2026
@albanm
albanm deleted the fix-missing-content-type branch August 31, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant