Tags: git-pkgs/registries
Tags
Let a tripped circuit breaker keep retrying instead of latching open (#… …70) * Let a tripped circuit breaker keep retrying instead of latching open * Add the circuit breaker recovery and probe cadence tests These were written alongside the fix but never made it into the commit: the file was untracked when the change was applied, so committing with -a skipped it. The PR therefore described coverage that was not in the diff, and left the clock field on CircuitBreakerFetcher as a test hook with no test using it. TestCircuitBreakerRecoversAfterProlongedOutage trips a breaker against a 503 server, advances a mock clock through an hour of failing probes, then brings the server back and asserts the next fetch succeeds and the breaker reports closed. It fails without MaxElapsedTime = 0, with the production symptom: "circuit breaker open for registry ...". TestCircuitBreakerProbesOncePerBackoffInterval asserts that an open breaker lets exactly one request per backoff interval reach the registry, refuses a second call in the same interval without contacting it, and wraps ErrUpstreamDown on both paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(npm): handle boolean-form deprecated field (#48) The npm packument spec defines a version's `deprecated` field as a string carrying the deprecation message, but some packuments emit a boolean instead (false meaning "not deprecated", true meaning deprecated with no message). The struct typed it as `string`, so unmarshalling failed with "cannot unmarshal bool into Go struct field versionInfo.versions.deprecated of type string" and FetchVersions returned an error for the whole package (e.g. react, which has 5 versions with `deprecated: false`). Introduce a `deprecatedField` string type with a custom UnmarshalJSON that accepts a string, boolean, or null and normalizes them to the string form the rest of the code relies on. Strings are kept verbatim; `true` maps to "true" (deprecated); `false` and null map to "" (not deprecated). This preserves the existing non-empty check that drives StatusDeprecated, so boolean-false versions stay active while string/true versions stay deprecated. Adds TestFetchVersions_DeprecatedShapes covering absent, string-message, boolean-false, and boolean-true forms.
safehttp: SSRF-safe transport for client and fetch (#24) Adds an HTTP transport that hardens registry fetches against three related threats: * Server-Side Request Forgery via a registry / CDN that 30x's to an internal address (http://localhost, RFC1918, link-local, ...) so the client probes services it shouldn't reach. * DNS rebinding between resolve and connect — the IP that comes back from DNS is not necessarily what gets connected to if the resolver cache or upstream is poisoned. * Redirect-target exfiltration via non-http(s) schemes (file://, gopher://, data://) returned in a Location header. Three defences in concert: 1. Dial-time IP gate. DNS is resolved once per dial; each resolved address is checked against the block list (loopback, RFC1918, CGNAT 100.64.0.0/10, link-local, multicast, unspecified) before any TCP connect. The connection then dials the resolved IP directly, so a rebind between check and connect cannot escape. 2. Redirect cap at 10 hops, re-validating every target through the same dial gate. 3. Non-http(s) scheme rejected on redirect. New package github.com/git-pkgs/registries/safehttp holds the transport. client.WithSafeHTTP() opts a Client into it. The fetch package's existing dnscache-backed dialer now gates each resolved IP against safehttp.CheckIP before connecting. Loopback opt-out via safehttp.EnableLoopbackForTesting (called from TestMain) keeps existing httptest.Server-backed test suites working; production paths never see the opt-out.
PreviousNext