CVE-2026-44850: Github.com/portainer/portainer Portainer Has A Bind-mount Restriction Vulnerability

HIGH
Advisory Identifier: GHSA-7fw3-x4r2-g7wc
CVSS 8.5
CWE-863
Published
Advisory Summary

CVE-2026-44850 is a HIGH (CVSS 8.5) portainer has a bind-mount restriction vulnerability (CWE-863: Incorrect Authorization) affecting Github.com/portainer/portainer libraries in the Go ecosystem. The issue involves portainer has a bind-mount restriction bypass via hostconfig.mounts. Remediation is available by upgrading affected packages to version 2.33.8, 2.39.2, 2.41.0.

CVE-2026-44850 at a Glance

CVE Identifier CVE-2026-44850
GHSA Identifier GHSA-7fw3-x4r2-g7wc
Severity HIGH
CVSS v3.1 Base Score 8.5
CWE Classification CWE-863: Incorrect Authorization
Affected Product Github.com/portainer/portainer
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 8.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity Low (I:L)
Availability None (A:N)

How to Fix CVE-2026-44850

To remediate this vulnerability, upgrade all affected Github.com/portainer/portainer dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/portainer/portainer fixed: 2.33.8
Upgrade github.com/portainer/portainer to 2.33.8
github.com/portainer/portainer fixed: 2.39.2
Upgrade github.com/portainer/portainer to 2.39.2
github.com/portainer/portainer fixed: 2.41.0
Upgrade github.com/portainer/portainer to 2.41.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/portainer/portainer

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-44850, inspect your project dependencies for Github.com/portainer/portainer:

inspect dependencies for github.com/portainer/portainer

