Tekton is a Kubernetes-native CI/CD framework where pipelines run as Pods with user-defined container images and service accounts. Because pipeline tasks execute arbitrary code in containers with configurable service accounts, Tekton is a natural privilege escalation vector: a TaskRun can use a high-privilege service account, parameter substitution can inject shell commands into scripts, workspaces backed by shared PVCs can leak data across pipeline runs, and the Tekton Dashboard may expose pipeline controls without authentication. This guide covers systematic Tekton security assessment.
# TaskRuns and PipelineRuns specify a serviceAccountName
# If a user can create TaskRuns with a privileged SA, they escalate to that SA's permissions
# Check who can create TaskRuns and PipelineRuns
kubectl auth can-i create taskruns \
--as=system:serviceaccount:developer:developer-sa \
-n ci-cd
# List service accounts available in the CI/CD namespace and their permissions
kubectl get serviceaccounts -n ci-cd -o json | python3 -c "
import json,sys
sas = json.load(sys.stdin)['items']
for sa in sas:
print(f\"SA: {sa['metadata']['name']}\")
"
# Test: create a TaskRun using a privileged SA
kubectl apply -f - <
# Tekton Tasks use $(params.NAME) substitution in script fields
# If user-controlled parameters are interpolated unsafely into shell scripts,
# shell injection is possible
# Find Tasks with parameters interpolated in scripts
kubectl get tasks --all-namespaces -o json | python3 -c "
import json,sys,re
tasks = json.load(sys.stdin)['items']
for t in tasks:
meta = t['metadata']
for step in t.get('spec',{}).get('steps',[]):
script = step.get('script','')
# Find parameter substitutions in scripts
params_in_script = re.findall(r'\\\$(params\.[^)]+)', script)
if params_in_script:
print(f\"Task: {meta['namespace']}/{meta['name']} step: {step.get('name','?')}\")
for p in params_in_script:
print(f\" Substitution: {p}\")
# If substitution is in a shell command without quoting, injection possible
if re.search(r'(sh|bash|/bin/sh)\s+-c.*\\\$(params', script):
print(f\" [!] Unquoted parameter in shell -c: INJECTION RISK\")
"
# Test: inject shell commands via a parameter
kubectl apply -f - <
# Tekton tasks can mount Kubernetes secrets as env vars or volumes
# Test what secrets are accessible to pipeline tasks and whether they leak
# Check Tasks and Pipelines for secret references
kubectl get tasks --all-namespaces -o json | python3 -c "
import json,sys
tasks = json.load(sys.stdin)['items']
for t in tasks:
meta = t['metadata']
for step in t.get('spec',{}).get('steps',[]):
for env in step.get('env',[]):
if 'valueFrom' in env and 'secretKeyRef' in env.get('valueFrom',{}):
secret = env['valueFrom']['secretKeyRef']
print(f\"Task: {meta['namespace']}/{meta['name']}\")
print(f\" Env {env['name']} from secret: {secret['name']} key: {secret['key']}\")
"
# Check TaskRun logs for secret leakage (secrets printed to stdout)
kubectl get taskruns --all-namespaces -o json | python3 -c "
import json,sys
runs = json.load(sys.stdin)['items']
for r in runs:
meta = r['metadata']
# Check for env var injection that could print secrets
params = r.get('spec',{}).get('params',[])
for p in params:
if any(k in str(p.get('value','')).lower() for k in ['password','secret','key','token']):
print(f\"[!] TaskRun {meta['namespace']}/{meta['name']} param {p['name']} may contain secret: {str(p.get('value',''))[:20]}\")
"
# Check if Tekton stores secrets in PipelineRun results (visible in CR status)
kubectl get pipelineruns --all-namespaces -o json | python3 -c "
import json,sys
runs = json.load(sys.stdin)['items']
for r in runs:
results = r.get('status',{}).get('pipelineResults',[])
for result in results:
val = result.get('value','')
if len(val) > 20: # Suspicious length results
print(f\"{r['metadata']['name']}: result {result['name']} = {val[:50]}\")
"
# Tekton Dashboard is often deployed without authentication (read-only by default)
# But some deployments allow write operations (creating TaskRuns, PipelineRuns)
# Check Dashboard deployment configuration
kubectl get deployment tekton-dashboard -n tekton-pipelines -o json | python3 -c "
import json,sys
dep = json.load(sys.stdin)
containers = dep['spec']['template']['spec']['containers']
for c in containers:
args = c.get('args',[])
read_only = '--read-only' in args
auth = '--auth-level' in ' '.join(args)
print(f\"Dashboard args: {args}\")
print(f\"Read-only: {read_only}\")
print(f\"Auth configured: {auth}\")
if not read_only and not auth:
print('[!] Dashboard allows unauthenticated writes (create/run pipelines)')
"
# Test: access Dashboard without credentials
curl -s http://tekton-dashboard.tekton-pipelines:9097/api/v1/namespaces/ci-cd/taskruns \
| python3 -m json.tool | head -20
# Test: create a TaskRun via unauthenticated Dashboard API
curl -X POST http://tekton-dashboard.tekton-pipelines:9097/api/v1/namespaces/ci-cd/taskruns \
-H "Content-Type: application/json" \
-d '{
"apiVersion": "tekton.dev/v1",
"kind": "TaskRun",
"metadata": {"name": "unauth-test"},
"spec": {
"taskSpec": {
"steps": [{"name": "test", "image": "alpine", "script": "id"}]
}
}
}' 2>/dev/null | head -5
$(params.X) in shell scripts: "$(params.image)" not $(params.image)--read-only=true and behind authentication proxyrunAsNonRoot: true| Security Test | Method | Risk |
|---|---|---|
| Developer can create TaskRun with privileged SA | kubectl auth can-i create taskruns — test SA field | Critical |
| Dashboard allows unauthenticated TaskRun creation | POST /api/v1/namespaces/X/taskruns without auth | Critical |
| Unquoted parameter substitution in shell scripts | Audit Task scripts for $(params.X) in sh -c | High |
| Task steps run as root | Check step securityContext.runAsNonRoot | High |
| Workspace PVC reused across pipeline runs | Check Workspace PVC retention policies | Medium |
| Secrets logged in TaskRun results | kubectl get pipelineruns — inspect status.results | Medium |
Ironimo tests Tekton deployments for TaskRun service account privilege escalation, parameter injection vulnerabilities in task scripts, workspace PVC cross-run data leakage, Dashboard unauthenticated access, secret exposure in pipeline logs, and supply chain attestation gaps via Tekton Chains.
Start free scan