VYPR
High severity8.5NVD Advisory· Published Jun 10, 2026· Updated Jun 10, 2026

CVE-2026-49824

CVE-2026-49824

Description

Fission Function admission webhook allows cross-namespace Environment references, enabling confused-deputy attacks and credential theft.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Fission Function admission webhook allows cross-namespace Environment references, enabling confused-deputy attacks and credential theft.

Vulnerability

Prior to version 1.24.0, the Fission Function admission webhook in pkg/webhook/function.go failed to validate that spec.environment.namespace matched the function's own namespace. While checks existed for spec.secrets[].namespace and spec.configmaps[].namespace, the absence of a similar check for spec.environment.namespace allowed for cross-namespace references [3]. This vulnerability affects all versions of Fission prior to 1.24.0 [2].

Exploitation

An attacker with functions.fission.io/create permissions in their own namespace can create a Function and set its spec.environment.namespace to a different, victim's namespace. This causes the Fission framework to use the victim's Environment CRD when scheduling the attacker's function pods [3]. The attacker can also exploit a similar vulnerability by setting spec.package.packageref.namespace to the victim's namespace [1].

Impact

Successful exploitation allows an attacker to run their function code within the victim's container image, potentially leading to code and credential theft if the victim's runtime image contains hardcoded secrets. It also enables confused-deputy attacks where the victim's privileged runtime image is leveraged. This breaks the namespace trust boundary intended by the Function specification [3].

Mitigation

This vulnerability was fixed in Fission version 1.24.0, released on May 23, 2026 [2, 3]. The fix includes an admission webhook that rejects Functions with spec.environment.namespace not matching metadata.namespace. Additional controller guards are in place to prevent webhook bypass scenarios [3]. No workarounds are available for affected versions.

AI Insight generated on Jun 10, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Fission/Fissionreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: <1.24.0

Patches

1
80e7ba55228e