Analyze the terminal output to locate any version of Github.com/portainer/portainer in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.33.8), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-863: Incorrect Authorization, where the product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. In Github.com/portainer/portainer, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary Portainer offers an environment-level **Disable bind mounts for non-administrators** security setting that blocks regular users from binding host paths into containers they create through the Portainer-mediated Docker API. The check that enforces this setting only inspected the legacy `HostConfig.Binds` array on the container-create proxy and never looked at the equivalent `HostConfig.Mounts` array. Any authenticated user with rights to create containers on a Docker environment where the restriction is enabled could submit a `bind`-typed entry under `HostConfig.Mounts` and mount any host path into their container. The two fields are interchangeable on the Docker daemon — both produce real bind mounts at runtime — so a check that inspects only one is functionally equivalent to no check at all. The same primitive is correctly enforced on Swarm service create against `TaskTemplate.ContainerSpec.Mounts`; the gap was specific to the `POST /containers/create` proxy path. Exploitation requires a regular user with container-create rights on an environment that has the restriction enabled. Such a user can mount any host path read-write or read-only into a container they own and use the resulting view of the host filesystem to read or write anything the Docker daemon's user can — typically `root`. Bind-mount restriction is the primary defence against host filesystem exposure on shared environments where regular users are otherwise permitted to deploy containers. ## Severity **High** The vulnerability is exploitable over the network with low attack complexity, no attack requirement, and no user interaction. It requires a low-privilege authenticated session — any regular user with container-create rights on an environment where the bind-mount restriction is enabled. The vulnerable system (the Portainer container-create proxy) suffers a confidentiality and integrity breach by virtue of the bypass itself, but the dominant impact is on the subsequent system: the Docker host's filesystem and any container running alongside the attacker's. This is a restriction bypass rather than a cross-authority escalation — the user already had container-create rights, and the bind-mount restriction is a defence-in-depth control on top of that capability — which is the reason the rating is held at High rather than promoted to Critical despite the host-level reach. ## Affected Versions The vulnerability has existed since the `AllowBindMountsForRegularUsers` security setting was introduced. The `HostConfig.Mounts` field has never been inspected by the container-create proxy on any release line. Fixes are included in the following releases: | Branch | First vulnerable | Fixed in | |--------------|------------------|------------| | 2.33.x (LTS) | 2.33.0 | **2.33.8** | | 2.39.x (LTS) | 2.39.0 | **2.39.2** | | 2.41.x (STS) | all prior | **2.41.0** | Portainer releases prior to 2.33.0 are end-of-life and will not receive a fix. Users on EOL versions should upgrade to a supported LTS branch. ## Workarounds Administrators who cannot immediately upgrade can reduce exposure by: - **Revoke container-create rights from non-administrator accounts on affected environments.** If the bind-mount restriction is being relied on as a hard guarantee, audit which non-administrator accounts have container-create rights on environments where it is set, and downgrade those accounts to roles that lack container-create until the patched release is deployed. Stack and service deployment that depends on container-create will stop working for those users until the patched release is in place. - **Audit recent container creations for `HostConfig.Mounts` of `Type: bind` from non-admin Portainer users.** Inspect Docker daemon logs and `docker inspect` output on affected environments. Any non-admin-created container with a bind-typed `Mounts` entry should be treated as a potential incident. - **Segregate tenants by environment.** Where the per-environment toggle was being used to share an environment between tenants of different trust levels, splitting the workloads onto separate environments is a stronger control than the toggle and remains in place after upgrade. None of these replace the fix. ## Affected Code The enforcement lives in `decorateContainerCreationOperation` in `package/server-ce/api/http/proxy/factory/docker/containers.go`. The `PartialContainer` struct used to deserialise the request body for inspection only contained `HostConfig.Binds`: ``` // package/server-ce/api/http/proxy/factory/docker/containers.go type PartialContainer struct { HostConfig struct { Privileged bool `json:"Privileged"` PidMode string `json:"PidMode"` Devices []any `json:"Devices"` Sysctls map[string]any `json:"Sysctls"` CapAdd []string `json:"CapAdd"` CapDrop []string `json:"CapDrop"` Binds []string `json:"Binds"` } `json:"HostConfig"` } if !securitySettings.AllowBindMountsForRegularUsers && len(partialContainer.HostConfig.Binds) > 0 { for _, bind := range partialContainer.HostConfig.Binds { if strings.HasPrefix(bind, "/") { return forbiddenResponse, ErrBindMountsForbidden } } } ``` The fix adds a `Mounts` field to `PartialContainer` and a parallel check that rejects any entry whose `Type` equals `bind`, mirroring the existing logic on the Swarm service-create proxy. The container-update path is unaffected — the Docker daemon does not accept mount changes via container update — and Swarm service create was already covered. Compose-stack deployment is not in scope of this advisory; the bind-mount restriction is a daemon-mediated container-create control, and Compose deployment runs Docker through a separate path that is not currently subject to the same restriction. The same change applies cleanly on each LTS branch — the surrounding code shape on `release/2.33` and `release/2.39` is identical to develop on the points the patch touches, so the LTS backports are byte-equivalent additions of the `Mounts` field and the parallel check. ## Impact A regular user who has been explicitly restricted from using bind mounts can bypass the restriction and: - **Read or write any path on the Docker host filesystem.** The mount runs as the daemon user (typically `root`), so any path is reachable. Sensitive examples include `/etc/shadow`, host SSH keys under `/root/.ssh` and `/home/*/.ssh`, and TLS material under `/etc/docker`. - **Compromise other containers on the same host.** The host's `/var/lib/docker` (or equivalent) is reachable from within the bound mount, exposing the layers, volumes, and live state of every container the daemon manages. - **Reach the Docker socket.** Mounting `/var/run/docker.sock` into the attacker's container hands them full Docker API access on the host, regardless of any authorisation enforced by Portainer above the proxy. - **Write persistence to the host.** Without `ReadOnly`, the attacker can drop SSH keys into `authorized_keys`, install systemd units, or modify cron, achieving persistence outside of any container the daemon supervises. The bind-mount restriction was the primary defence against this class of host exposure for non-administrator container creators; bypassing it removes the only enforcement point above the daemon for tenants who were granted container-create rights. ## Timeline - 2026-03-04: Reported via GitHub Security Advisory by **offensiveee** (Assaf Alassaf). - 2026-03-04 – 2026-04-17: Six further independent reports of the same primitive received via GitHub Security Advisory (alexwaira, ffulbtech, Proscan-one, jeroengui, AyushParkara, marduc812) and consolidated against this advisory. - 2026-04-18: Fix merged to `develop`. - 2026-06-04: Backports merged to `release/2.33` and `release/2.39`. - 2026-04-29: 2.41.0 released with fix. - 2026-05-07: 2.33.8, 2.39.2, released with fix. ## Credit - **offensiveee** (Assaf Alassaf) — initial report identifying the `HostConfig.Mounts` bypass on container create and the divergence from the Swarm service-create check. - **alexwaira** — independently reported the same `HostConfig.Mounts` bypass on container create. - **ffulbtech** — independently reported the same `HostConfig.Mounts` bypass on container create. - **Proscan-one** — independently reported the same `HostConfig.Mounts` bypass on container create. - **jeroengui** — independently reported the same `HostConfig.Mounts` bypass on container create. - **AyushParkara** — independently reported the same `HostConfig.Mounts` bypass on container create. - **marduc812** — independently reported the same `HostConfig.Mounts` bypass on container create.

