GHSA-2R75-CXRJ-CMPH

Vulnerability from github – Published: 2026-06-05 15:47 – Updated: 2026-06-05 15:47
VLAI
Summary
wasmtime-wasi: WASI path_open(TRUNCATE) bypasses `FilePerms::WRITE` host restriction
Details

Summary

In wasmtime-wasi, when a filesystem preopen is given DirPerms::all() and FilePerms::READ without FilePerms::WRITE, this wasmtime-wasi enforced access control mechanism can be bypassed by using the wasip2 descriptor.open-at or wasip1 path_open interfaces by opening a file with OpenFlags::TRUNCATE oflag only, for example:

dir_descriptor.open_at(
   PathFlags::empty(),
   FILENAME,
   OpenFlags::TRUNCATE,
   DescriptorFlags::READ,
)
wasip1::path_open(
    dir_fd,
    0,
    FILENAME,
    wasip1::OFLAGS_TRUNC,
    wasip1::RIGHTS_FD_READ,
    0,
    0
)

The root cause is that the clause that considered OpenFlags::TRUNCATE did not set open_mode |= OpenMode::WRITE;, used later in that function for the access control check against FilePerms for whether opening that file is permitted. With the bug corrected, these calls to open-at and path_open fail with error-code.not-permitted and ERRNO_PERM respectively.

The bug in crates/wasi/src/filesystem.rs, Dir::open_at, lines 967–969:

if oflags.contains(OpenFlags::TRUNCATE) {
    opts.truncate(true).write(true);
}

and the single line fix is:

if oflags.contains(OpenFlags::TRUNCATE) {
    opts.truncate(true).write(true);
    open_mode |= OpenMode::WRITE;
}

Only wasmtime-wasi embeddings that use a combination of DirPerms::MUTATE with FilePerms::READ are affected by this bug, e.g. those that use in the WasiCtxBuilder:

builder.preopened_dir("readonly", "readonly", DirPerms::READ | DirPerms::MUTATE, FilePerms::READ);

In particular, the Wasmtime project's wasmtime-cli's use of wasmtime-wasi is not affected, because it always sets FilePerms::all() for all preopens.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "wasmtime-wasi"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "37.0.0"
            },
            {
              "fixed": "44.0.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "wasmtime-wasi"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "25.0.0"
            },
            {
              "fixed": "36.0.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "wasmtime-wasi"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "24.0.9"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47261"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-284"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-05T15:47:02Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\n\nIn `wasmtime-wasi`, when a filesystem preopen is given `DirPerms::all()` and `FilePerms::READ` without `FilePerms::WRITE`,  this wasmtime-wasi enforced access control mechanism can be bypassed by using the wasip2 `descriptor.open-at` or wasip1 `path_open` interfaces by opening a file with `OpenFlags::TRUNCATE` oflag only, for example:\n\n```rust\ndir_descriptor.open_at(\n   PathFlags::empty(),\n   FILENAME,\n   OpenFlags::TRUNCATE,\n   DescriptorFlags::READ,\n)\n```\n\n```rust\nwasip1::path_open(\n    dir_fd,\n    0,\n    FILENAME,\n    wasip1::OFLAGS_TRUNC,\n    wasip1::RIGHTS_FD_READ,\n    0,\n    0\n)\n```\n\nThe root cause is that the clause that considered `OpenFlags::TRUNCATE` did not set `open_mode |= OpenMode::WRITE;`, used later in that function for the access control check against `FilePerms` for whether opening that file is permitted. With the bug corrected, these calls to `open-at` and `path_open` fail with `error-code.not-permitted` and `ERRNO_PERM` respectively.\n\nThe bug in `crates/wasi/src/filesystem.rs`, `Dir::open_at`, lines 967\u2013969:\n\n```rust\nif oflags.contains(OpenFlags::TRUNCATE) {\n    opts.truncate(true).write(true);\n}\n```\nand the single line fix is:\n```rust\nif oflags.contains(OpenFlags::TRUNCATE) {\n    opts.truncate(true).write(true);\n    open_mode |= OpenMode::WRITE;\n}\n```\n\nOnly wasmtime-wasi embeddings that use a combination of DirPerms::MUTATE with FilePerms::READ are affected by this bug, e.g. those that use in the `WasiCtxBuilder`:\n```rust\nbuilder.preopened_dir(\"readonly\", \"readonly\", DirPerms::READ | DirPerms::MUTATE, FilePerms::READ);\n```\n\nIn particular, the Wasmtime project\u0027s `wasmtime-cli`\u0027s use of wasmtime-wasi is not affected, because it always sets `FilePerms::all()` for all preopens.",
  "id": "GHSA-2r75-cxrj-cmph",
  "modified": "2026-06-05T15:47:02Z",
  "published": "2026-06-05T15:47:02Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-2r75-cxrj-cmph"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/bytecodealliance/wasmtime"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bytecodealliance/wasmtime/releases/tag/v24.0.9"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bytecodealliance/wasmtime/releases/tag/v36.0.10"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bytecodealliance/wasmtime/releases/tag/v44.0.2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bytecodealliance/wasmtime/releases/tag/v45.0.0"
    },
    {
      "type": "WEB",
      "url": "https://rustsec.org/advisories/RUSTSEC-2026-0149.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "wasmtime-wasi: WASI path_open(TRUNCATE) bypasses `FilePerms::WRITE` host restriction"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…