Reject cross-namespace Environment + Package references in Function (… (#3389)

https://github.com/fission/fissionSanket SudakeMay 23, 2026via body-scan-shorthand
4 files changed · +160 0
  • pkg/executor/executortype/newdeploy/newdeploymgr.go+13 0 modified
    @@ -270,6 +270,11 @@ func (deploy *NewDeploy) IsValid(ctx context.Context, fsvc *fscache.FuncSvc) boo
     
     // RefreshFuncPods deletes pods related to the function so that new pods are replenished
     func (deploy *NewDeploy) RefreshFuncPods(ctx context.Context, logger logr.Logger, f fv1.Function) error {
    +	// Defence in depth for GHSA-cvw6-gfvv-953q — see fnCreate for context.
    +	if envNs := f.Spec.Environment.Namespace; envNs != "" && envNs != f.Namespace {
    +		return fmt.Errorf("cross-namespace environment reference is not allowed: fn.namespace=%s env.namespace=%s",
    +			f.Namespace, envNs)
    +	}
     
     	env, err := deploy.fissionClient.CoreV1().Environments(f.Spec.Environment.Namespace).Get(ctx, f.Spec.Environment.Name, metav1.GetOptions{})
     	if err != nil {
    @@ -427,6 +432,14 @@ func (deploy *NewDeploy) deleteFunction(ctx context.Context, fn *fv1.Function) e
     }
     
     func (deploy *NewDeploy) fnCreate(ctx context.Context, fn *fv1.Function) (*fscache.FuncSvc, error) {
    +	// Defence in depth for GHSA-cvw6-gfvv-953q — primary defence is the
    +	// admission webhook in pkg/webhook/function.go, but a stale Function
    +	// from a pre-webhook upgrade window (or failurePolicy=ignore) could
    +	// still reach this path.
    +	if envNs := fn.Spec.Environment.Namespace; envNs != "" && envNs != fn.Namespace {
    +		return nil, fmt.Errorf("cross-namespace environment reference is not allowed: fn.namespace=%s env.namespace=%s",
    +			fn.Namespace, envNs)
    +	}
     	cleanupFunc := func(ctx context.Context, ns string, name string) {
     		err := deploy.cleanupNewdeploy(ctx, ns, name)
     		if err != nil {
    
  • pkg/executor/executortype/poolmgr/gpm.go+9 0 modified
    @@ -586,6 +586,15 @@ func (gpm *GenericPoolManager) getFunctionEnv(ctx context.Context, fn *fv1.Funct
     	var env *fv1.Environment
     	otelUtils.SpanTrackEvent(ctx, "getFunctionEnv", otelUtils.GetAttributesForFunction(fn)...)
     
    +	// Defence in depth for GHSA-cvw6-gfvv-953q — the admission webhook
    +	// already rejects this at submit time, but a stale Function object
    +	// from an upgrade-before-webhook-restart window (or a cluster running
    +	// with failurePolicy=ignore) could still reach this path.
    +	if envNs := fn.Spec.Environment.Namespace; envNs != "" && envNs != fn.Namespace {
    +		return nil, fmt.Errorf("cross-namespace environment reference is not allowed: fn.namespace=%s env.namespace=%s",
    +			fn.Namespace, envNs)
    +	}
    +
     	// Cached ?
     	// TODO: the cache should be able to search by <env name, fn namespace> instead of function metadata.
     	result, err := gpm.functionEnv.Get(crd.CacheKeyURFromMeta(&fn.ObjectMeta))
    
  • pkg/webhook/function.go+19 0 modified
    @@ -61,6 +61,25 @@ func (r *Function) Validate(new *v1.Function) error {
     			return v1.AggregateValidationErrors("Function", err)
     		}
     	}
    +	// Cross-namespace EnvironmentRef closes GHSA-cvw6-gfvv-953q. An empty
    +	// namespace remains accepted — the Fission CLI populates it with the
    +	// function's own namespace at creation time (pkg/fission-cli/cmd/function/
    +	// create.go), and downstream controllers tolerate empty via
    +	// DefaultNSResolver. Rejecting only the explicit cross-namespace value is
    +	// sufficient for this advisory; defaulting an empty namespace at admission
    +	// is a separate hardening track tracked outside this fix.
    +	if envRef := new.Spec.Environment; envRef.Namespace != "" && envRef.Namespace != new.Namespace {
    +		err := fmt.Errorf("environment's namespace [%s] and function's namespace [%s] are different; cross-namespace Environment reference is not allowed",
    +			envRef.Namespace, new.Namespace)
    +		return v1.AggregateValidationErrors("Function", err)
    +	}
    +	// Cross-namespace PackageRef closes GHSA-3r8v-2xmj-5c39. Same shape as
    +	// the EnvironmentRef check above, including the empty-is-accepted rule.
    +	if pkgRef := new.Spec.Package.PackageRef; pkgRef.Namespace != "" && pkgRef.Namespace != new.Namespace {
    +		err := fmt.Errorf("package's namespace [%s] and function's namespace [%s] are different; cross-namespace Package reference is not allowed",
    +			pkgRef.Namespace, new.Namespace)
    +		return v1.AggregateValidationErrors("Function", err)
    +	}
     
     	if err := new.Validate(); err != nil {
     		return v1.AggregateValidationErrors("Function", err)
    
  • pkg/webhook/function_test.go+119 0 added
    @@ -0,0 +1,119 @@
    +/*
    +Copyright 2026.
    +
    +Licensed under the Apache License, Version 2.0 (the "License");
    +you may not use this file except in compliance with the License.
    +You may obtain a copy of the License at
    +
    +    http://www.apache.org/licenses/LICENSE-2.0
    +*/
    +
    +package webhook
    +
    +import (
    +	"strings"
    +	"testing"
    +
    +	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    +
    +	v1 "github.com/fission/fission/pkg/apis/core/v1"
    +)
    +
    +// makeValidFunction returns a Function object that satisfies v1.Function.Validate()
    +// so the cross-namespace branches are the only thing under test. The caller may
    +// override the Environment / PackageRef namespaces to exercise the rejects.
    +func makeValidFunction(fnNs, envNs, pkgNs string) *v1.Function {
    +	return &v1.Function{
    +		ObjectMeta: metav1.ObjectMeta{
    +			Name:      "fn-1",
    +			Namespace: fnNs,
    +		},
    +		Spec: v1.FunctionSpec{
    +			Environment: v1.EnvironmentReference{
    +				Name:      "env-1",
    +				Namespace: envNs,
    +			},
    +			Package: v1.FunctionPackageRef{
    +				PackageRef: v1.PackageRef{
    +					Name:      "pkg-1",
    +					Namespace: pkgNs,
    +				},
    +			},
    +			InvokeStrategy: v1.InvokeStrategy{
    +				StrategyType: v1.StrategyTypeExecution,
    +				ExecutionStrategy: v1.ExecutionStrategy{
    +					ExecutorType: v1.ExecutorTypePoolmgr,
    +				},
    +			},
    +		},
    +	}
    +}
    +
    +func TestFunctionWebhook_Validate_CrossNamespaceEnvironment(t *testing.T) {
    +	cases := []struct {
    +		name         string
    +		fnNs         string
    +		envNs        string
    +		wantRejected bool
    +	}{
    +		{name: "empty env.namespace is accepted", fnNs: "default", envNs: "", wantRejected: false},
    +		{name: "same namespace is accepted", fnNs: "default", envNs: "default", wantRejected: false},
    +		{name: "cross namespace is rejected", fnNs: "ns-attacker", envNs: "ns-victim", wantRejected: true},
    +		{name: "cross namespace rejected even when fn in kube-system", fnNs: "kube-system", envNs: "default", wantRejected: true},
    +	}
    +
    +	r := &Function{}
    +	for _, tc := range cases {
    +		t.Run(tc.name, func(t *testing.T) {
    +			err := r.Validate(makeValidFunction(tc.fnNs, tc.envNs, tc.fnNs))
    +			if tc.wantRejected {
    +				if err == nil {
    +					t.Fatalf("expected rejection, got nil")
    +				}
    +				if !strings.Contains(err.Error(), "Environment reference") {
    +					t.Fatalf("error should reference cross-namespace Environment, got: %v", err)
    +				}
    +				if !strings.Contains(err.Error(), tc.envNs) || !strings.Contains(err.Error(), tc.fnNs) {
    +					t.Fatalf("error should mention both namespaces (%q and %q), got: %v", tc.fnNs, tc.envNs, err)
    +				}
    +			} else if err != nil {
    +				t.Fatalf("expected acceptance, got: %v", err)
    +			}
    +		})
    +	}
    +}
    +
    +func TestFunctionWebhook_Validate_CrossNamespacePackage(t *testing.T) {
    +	cases := []struct {
    +		name         string
    +		fnNs         string
    +		pkgNs        string
    +		wantRejected bool
    +	}{
    +		{name: "empty pkg.namespace is accepted", fnNs: "default", pkgNs: "", wantRejected: false},
    +		{name: "same namespace is accepted", fnNs: "default", pkgNs: "default", wantRejected: false},
    +		{name: "cross namespace is rejected", fnNs: "ns-attacker", pkgNs: "ns-victim", wantRejected: true},
    +	}
    +
    +	r := &Function{}
    +	for _, tc := range cases {
    +		t.Run(tc.name, func(t *testing.T) {
    +			// Keep env.Namespace aligned with fn.Namespace so only the
    +			// package-ref branch can trigger the cross-ns reject.
    +			err := r.Validate(makeValidFunction(tc.fnNs, tc.fnNs, tc.pkgNs))
    +			if tc.wantRejected {
    +				if err == nil {
    +					t.Fatalf("expected rejection, got nil")
    +				}
    +				if !strings.Contains(err.Error(), "Package reference") {
    +					t.Fatalf("error should reference cross-namespace Package, got: %v", err)
    +				}
    +				if !strings.Contains(err.Error(), tc.pkgNs) || !strings.Contains(err.Error(), tc.fnNs) {
    +					t.Fatalf("error should mention both namespaces (%q and %q), got: %v", tc.fnNs, tc.pkgNs, err)
    +				}
    +			} else if err != nil {
    +				t.Fatalf("expected acceptance, got: %v", err)
    +			}
    +		})
    +	}
    +}
    

Vulnerability mechanics

Root cause

"The Fission Function admission webhook failed to validate the namespace for Environment references."

Attack vector

An attacker with permission to create Functions in their own namespace could set `spec.environment.namespace` to a different tenant's namespace. This would cause the attacker's function to execute within the victim's environment, potentially leading to code and credential theft or confused-deputy attacks. The webhook previously only validated `spec.secrets[].namespace` and `spec.configmaps[].namespace` against the function's own namespace, leaving `spec.environment.namespace` unchecked [ref_id=2].

Affected code

The vulnerability exists in the Fission Function admission webhook, specifically in `pkg/webhook/function.go::Validate`. The fix is implemented in pull request #3389 [ref_id=1].

What the fix does

The patch modifies the Function admission webhook to reject Function creations or updates where `spec.environment.namespace` does not match the function's own namespace [patch_id=5504377]. This prevents attackers from specifying a cross-namespace Environment reference. Additional checks are also present in controller logic for defense-in-depth, covering scenarios like webhook bypasses [ref_id=2].

Preconditions

  • authAttacker must have permission to create Functions in their own namespace (`functions.fission.io/create`).

Generated on Jun 10, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

1