paperclipai/paperclip · warning

[plugin-kubernetes] egressMode=standard cannot enforce FQDN-

Error message

[plugin-kubernetes] egressMode=standard cannot enforce FQDN-based egress rules. The following FQDNs are reachable only via operator-supplied egressAllowCidrs: ${totalFqdnsForWarn.join(", ")}. Switch egressMode to "cilium" for exact FQDN allow-listing.

What it means

Variant of the standard-mode egress warning: FQDN allow-lists are configured AND operator-supplied egressAllowCidrs exist. The FQDNs are reachable only through those CIDRs — standard NetworkPolicy cannot bind rules to hostnames. If a target service's IPs rotate (CDNs, provider endpoints), egress breaks silently because the CIDR list no longer matches.

Source

Thrown at packages/plugins/sandbox-providers/kubernetes/src/plugin.ts:323

    // The adapter for THIS run is the agent's adapter (params.adapterType) when
    // supplied, so one environment can serve mixed harnesses; otherwise fall back
    // to the environment's configured default adapter. getAdapterDefaults validates
    // it is a registered adapter (throws otherwise), so a curated-out adapter fails
    // the lease as before.
    const effectiveAdapterType = resolveRunAdapterType(params.adapterType, config.adapterType);

    // Emit a runtime warning if FQDNs are configured but egressMode=standard
    // cannot enforce them. Mirrors the validateConfig warning so operators see
    // it in paperclip-server logs even if they missed the validation step.
    const adapterDefaultsForWarn = getAdapterDefaults(effectiveAdapterType, config.adapters);
    const totalFqdnsForWarn = [...adapterDefaultsForWarn.allowFqdns, ...config.egressAllowFqdns];
    if (config.egressMode === "standard" && totalFqdnsForWarn.length > 0) {
      if (config.egressAllowCidrs.length === 0) {
        console.warn(
          `[plugin-kubernetes] egressMode=standard cannot enforce FQDN-based egress rules; falling back to public-IPv4 (TCP 80/443) with private/link-local ranges excluded so the configured FQDNs (${totalFqdnsForWarn.join(", ")}) remain reachable. Switch egressMode to "cilium" for exact FQDN allow-listing.`,
        );
      } else {
        console.warn(
          `[plugin-kubernetes] egressMode=standard cannot enforce FQDN-based egress rules. The following FQDNs are reachable only via operator-supplied egressAllowCidrs: ${totalFqdnsForWarn.join(", ")}. Switch egressMode to "cilium" for exact FQDN allow-listing.`,
        );
      }
    }

    const kc = createKubeConfig({
      inCluster: config.inCluster,
      kubeconfig: config.kubeconfig,
    });
    const clients = makeKubeClients(kc);

    // Ensure the tenant namespace and all its RBAC / network policy resources
    // exist before we try to create the Job.
    const adapterDefaults = getAdapterDefaults(effectiveAdapterType, config.adapters);

    await ensureTenant(clients, {
      namespace,
      companyId: params.companyId,

View on GitHub (pinned to 120ae5428f)

Solutions

  1. Prefer egressMode "cilium" for hostname-exact enforcement.
  2. If staying on standard, automate refreshing egressAllowCidrs from the FQDNs' current DNS resolution on a schedule.
  3. Widen CIDRs to the provider's officially published IP ranges instead of point-in-time resolutions.
  4. Remove FQDNs that are no longer needed to shrink the drift surface.

Example fix

// before
{
  "egressMode": "standard",
  "egressAllowFqdns": ["api.anthropic.com"],
  "egressAllowCidrs": ["160.79.104.0/23"]
}

// after
{
  "egressMode": "cilium",
  "egressAllowFqdns": ["api.anthropic.com"]
}
Defensive patterns

Strategy: validation

Validate before calling

// Keep CIDRs honest: verify each FQDN still resolves into the allow-list.
import dns from 'node:dns/promises';
import ip from 'ip6addr';

async function fqdnsCoveredByCidrs(fqdns: string[], cidrs: string[]): Promise<string[]> {
  const uncovered: string[] = [];
  for (const fqdn of fqdns) {
    const addrs = await dns.resolve4(fqdn).catch(() => [] as string[]);
    const covered = addrs.some((a) => cidrs.some((c) => ip.parse(c).contains(a)));
    if (!covered) uncovered.push(fqdn);
  }
  return uncovered;
}

Prevention

When it happens

Trigger: egressMode === 'standard', non-empty FQDN set, and non-empty egressAllowCidrs — the plugin emits this warn at lease creation to flag that FDN enforcement is indirect via the operator's CIDR list.

Common situations: Pinning a provider's API IPs in CIDRs; CDN IP rotation making the allow-list stale; providers publishing changing ranges; operators copying yesterday's DNS answers into config.

Related errors


AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18). Data as JSON: /api/errors/8ff8b4ddbf5e5f24. Report an issue: GitHub.