CVE-2026-44850 Affected Github.com/portainer/portainer Versions

3 component(s)
Fixed Versions:
2.33.82.39.22.41.0
Product / Package Ecosystem Affected Versions Fixed Version
github.com/portainer/portainer
Go
≥ 2.33.0
< 2.33.8
2.33.8
github.com/portainer/portainer
Go
≥ 2.39.0
< 2.39.2
2.39.2
github.com/portainer/portainer
Go
≥ 2.40.0
< 2.41.0
2.41.0

References

Frequently Asked Questions

What is CVE-2026-44850?
CVE-2026-44850 is a security vulnerability in Github.com/portainer/portainer involving Portainer has a bind-mount restriction bypass via HostConfig.Mounts under CWE-863: Incorrect Authorization.
Which Github.com/portainer/portainer versions are affected?
Affected versions include releases prior to 2.33.8, 2.39.2, 2.41.0 across affected packages: github.com/portainer/portainer.
What version fixes CVE-2026-44850?
Upgrading to 2.33.8, 2.39.2, 2.41.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/portainer/portainer affected?
Yes, github.com/portainer/portainer is affected in releases prior to 2.33.8, 2.39.2, 2.41.0. Upgrade your dependency to 2.33.8, 2.39.2, 2.41.0 or later.
What is the CVSS score of CVE-2026-44850?
CVE-2026-44850 has a CVSS v3.1 base score of 8.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N.
What CWE is associated with CVE-2026-44850?
CVE-2026-44850 is classified under CWE-863: Incorrect Authorization (The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.).
How can I check Go dependencies for CVE-2026-44850?
Run the dependency tree command: 'inspect dependencies for github.com/portainer/portainer'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-7fw3-x4r2-g7wc",
  "modified" : "2026-06-09T10:25:08Z",
  "published" : "2026-05-14T16:23:45Z",
  "aliases" : [ "CVE-2026-44850" ],
  "summary" : "Portainer has a bind-mount restriction bypass via HostConfig.Mounts",
  "details" : "## Summary\n\nPortainer offers an environment-level **Disable bind mounts for non-administrators** security setting that blocks regular users from binding host paths into containers they create through the Portainer-mediated Docker API. The check that enforces this setting only inspected the legacy `HostConfig.Binds` array on the container-create proxy and never looked at the equivalent `HostConfig.Mounts` array. Any authenticated user with rights to create containers on a Docker environment where the restriction is enabled could submit a `bind`-typed entry under `HostConfig.Mounts` and mount any host path into their container.\n\nThe two fields are interchangeable on the Docker daemon — both produce real bind mounts at runtime — so a check that inspects only one is functionally equivalent to no check at all. The same primitive is correctly enforced on Swarm service create against `TaskTemplate.ContainerSpec.Mounts`; the gap was specific to the `POST /containers/create` proxy path.\n\nExploitation requires a regular user with container-create rights on an environment that has the restriction enabled. Such a user can mount any host path read-write or read-only into a container they own and use the resulting view of the host filesystem to read or write anything the Docker daemon's user can — typically `root`. Bind-mount restriction is the primary defence against host filesystem exposure on shared environments where regular users are otherwise permitted to deploy containers.\n\n## Severity\n\n**High**\n\nThe vulnerability is exploitable over the network with low attack complexity, no attack requirement, and no user interaction. It requires a low-privilege authenticated session — any regular user with container-create rights on an environment where the bind-mount restriction is enabled. The vulnerable system (the Portainer container-create proxy) suffers a confidentiality and integrity breach by virtue of the bypass itself, but the dominant impact is on the subsequent system: the Docker host's filesystem and any container running alongside the attacker's. This is a restriction bypass rather than a cross-authority escalation — the user already had container-create rights, and the bind-mount restriction is a defence-in-depth control on top of that capability — which is the reason the rating is held at High rather than promoted to Critical despite the host-level reach.\n\n## Affected Versions\n\nThe vulnerability has existed since the `AllowBindMountsForRegularUsers` security setting was introduced. The `HostConfig.Mounts` field has never been inspected by the container-create proxy on any release line.\n\nFixes are included in the following releases:\n\n| Branch       | First vulnerable | Fixed in   |\n|--------------|------------------|------------|\n| 2.33.x (LTS) | 2.33.0           | **2.33.8** |\n| 2.39.x (LTS) | 2.39.0           | **2.39.2** |\n| 2.41.x (STS) | all prior        | **2.41.0** |\n\nPortainer releases prior to 2.33.0 are end-of-life and will not receive a fix. Users on EOL versions should upgrade to a supported LTS branch.\n\n## Workarounds\n\nAdministrators who cannot immediately upgrade can reduce exposure by:\n\n- **Revoke container-create rights from non-administrator accounts on affected environments.** If the bind-mount restriction is being relied on as a hard guarantee, audit which non-administrator accounts have container-create rights on environments where it is set, and downgrade those accounts to roles that lack container-create until the patched release is deployed. Stack and service deployment that depends on container-create will stop working for those users until the patched release is in place.\n- **Audit recent container creations for `HostConfig.Mounts` of `Type: bind` from non-admin Portainer users.** Inspect Docker daemon logs and `docker inspect` output on affected environments. Any non-admin-created container with a bind-typed `Mounts` entry should be treated as a potential incident.\n- **Segregate tenants by environment.** Where the per-environment toggle was being used to share an environment between tenants of different trust levels, splitting the workloads onto separate environments is a stronger control than the toggle and remains in place after upgrade.\n\nNone of these replace the fix.\n\n## Affected Code\n\nThe enforcement lives in `decorateContainerCreationOperation` in `package/server-ce/api/http/proxy/factory/docker/containers.go`. The `PartialContainer` struct used to deserialise the request body for inspection only contained `HostConfig.Binds`:\n\n```\n// package/server-ce/api/http/proxy/factory/docker/containers.go\ntype PartialContainer struct {\n    HostConfig struct {\n        Privileged bool           `json:\"Privileged\"`\n        PidMode    string         `json:\"PidMode\"`\n        Devices    []any          `json:\"Devices\"`\n        Sysctls    map[string]any `json:\"Sysctls\"`\n        CapAdd     []string       `json:\"CapAdd\"`\n        CapDrop    []string       `json:\"CapDrop\"`\n        Binds      []string       `json:\"Binds\"`\n    } `json:\"HostConfig\"`\n}\n\nif !securitySettings.AllowBindMountsForRegularUsers && len(partialContainer.HostConfig.Binds) > 0 {\n    for _, bind := range partialContainer.HostConfig.Binds {\n        if strings.HasPrefix(bind, \"/\") {\n            return forbiddenResponse, ErrBindMountsForbidden\n        }\n    }\n}\n```\n\nThe fix adds a `Mounts` field to `PartialContainer` and a parallel check that rejects any entry whose `Type` equals `bind`, mirroring the existing logic on the Swarm service-create proxy. The container-update path is unaffected — the Docker daemon does not accept mount changes via container update — and Swarm service create was already covered. Compose-stack deployment is not in scope of this advisory; the bind-mount restriction is a daemon-mediated container-create control, and Compose deployment runs Docker through a separate path that is not currently subject to the same restriction.\n\nThe same change applies cleanly on each LTS branch — the surrounding code shape on `release/2.33` and `release/2.39` is identical to develop on the points the patch touches, so the LTS backports are byte-equivalent additions of the `Mounts` field and the parallel check.\n\n## Impact\n\nA regular user who has been explicitly restricted from using bind mounts can bypass the restriction and:\n\n- **Read or write any path on the Docker host filesystem.** The mount runs as the daemon user (typically `root`), so any path is reachable. Sensitive examples include `/etc/shadow`, host SSH keys under `/root/.ssh` and `/home/*/.ssh`, and TLS material under `/etc/docker`.\n- **Compromise other containers on the same host.** The host's `/var/lib/docker` (or equivalent) is reachable from within the bound mount, exposing the layers, volumes, and live state of every container the daemon manages.\n- **Reach the Docker socket.** Mounting `/var/run/docker.sock` into the attacker's container hands them full Docker API access on the host, regardless of any authorisation enforced by Portainer above the proxy.\n- **Write persistence to the host.** Without `ReadOnly`, the attacker can drop SSH keys into `authorized_keys`, install systemd units, or modify cron, achieving persistence outside of any container the daemon supervises.\n\nThe bind-mount restriction was the primary defence against this class of host exposure for non-administrator container creators; bypassing it removes the only enforcement point above the daemon for tenants who were granted container-create rights.\n\n## Timeline\n\n- 2026-03-04: Reported via GitHub Security Advisory by **offensiveee** (Assaf Alassaf).\n- 2026-03-04 – 2026-04-17: Six further independent reports of the same primitive received via GitHub Security Advisory (alexwaira, ffulbtech, Proscan-one, jeroengui, AyushParkara, marduc812) and consolidated against this advisory.\n- 2026-04-18: Fix merged to `develop`.\n- 2026-06-04: Backports merged to `release/2.33` and `release/2.39`.\n- 2026-04-29: 2.41.0 released with fix.\n- 2026-05-07: 2.33.8, 2.39.2, released with fix.\n\n## Credit\n\n- **offensiveee** (Assaf Alassaf) — initial report identifying the `HostConfig.Mounts` bypass on container create and the divergence from the Swarm service-create check.\n- **alexwaira** — independently reported the same `HostConfig.Mounts` bypass on container create.\n- **ffulbtech** — independently reported the same `HostConfig.Mounts` bypass on container create.\n- **Proscan-one** — independently reported the same `HostConfig.Mounts` bypass on container create.\n- **jeroengui** — independently reported the same `HostConfig.Mounts` bypass on container create.\n- **AyushParkara** — independently reported the same `HostConfig.Mounts` bypass on container create.\n- **marduc812** — independently reported the same `HostConfig.Mounts` bypass on container create.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/portainer/portainer"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.33.0"
      }, {
        "fixed" : "2.33.8"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/portainer/portainer"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.39.0"
      }, {
        "fixed" : "2.39.2"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/portainer/portainer"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.40.0"
      }, {
        "fixed" : "2.41.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/portainer/portainer/security/advisories/GHSA-7fw3-x4r2-g7wc"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-44850"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/portainer/portainer"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/portainer/portainer/releases/tag/2.33.8"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/portainer/portainer/releases/tag/2.39.2"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/portainer/portainer/releases/tag/2.41.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-863" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-14T16:23:45Z",
    "nvd_published_at" : "2026-05-28T22:16:59Z"
  }
}