Repository navigation
feat(C-0021): cover AI/ML inference and MLOps interfaces in sensitiveInterfaces - #753
Conversation
Extend the sensitiveInterfaces posture-control input with AI/ML inference and MLOps workloads that commonly ship without authentication by default: ollama, vllm, kserve, triton-inference-server, ray-dashboard, ray-head, mlflow, jupyterhub, seldon and bentoml. With these names in the allowlist, the existing exposed-sensitive- interfaces-v1 rule (C-0021) flags a LoadBalancer/NodePort Service that fronts any of these workloads, with no rule logic change. Update the C-0021 control description and long_description to document the AI/ML exposure pattern, and add a vllm test fixture (exposed Deployment + LoadBalancer Service) mirroring the existing workloads/workloads2 cases. kubeflow-pipelines is intentionally omitted: the rule uses a substring match, so the existing kubeflow entry already covers it. Signed-off-by: Devam Shah <devamshah91@gmail.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughControl C-0021 (exposed sensitive interfaces) is updated to explicitly cover AI/ML inference and MLOps frameworks. The control's description and long description are expanded, the ChangesAI/ML Sensitive Interface Coverage
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
matthyx
left a comment
There was a problem hiding this comment.
Reviewed the change end-to-end — no blockers. Summary plus two notes below.
Sound and merge-safe
- Purely additive to
settings.postureControlInputs.sensitiveInterfaces;exposed-sensitive-interfaces-v1needs no logic change, as the description states. - The new
test/vllm/fixture mirrors the existingworkloadsLoadBalancer case exactly: Deploymentspec.selector.matchLabelsequals the Servicespec.selector(app: vllm), Service isLoadBalancerwithstatus.loadBalancer.ingress[0].ipset, andexpected.jsonmatches the rule'swlvectoroutput shape (name/namespace/kind/relatedObjects). It should pass alongsidepod/workloads/workloads2, and the Deployment name matches only the singlevllmentry, so exactly one alert is produced. - Touched JSON is well-formed and there is no duplicate
sensitiveInterfaceslist elsewhere in the repo to keep in sync (default-config-inputs.jsonis the single source; releaseDev is generated in CI). - Good calls keeping entries specific (
ray-dashboard/ray-head,triton-inference-server) to avoid broad substring collisions, and skippingkubeflow-pipelinessincekubeflowalready covers it via the substring match.
One gate before merge (not a code issue)
- The
pr-testsworkflow — which runs the Go rego suite,regal lint, andexport.py— has not run on this PR; its status isaction_required. Only DCO / GitGuardian / CodeRabbit have run. Because this is a fork PR, a maintainer needs to approve the workflow run, so the suite the description reports as green locally has not yet been validated in CI. Worth approving/running before merge.
Non-blocking coverage note
- The rule matches on workload name substrings (
contains(wl.metadata.name, wl_name)).ollama,vllm,mlflow,jupyterhub, and KubeRay head pods (*-head→ containsray-head) typically carry these names, so they'll match. However, KServe (<isvc>-predictor-…), Seldon (<sdep>-<predictor>-…), and Triton deployed under KServe/Seldon usually get model-derived workload names that don't containkserve/seldon/triton-inference-server, so those three entries may match fewer real-world deployments than expected. Not a reason to hold the PR — just a candidate for a follow-up (e.g. label/annotation-based matching) if coverage on those stacks matters.
|
Sorry for the long silence on your second note. Picking it back up now. You were right, and it's still true on master. The rule is unchanged ( One correction to something we both assumed in that thread: Going through the obvious siblings against the list on master, these are genuinely missing: TorchServe (the pytorch/serve chart names the Deployment I've got those four entries plus The label-based matching you suggested is the better fix for KServe and Seldon, since those names are model-derived and no name list will catch them. That needs a new config input (something like |
Overview
Extends the
sensitiveInterfacesposture-control input with the AI/ML inference and MLOps interfaces that have become standard in Kubernetes clusters — Ollama, vLLM, KServe, NVIDIA Triton, the Ray dashboard/head, MLflow, JupyterHub, Seldon and BentoML. With these names in the allowlist, the existingexposed-sensitive-interfaces-v1rule (C-0021) immediately flags aLoadBalancer/NodePortService that fronts any of these workloads — no rule logic changes required.Problem / motivation
C-0021 detects sensitive interfaces exposed to the internet via
LoadBalancer/NodePortServices, matching workload names against thesensitiveInterfaceslist. That list predates the current wave of AI/ML serving stacks and only covers classic DevOps tooling (NiFi, Argo, Kubeflow, Weave Scope, the Kubernetes dashboard, Jenkins, Prometheus).Modern AI/ML serving and MLOps components share the exact property that makes this control matter: they commonly ship without authentication by default and bind broadly. When exposed they enable model/prompt exfiltration and, in several cases, remote code execution on cluster nodes:
This is the same class of "exposed sensitive interface" the control already guards (MITRE ATT&CK for Containers, Initial Access — Exposed Sensitive Interfaces) and is reflected in OWASP's ML/LLM security guidance. The gap is a coverage false-negative: real, high-impact exposures go unflagged today.
Change
default-config-inputs.json— appended ten entries tosettings.postureControlInputs.sensitiveInterfaces:ollama,vllm,kserve,triton-inference-server,ray-dashboard,ray-head,mlflow,jupyterhub,seldon,bentoml.controls/C-0021-exposedsensitiveinterfaces.json— updateddescriptionandlong_descriptionto note that the same exposure pattern applies to AI/ML inference and MLOps interfaces, with examples.rules/exposed-sensitive-interfaces-v1/test/vllm/— new test case: an exposed vLLMDeployment+LoadBalancerService, with the expected alert, mirroring the existingworkloads(LoadBalancer) andworkloads2(NodePort) fixtures exactly.kubeflow-pipelinesis intentionally not added: the rule uses a substring match (contains(wl.metadata.name, wl_name)), so the existingkubeflowentry already coverskubeflow-pipelines*workload names. The names chosen above are specific enough to avoid broad substring collisions (e.g.ray-dashboard/ray-headrather thanray,triton-inference-serverrather thantriton).Security rationale
microsoftMitreColumnstag). The added interfaces are direct, current instances of that technique.LoadBalancer/NodePortService — exactly what C-0021 detects.Testing / validation
Run from
testrunner/(go1.26.2,-tags=static):vllm): an exposed vLLM Deployment behind aLoadBalancerService is correctly flagged.LoadBalancer/NodePortService selector-matched to the workload, soClusterIP-only AI workloads (the common, non-exposed case) are not flagged — the entire existing test matrix continues to pass unchanged.’(’) escaping convention is preserved.Checklist before requesting a review
Summary by CodeRabbit
New Features
Documentation