You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The openab Helm chart (charts/openab/) and raw manifests (k8s/) currently ship without any NetworkPolicy resource. Once deployed, agent pods can freely initiate and receive traffic to/from every other pod in the namespace — and, on most CNIs without a default-deny baseline, to/from every other pod in the cluster.
This surfaced as a Medium-severity IaC finding in an internal AppSec scan (automation confidence 93%): "a NetworkPolicy is a way to define how pods are allowed to communicate with each other over the network. By default, pods are allowed to communicate with any other pod within the same namespace, which can create security risks." The finding is valid — grep -r NetworkPolicy charts/ k8s/ returns zero matches. No shared upstream terraform / k8s-workload module supplies one either; the chart is fully self-contained.
For a workload whose whole job is executing LLM-driven agents (some tool-using, some code-executing), unrestricted pod-to-pod traffic and unrestricted egress are non-trivial concerns:
Lateral movement: an agent pod compromised via prompt-injection or a hostile tool result has unrestricted access to co-tenant workloads (databases, Vault, other agents' PVCs, etc.) in the same namespace.
Egress abuse: agent commands can reach arbitrary internal endpoints (cloud metadata service, admin APIs, internal SaaS), not just the intended LLM / Slack / Discord APIs.
Compliance pushback: downstream enterprise deployments (a Dataminr fork of this chart, for example) are being asked by AppSec to justify or fix this today. Without a chart-provided template, every downstream hand-rolls its own — different labels, different selector conventions, different levels of correctness.
Use Case
Give operators an opt-in, well-labelled NetworkPolicy they can flip on with a single value, without having to reverse-engineer the chart's pod selectors, gateway topology, or which ports actually matter.
Concrete scenarios:
Enterprise deployment (e.g. Dataminr fork) — AppSec ticket requires a NetworkPolicy on k8s/deployment.yaml. Today the fix path is: fork the chart, hand-write the policy, keep it in sync forever. Proposal: --set networkPolicy.enabled=true closes the finding.
Multi-tenant namespace — cluster admin runs openab next to unrelated workloads and wants agent pods walled off. Today: hand-write from scratch, hope the pod selector matches. Proposal: chart uses the same openab.selectorLabels helper the Deployment already uses, so ingress/egress selectors can never drift.
Gateway + agent split — gateway pod needs webhook ingress (Telegram / LINE / Teams / Feishu / WeCom / Google Chat hit it), agent pods do not. Today: two hand-written policies. Proposal: chart renders the right policy per resource based on gateway.enabled.
Egress-restricted enterprise cluster (per @pahud, see comment) — org policy is deny-all egress; all outbound traffic must be routed through a designated proxy (e.g. OpenSHELL, Squid, Envoy) that owns the domain allowlist. Today: hand-write a to: podSelector: {...proxy...} policy. Proposal: networkPolicy.egress.mode=proxy + egress.proxy.{namespace,podSelector,ports} renders the correct policy shape, chart stays proxy-agnostic (BYO proxy).
Proposed Design
Backwards-compatible, opt-in. Default networkPolicy.enabled: false — no rendered resource, no behaviour change for existing releases. Mirrors the established openab pattern (slack.enabled, gateway.enabled, per-agent discord.enabled) and matches the RFC precedent set by PRs #901 / #911 / #914.
Two supported egress topologies, chosen via egress.mode:
direct (default) — DNS + HTTPS direct to any external destination. Suits hobbyist / dev-cluster / small-team deployments where the cluster has no dedicated egress proxy.
proxy — DNS + egress restricted to a designated proxy Service; all HTTPS/HTTP is expected to be tunnelled through that proxy. Matches the enterprise pattern (OpenSHELL et al.) called out by @pahud on Discord (discussion / comment). Chart does not ship the proxy — users BYO.
values.yaml
networkPolicy:
# Master switch. false (default) = no NetworkPolicy resource rendered.# Backwards-compatible; existing releases are unaffected until this flips.enabled: false# Ingress rules. Default = deny-all ingress to agent pods (they only# initiate outbound Socket Mode / websocket connections). Gateway pod# gets a separate policy allowing port 8080 when gateway.enabled=true.ingress:
# extraRules: raw NetworkPolicyIngressRule entries appended verbatim.# Use for cluster-specific allow-lists (e.g. Prometheus scrape, mesh sidecars).extraRules: []# Egress rules.egress:
# Egress topology. "direct" (default) allows egress to the open internet# (typically DNS + HTTPS). "proxy" restricts egress to a designated proxy# Service — recommended for enterprise / multi-tenant / compliance-driven# deployments (see OpenSHELL prior art).mode: direct # or "proxy"# ── mode: direct ────────────────────────────────────────────────────────# Allow DNS to kube-dns (UDP+TCP 53). Almost always required.allowDns: true# Allow HTTPS (TCP 443) to any external destination.allowHttps: true# Allow HTTP (TCP 80). Off by default — enable if hooks/STT fetch over HTTP.allowHttp: false# ── mode: proxy ─────────────────────────────────────────────────────────# When mode=proxy, egress is restricted to this Service selector.# The chart does NOT ship the proxy — deploy it separately (OpenSHELL,# Squid, Envoy, mitmproxy, or anything speaking HTTP CONNECT).# allowDns above still applies (kube-dns needs DNS regardless).# allowHttps / allowHttp are IGNORED in proxy mode.proxy:
namespace: ""# e.g. "egress-proxy"podSelector: {} # e.g. matchLabels: { app: openshell }ports: [] # e.g. [{ protocol: TCP, port: 3128 }]# extraRules: raw NetworkPolicyEgressRule entries appended verbatim.# Use to open extra ports or add cluster-specific carve-outs.extraRules: []
Rendered resources (when enabled: true)
Up to two policies emitted:
<release>-agents — targets pods matching the agent Deployment's selector labels. Ingress: [] (deny-all). Egress: shape depends on egress.mode:
direct: DNS (if allowDns) + HTTPS (if allowHttps) + HTTP (if allowHttp) + any extraRules.
proxy: DNS (if allowDns) + single to: [{ namespaceSelector, podSelector, ports }] rule pointing at the configured proxy + any extraRules.
<release>-gateway — only rendered when gateway.enabled=true. Ingress: TCP 8080 from any source (webhook entry point; Ingress controller in front handles auth). Egress: same shape as agent policy — because the gateway also talks to platform APIs (Telegram / Teams / Feishu / etc.), it needs the same egress path.
Selector labels reuse the existing openab.selectorLabels helper so drift with deployment.yaml / gateway.yaml is structurally impossible.
Raw k8s/ manifests
Add k8s/networkpolicy.yaml mirroring the chart's rendered direct-mode default (deny-all ingress, DNS + HTTPS egress). This is the specific file cited by the AppSec finding — a chart-only fix leaves k8s/deployment.yaml still flagged in downstream scans that consume the raw manifests directly. Users who want proxy-mode should use the chart.
egress.allowDns: false, allowHttps: false, mode: direct → egress locked down (only extraRules apply)
helm lint + helm template smoke on the affected release configurations.
Out of Scope
Namespace-level default-deny — cluster-admin concern, not a workload chart concern.
CNI-specific extensions (Cilium CiliumNetworkPolicy, Calico GlobalNetworkPolicy). Stay on vanilla networking.k8s.io/v1 for portability; advanced users can layer their own on top.
Automatic pinning of Slack / Discord / Anthropic egress CIDRs. Those move; hardcoding them in a chart ages badly. direct mode users who want tighter egress can supply egress.extraRules themselves; proxy mode users push the allowlist to the proxy where it belongs.
Chart-managed egress proxy (bundling OpenSHELL / Squid as a subchart). Would expand upstream maintenance surface — users BYO proxy, chart just emits the right NetworkPolicy pointing at it.
Command-execution restriction / tool allowlist (raised by @pahud in the linked Discord thread: "指定只有某些指令可以執行"). That belongs to the ACP / agent tool-allowlist layer, not the NetworkPolicy layer. Worth a separate RFC.
Prior Art
OpenSHELL — egress proxy pattern cited by @pahud on Discord as the enterprise reference for mode: proxy.
Happy to take the PR — will follow the same file layout (values.yaml, templates/networkpolicy.yaml, README.md, tests/networkpolicy_test.yaml) plus the k8s/networkpolicy.yaml addition.
Trigger: AppSec / IaC scan flagged k8s/deployment.yaml for missing NetworkPolicy (Medium severity, AppSec automation confidence 93%). Verified valid — repo-wide grep NetworkPolicy returns zero matches across charts/ and k8s/.
Description
The openab Helm chart (
charts/openab/) and raw manifests (k8s/) currently ship without anyNetworkPolicyresource. Once deployed, agent pods can freely initiate and receive traffic to/from every other pod in the namespace — and, on most CNIs without a default-deny baseline, to/from every other pod in the cluster.This surfaced as a Medium-severity IaC finding in an internal AppSec scan (automation confidence 93%): "a NetworkPolicy is a way to define how pods are allowed to communicate with each other over the network. By default, pods are allowed to communicate with any other pod within the same namespace, which can create security risks." The finding is valid —
grep -r NetworkPolicy charts/ k8s/returns zero matches. No shared upstream terraform / k8s-workload module supplies one either; the chart is fully self-contained.For a workload whose whole job is executing LLM-driven agents (some tool-using, some code-executing), unrestricted pod-to-pod traffic and unrestricted egress are non-trivial concerns:
Use Case
Give operators an opt-in, well-labelled
NetworkPolicythey can flip on with a single value, without having to reverse-engineer the chart's pod selectors, gateway topology, or which ports actually matter.Concrete scenarios:
k8s/deployment.yaml. Today the fix path is: fork the chart, hand-write the policy, keep it in sync forever. Proposal:--set networkPolicy.enabled=truecloses the finding.openab.selectorLabelshelper the Deployment already uses, so ingress/egress selectors can never drift.gateway.enabled.to: podSelector: {...proxy...}policy. Proposal:networkPolicy.egress.mode=proxy+egress.proxy.{namespace,podSelector,ports}renders the correct policy shape, chart stays proxy-agnostic (BYO proxy).Proposed Design
Backwards-compatible, opt-in. Default
networkPolicy.enabled: false— no rendered resource, no behaviour change for existing releases. Mirrors the established openab pattern (slack.enabled,gateway.enabled, per-agentdiscord.enabled) and matches the RFC precedent set by PRs #901 / #911 / #914.Two supported egress topologies, chosen via
egress.mode:direct(default) — DNS + HTTPS direct to any external destination. Suits hobbyist / dev-cluster / small-team deployments where the cluster has no dedicated egress proxy.proxy— DNS + egress restricted to a designated proxy Service; all HTTPS/HTTP is expected to be tunnelled through that proxy. Matches the enterprise pattern (OpenSHELL et al.) called out by @pahud on Discord (discussion / comment). Chart does not ship the proxy — users BYO.values.yamlRendered resources (when
enabled: true)Up to two policies emitted:
<release>-agents— targets pods matching the agent Deployment's selector labels. Ingress:[](deny-all). Egress: shape depends onegress.mode:direct: DNS (ifallowDns) + HTTPS (ifallowHttps) + HTTP (ifallowHttp) + anyextraRules.proxy: DNS (ifallowDns) + singleto: [{ namespaceSelector, podSelector, ports }]rule pointing at the configured proxy + anyextraRules.<release>-gateway— only rendered whengateway.enabled=true. Ingress: TCP 8080 from any source (webhook entry point; Ingress controller in front handles auth). Egress: same shape as agent policy — because the gateway also talks to platform APIs (Telegram / Teams / Feishu / etc.), it needs the same egress path.Selector labels reuse the existing
openab.selectorLabelshelper so drift withdeployment.yaml/gateway.yamlis structurally impossible.Raw
k8s/manifestsAdd
k8s/networkpolicy.yamlmirroring the chart's rendereddirect-mode default (deny-all ingress, DNS + HTTPS egress). This is the specific file cited by the AppSec finding — a chart-only fix leavesk8s/deployment.yamlstill flagged in downstream scans that consume the raw manifests directly. Users who want proxy-mode should use the chart.Test plan
charts/openab/tests/networkpolicy_test.yaml(helm-unittest), extending the 6-case template from PRs feat(chart): add imagePullSecrets support at per-agent and global level #911 / feat(chart): add serviceAccountName support at per-agent and global level #914 to cover both modes:enabled: false(default) → no NetworkPolicy resource renderedenabled: true,mode: direct, gateway off → single agent policy, DNS + HTTPS egressenabled: true,mode: direct, gateway on → agent + gateway policies renderedenabled: true,mode: direct,allowHttp: true→ HTTP egress rule presentenabled: true,mode: proxy→ egress restricted to proxy podSelector, no HTTPS/HTTP-to-any ruleenabled: true,mode: proxy, gateway on → both policies use proxy egressingress.extraRulespopulated → rules present verbatimegress.allowDns: false,allowHttps: false,mode: direct→ egress locked down (only extraRules apply)helm lint+helm templatesmoke on the affected release configurations.Out of Scope
CiliumNetworkPolicy, CalicoGlobalNetworkPolicy). Stay on vanillanetworking.k8s.io/v1for portability; advanced users can layer their own on top.directmode users who want tighter egress can supplyegress.extraRulesthemselves;proxymode users push the allowlist to the proxy where it belongs.Prior Art
mode: proxy.slack.existingSecret(conditional-render pattern)imagePullSecretsper-agent + global fallback (opt-in flag pattern)serviceAccountNameper-agent + global fallback (opt-in flag pattern)Happy to take the PR — will follow the same file layout (
values.yaml,templates/networkpolicy.yaml,README.md,tests/networkpolicy_test.yaml) plus thek8s/networkpolicy.yamladdition.Trigger: AppSec / IaC scan flagged
k8s/deployment.yamlfor missing NetworkPolicy (Medium severity, AppSec automation confidence 93%). Verified valid — repo-widegrep NetworkPolicyreturns zero matches acrosscharts/andk8s/.