From c37e5919ce754eb791dfa53074d5982c3fdddd45 Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 12 May 2026 17:30:56 -0500 Subject: [PATCH] fix(plugin): restrict kubernetes cilium cidr egress --- .../kubernetes/src/cilium-network-policy.ts | 1 + .../sandbox-providers/kubernetes/src/types.ts | 24 +++++++++++++++++-- .../test/unit/cilium-network-policy.test.ts | 1 + .../kubernetes/test/unit/types.test.ts | 8 +++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/plugins/sandbox-providers/kubernetes/src/cilium-network-policy.ts b/packages/plugins/sandbox-providers/kubernetes/src/cilium-network-policy.ts index 5dedcf73..faaa466f 100644 --- a/packages/plugins/sandbox-providers/kubernetes/src/cilium-network-policy.ts +++ b/packages/plugins/sandbox-providers/kubernetes/src/cilium-network-policy.ts @@ -49,6 +49,7 @@ export function buildCiliumNetworkPolicyManifest(input: BuildCiliumNetworkPolicy if (input.egressAllowCidrs.length > 0) { egress.push({ toCIDRSet: input.egressAllowCidrs.map((cidr) => ({ cidr })), + toPorts: [{ ports: [{ port: "443", protocol: "TCP" }] }], }); } diff --git a/packages/plugins/sandbox-providers/kubernetes/src/types.ts b/packages/plugins/sandbox-providers/kubernetes/src/types.ts index 2a4407fa..8d984946 100644 --- a/packages/plugins/sandbox-providers/kubernetes/src/types.ts +++ b/packages/plugins/sandbox-providers/kubernetes/src/types.ts @@ -1,7 +1,27 @@ import { z } from "zod"; import { KNOWN_ADAPTER_TYPES } from "./adapter-defaults.js"; -const cidrRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/; +function isIpv4Cidr(value: string): boolean { + const [address, prefix, extra] = value.split("/"); + if (!address || !prefix || extra !== undefined || !/^\d+$/.test(prefix)) { + return false; + } + + const prefixNumber = Number(prefix); + if (prefixNumber < 0 || prefixNumber > 32) { + return false; + } + + const octets = address.split("."); + return octets.length === 4 && octets.every((octet) => { + if (!/^\d+$/.test(octet)) { + return false; + } + + const value = Number(octet); + return value >= 0 && value <= 255; + }); +} export const kubernetesProviderConfigSchema = z .object({ @@ -16,7 +36,7 @@ export const kubernetesProviderConfigSchema = z imagePullSecrets: z.array(z.string()).default([]), egressAllowFqdns: z.array(z.string()).default([]), - egressAllowCidrs: z.array(z.string().regex(cidrRegex, "Invalid CIDR")).default([]), + egressAllowCidrs: z.array(z.string().refine(isIpv4Cidr, "Invalid CIDR")).default([]), egressMode: z.enum(["cilium", "standard"]).default("standard"), defaultResources: z diff --git a/packages/plugins/sandbox-providers/kubernetes/test/unit/cilium-network-policy.test.ts b/packages/plugins/sandbox-providers/kubernetes/test/unit/cilium-network-policy.test.ts index 0e650363..592393ac 100644 --- a/packages/plugins/sandbox-providers/kubernetes/test/unit/cilium-network-policy.test.ts +++ b/packages/plugins/sandbox-providers/kubernetes/test/unit/cilium-network-policy.test.ts @@ -56,5 +56,6 @@ describe("buildCiliumNetworkPolicyManifest", () => { }); const cidrRule = cnp.spec.egress.find((e: { toCIDRSet?: { cidr: string }[] }) => e.toCIDRSet); expect(cidrRule.toCIDRSet[0].cidr).toBe("10.0.0.0/8"); + expect(cidrRule.toPorts).toEqual([{ ports: [{ port: "443", protocol: "TCP" }] }]); }); }); diff --git a/packages/plugins/sandbox-providers/kubernetes/test/unit/types.test.ts b/packages/plugins/sandbox-providers/kubernetes/test/unit/types.test.ts index c6f8ceb5..49aa65e3 100644 --- a/packages/plugins/sandbox-providers/kubernetes/test/unit/types.test.ts +++ b/packages/plugins/sandbox-providers/kubernetes/test/unit/types.test.ts @@ -36,4 +36,12 @@ describe("kubernetesProviderConfigSchema", () => { parseKubernetesProviderConfig({ inCluster: true, egressAllowCidrs: ["not-a-cidr"] }), ).toThrow(/CIDR/i); }); + + it("rejects CIDRs with invalid octets or prefixes", () => { + for (const cidr of ["999.0.0.0/8", "10.0.0.0/99", "10.0.0/24"]) { + expect(() => + parseKubernetesProviderConfig({ inCluster: true, egressAllowCidrs: [cidr] }), + ).toThrow(/CIDR/i); + } + }); });