From 436185818d488895ee08a7298131f6b98fc62f25 Mon Sep 17 00:00:00 2001 From: Andrew Stoltz Date: Thu, 23 Apr 2026 20:12:25 -0500 Subject: [PATCH] fc-distribution: restrict public IngressRoute to GET+HEAD only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live verification 2026-04-24 caught POST /blobs on dist.flowercore.io returning 201 Created with the blob persisted — admin write operations reachable on the public surface. Controller-level strict entitlement was on, but that gates reads; writes weren't blocked at all. Fix: add Method(GET) || Method(HEAD) to the Host match on the public IngressRoute. POST/PUT/PATCH/DELETE now miss every route for dist.flowercore.io and Traefik returns 404 before the pod sees the request. Edge-level defense-in-depth on top of the controller's strict-mode entitlement check. The internal IngressRoute for dist.iamworkin.lan stays unrestricted — admin POST /blobs + POST /manifests flows keep working from the lab. --- apps/fc-distribution/fc-distribution.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/fc-distribution/fc-distribution.yaml b/apps/fc-distribution/fc-distribution.yaml index 0f6d4dc..ec7a949 100644 --- a/apps/fc-distribution/fc-distribution.yaml +++ b/apps/fc-distribution/fc-distribution.yaml @@ -331,7 +331,12 @@ spec: entryPoints: - websecure routes: - - match: Host(`dist.flowercore.io`) + # Method allowlist: Host + (GET || HEAD). Anything else misses every + # route and Traefik returns 404 before reaching the pod — edge-level + # defense-in-depth over the controller's strict-mode entitlement check. + # Together these block admin ops (POST /blobs, POST /manifests*) from + # ever being processed on the public surface. + - match: Host(`dist.flowercore.io`) && (Method(`GET`) || Method(`HEAD`)) kind: Rule middlewares: - name: dist-public-profile-header