Skip to content

cadish v0.2.2

Choose a tag to compare

@github-actions github-actions released this 30 Jun 20:17

Clustering hardening + a Cadish Edge batch + cache-isolation/redirect security fixes. Every change is fail-closed and costs nothing when unused — a non-clustered, non-edge cadish on the request/response fast path is byte-for-byte unchanged. Go↔JS edge conformance is kept in lockstep (IR contract v6 → v9, additive fields only).

Highlights

Clustering — "one sharded cache", store-once restored

Surfaced by exercising a real 3-node cluster on staging (the in-process tests passed, but the binary behind a shared client hostname fetched every object from origin twice):

  • Objects are cached once per region again. A non-owner reverse-proxying to the owning peer dropped the original client Host and client IP, so the owner keyed a proxied request differently from a direct one — storing each object twice and doubling origin load. cadish now forwards the client Host + resolved client IP on the peer hop (and overwrites any client-forged X-Forwarded-For, closing a peer-hop spoof). [D103]
  • Correct client IP for owner-side ACL / rate-limit / geo decisions on proxied requests (same root cause). [D103]
  • read_through: a pass goes straight to origin (no peer hop), and writes (POST/PUT/…) reach origin intact instead of being sharded to a peer. [D102]
  • Self-dial guard is health-aware — a brief owner health flap can no longer route an object back to the local node and stall the coalescer.

All clustering changes are gated by the cluster { } block. A new 3-node single-location deployment guide is in deploy/README.md.

Cadish Edge — cache a workload it previously couldn't

On a high-cardinality media workload, cadish edge build went from 22 forced-pass directives (one forced-pass on a selecting directive fail-opens the whole site → the edge caches nothing) down to a small residual that correctly delegates to the server behind:

  • all (AND-composite) and query NAME VALUE matchers are now edge-native (were server-only → site-wide pass). A sub-term it can't honor still fails closed.
  • query_present NAME+ — per-name non-empty-value modifier (Varnish =[^&]+ parity).
  • redirect … no_store — marks a personalized redirect uncacheable.
  • +cache_age deliver special and {device} / {geo*} / {query.NAME} template tokens — reproduces the original worker's X-CF-Cache-Age / X-CF-Vary-* debug headers, cache-safe by construction (a class token forwarded to origin renders empty unless the selected cache_key recipe varies on that class).
  • cadish edge deploy -origin passthrough — fetch-through mode for a multi-host origin in the same CF zone (fixes the canonicalizing-origin redirect loop).
  • Edge worker-route exclusionsedge { bypass_passes } (auto-derived) and edge { bypass PATTERN… } (operator-declared): paths the edge only ever passes are projected as CF routes that run no worker. Plus an X-Cadish-Edge response marker (its absence = served directly by origin).
  • cadish edge deploy -allow-public-values — acknowledge non-secret literal cookie/header values past the deploy safety gate (does not relax the forced-pass gate).

Security

  • cache_credentialed: cross-user cache leak on a no-signal response — fixed (fail-closed). A credentialed in-scope response carrying no per-response signal, yet made cacheable by a co-existing cache_ttl default ttl N, was stored under the shared credential-free key — serving one user's private body to the next. The response phase now refuses unconditionally without the signal. Server and edge (both had the identical fail-open; present since 0.2.1).
  • Open redirect via a $N capture in a redirect target authority — fixed. A request-sourced token in the Location authority (e.g. GET /index.php@evil.example.com/) could drive an off-origin redirect. A new runtime post-expansion authority assertion (server + edge, byte-identical) re-expands with request-sourced inputs neutralized and suppresses the redirect if the authority differs — also normalizing away embedded/trailing C0 control bytes before the check.
  • Admin /api/config: absolute-path disclosure in diagnostic messages — fixed (message now scrubbed, not just position).

Full detail in CHANGELOG.md. Signed binaries + SBOMs are attached below; the multi-arch image is at ghcr.io/cadi-sh/cadish:0.2.2, and the Helm chart at oci://ghcr.io/cadi-sh/charts/cadish --version 0.2.2.