Skip to content

Fission router exposes /fission-function/<ns>/<name> on its public listener, allowing invocation of any function without an HTTPTrigger

Critical
sanketsudake published GHSA-3g33-6vg6-27m8 May 15, 2026

Package

gomod github.com/fission/fission (Go)

Affected versions

<= 1.22.0

Patched versions

>= 1.23.0

Description

Summary

The Fission router registers an internal-style route — /fission-function/<name> and
/fission-function/<ns>/<name> — for every Function object, independent of whether any
HTTPTrigger exists for that function. The route was mounted on the same listener as
user-defined HTTPTriggers (svc/router, port 8888), so any caller who could reach the router
could invoke any function by guessing its metadata.name (and namespace), bypassing the host /
path / method / method-allow-list restrictions encoded in HTTPTrigger objects.

Affected component

  • pkg/router/httpTriggers.go:280-284internalRoute registration via
    utils.UrlForFunction(fn.Name, fn.Namespace), bound to the function handler.

Impact

An external caller who reaches the public router could:

  1. Invoke functions that the operator intentionally did not publish through an HTTPTrigger
    (e.g. functions used only as Kubewatcher / Timer / MessageQueue trigger targets, internal
    helpers, or sample functions).
  2. Bypass HTTPTrigger-level restrictions: a function published only on POST /api/v2/foo
    could still be invoked as GET /fission-function/<ns>/<name> with arbitrary headers and body.
  3. Enumerate function names by probing the response semantics (404 vs 200 vs 502 from cold
    start).

In multi-tenant deployments this also crosses tenant boundaries when functions in tenant
namespace B are reachable from tenant A's pods (or from anywhere on the internet if the router
is ingress-exposed).

Root cause

/fission-function/... was historically used by internal trigger sources (timer, kubewatcher,
mqtrigger) that share the cluster network with the router, but the route was registered on the
public listener that also serves user HTTPTriggers. The two audiences were never separated.

Fix

Released in v1.23.0:

  • PR #3369 (commit 814d232c): the router now runs two listeners — a public listener
    (port 8888, svc/router) that serves only user-defined HTTPTriggers, /router-healthz, and
    /_version, and an internal listener (port 8889, svc/router-internal, ClusterIP-only) that
    exclusively serves /fission-function/<ns>/<name>. The internal listener is wrapped with the
    pkg/auth/hmac.ServiceVerifier using the ServiceRouterInternal derived key — internal trigger
    sources sign their requests with a per-service HKDF-derived key from a cluster master secret.
    Empty master secret falls back to pass-through (preserves compatibility for clusters not yet
    rotating in a secret).
  • PR #3365 (commit 0aa24788): added per-service NetworkPolicy resources to
    charts/fission-all, ensuring svc/router-internal is only reachable from kubewatcher,
    timer, mqtrigger, and mqt-keda pods inside the release namespace.
  • The internal-listener path itself is still /fission-function/<ns>/<name> — only its
    location moved.

Mitigation (until upgrade)

  1. Apply a NetworkPolicy to the Fission namespace that allows ingress to svc/router (port
  1. only from your ingress controller, and blocks /fission-function/... at the ingress layer
    (path-based filter on the ingress).
  1. Avoid exposing the router directly via LoadBalancer/NodePort; front it with an ingress that
    path-filters /fission-function/.
  2. Treat function metadata.name as not a secret — names should not be the access control
    boundary.

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CVE ID

CVE-2026-46614

Weaknesses

Improper Access Control

The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor. Learn more on MITRE.

Missing Authorization

The product does not perform an authorization check when an actor attempts to access a resource or perform an action. Learn more on MITRE.

Credits