VYPR
High severity7.3OSV Advisory· Published Aug 14, 2025· Updated Apr 15, 2026

CVE-2025-55195

CVE-2025-55195

Description

@std/toml is the Deno Standard Library. Prior to version 1.0.9, an attacker can pollute the prototype chain in Node.js runtime and Browser when parsing untrusted TOML data, thus achieving Prototype Pollution (PP) vulnerability. This is because the library is merging an untrusted object with an empty object, which by default the empty object has the prototype chain. This issue has been patched in version 1.0.9.

Affected products

1

Patches

2
6b92bffee728

chore: release 2025.08.13 (#6795)

https://github.com/denoland/stddenobotAug 13, 2025via osv
9 files changed · +48 13
  • collections/deno.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@std/collections",
    -  "version": "1.1.2",
    +  "version": "1.1.3",
       "exports": {
         ".": "./mod.ts",
         "./aggregate-groups": "./aggregate_groups.ts",
    
  • import_map.json+6 6 modified
    @@ -13,7 +13,7 @@
         "@std/cache": "jsr:@std/cache@^0.2.0",
         "@std/cbor": "jsr:@std/cbor@^0.1.8",
         "@std/cli": "jsr:@std/cli@^1.0.21",
    -    "@std/collections": "jsr:@std/collections@^1.1.2",
    +    "@std/collections": "jsr:@std/collections@^1.1.3",
         "@std/crypto": "jsr:@std/crypto@^1.0.5",
         "@std/csv": "jsr:@std/csv@^1.0.6",
         "@std/data-structures": "jsr:@std/data-structures@^1.0.9",
    @@ -34,16 +34,16 @@
         "@std/log": "jsr:@std/log@^0.224.14",
         "@std/media-types": "jsr:@std/media-types@^1.1.0",
         "@std/msgpack": "jsr:@std/msgpack@^1.0.3",
    -    "@std/net": "jsr:@std/net@^1.0.4",
    -    "@std/path": "jsr:@std/path@^1.1.1",
    +    "@std/net": "jsr:@std/net@^1.0.5",
    +    "@std/path": "jsr:@std/path@^1.1.2",
         "@std/regexp": "jsr:@std/regexp@^1.0.1",
         "@std/random": "jsr:@std/random@^0.1.2",
         "@std/semver": "jsr:@std/semver@^1.0.5",
    -    "@std/streams": "jsr:@std/streams@^1.0.10",
    +    "@std/streams": "jsr:@std/streams@^1.0.11",
         "@std/tar": "jsr:@std/tar@^0.1.7",
         "@std/testing": "jsr:@std/testing@^1.0.15",
    -    "@std/text": "jsr:@std/text@^1.0.15",
    -    "@std/toml": "jsr:@std/toml@^1.0.8",
    +    "@std/text": "jsr:@std/text@^1.0.16",
    +    "@std/toml": "jsr:@std/toml@^1.0.9",
         "@std/ulid": "jsr:@std/ulid@^1.0.0",
         "@std/uuid": "jsr:@std/uuid@^1.0.9",
         "@std/webgpu": "jsr:@std/webgpu@^0.224.8",
    
  • net/deno.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@std/net",
    -  "version": "1.0.4",
    +  "version": "1.0.5",
       "exports": {
         ".": "./mod.ts",
         "./get-available-port": "./get_available_port.ts",
    
  • path/deno.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@std/path",
    -  "version": "1.1.1",
    +  "version": "1.1.2",
       "exports": {
         ".": "./mod.ts",
         "./basename": "./basename.ts",
    
  • Releases.md+36 0 modified
    @@ -1,3 +1,39 @@
    +### 2025.08.13
    +
    +#### @std/assert 1.0.14 (patch)
    +
    +- chore(assert,expect): bump assert and expect versions (#6791)
    +
    +#### @std/collections 1.1.3 (patch)
    +
    +- test(collections): fix mapValues mutation test so it actually tests mutation
    +  (#6780)
    +
    +#### @std/expect 1.0.17 (patch)
    +
    +- chore(assert,expect): bump assert and expect versions (#6791)
    +
    +#### @std/net 1.0.5 (patch)
    +
    +- feat(net/unstable): add ip utilities (#6765)
    +
    +#### @std/path 1.1.2 (patch)
    +
    +- fix(path): improve regex in `isGlob` (#6764)
    +
    +#### @std/streams 1.0.11 (patch)
    +
    +- refactor(streams/unstable): toByteStream to make use of autoAllocateChunkSize
    +  (#6781)
    +
    +#### @std/text 1.0.16 (patch)
    +
    +- feat(text/unstable): add `trimBy` functions (#6778)
    +
    +#### @std/toml 1.0.9 (patch)
    +
    +- fix(toml): prevent prototype pollution by table key
    +
     ### 2025.07.29
     
     #### @std/async 1.0.14 (patch)
    
  • streams/deno.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@std/streams",
    -  "version": "1.0.10",
    +  "version": "1.0.11",
       "exports": {
         ".": "./mod.ts",
         "./unstable-abort-stream": "./unstable_abort_stream.ts",
    
  • text/deno.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@std/text",
    -  "version": "1.0.15",
    +  "version": "1.0.16",
       "exports": {
         ".": "./mod.ts",
         "./closest-string": "./closest_string.ts",
    
  • toml/deno.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@std/toml",
    -  "version": "1.0.8",
    +  "version": "1.0.9",
       "exports": {
         ".": "./mod.ts",
         "./parse": "./parse.ts",
    
  • toml/parse_test.ts+0 1 modified
    @@ -857,7 +857,6 @@ Deno.test({
       },
     });
     
    -
     Deno.test({
       name: "parse() doesn't pollute prototype with __proto__",
       async fn() {
    
540662cfd6d7

Merge commit from fork

https://github.com/denoland/stdYoshiya HinosawaAug 13, 2025via osv
2 files changed · +33 9
  • toml/_parser.ts+8 8 modified
    @@ -154,7 +154,7 @@ function failure(): Failure {
      */
     export function unflat(
       keys: string[],
    -  values: unknown = {},
    +  values: unknown = { __proto__: null },
     ): Record<string, unknown> {
       return keys.reduceRight(
         (acc, key) => ({ [key]: acc }),
    @@ -336,7 +336,7 @@ function merge(
       return (scanner: Scanner): ParseResult<Record<string, unknown>> => {
         const result = parser(scanner);
         if (!result.ok) return failure();
    -    let body = {};
    +    let body = { __proto__: null };
         for (const record of result.body) {
           if (typeof record === "object" && record !== null) {
             body = deepMerge(body, record);
    @@ -744,11 +744,11 @@ export function inlineTable(
       scanner.nextUntilChar();
       if (scanner.char(1) === "}") {
         scanner.next(2);
    -    return success({});
    +    return success({ __proto__: null });
       }
       const pairs = surround("{", join(pair, ","), "}")(scanner);
       if (!pairs.ok) return failure();
    -  let table = {};
    +  let table = { __proto__: null } as Record<string, unknown>;
       for (const pair of pairs.body) {
         table = deepMerge(table, pair);
       }
    @@ -796,7 +796,7 @@ export function table(scanner: Scanner): ParseResult<Table> {
       return success({
         type: "Table",
         keys: header.body,
    -    value: b.ok ? b.body.value : {},
    +    value: b.ok ? b.body.value : { __proto__: null },
       });
     }
     
    @@ -813,16 +813,16 @@ export function tableArray(
       return success({
         type: "TableArray",
         keys: header.body,
    -    value: b.ok ? b.body.value : {},
    +    value: b.ok ? b.body.value : { __proto__: null },
       });
     }
     
     export function toml(
       scanner: Scanner,
     ): ParseResult<Record<string, unknown>> {
       const blocks = repeat(or([block, tableArray, table]))(scanner);
    -  if (!blocks.ok) return success({});
    -  const body = blocks.body.reduce(deepAssign, {});
    +  if (!blocks.ok) return success({ __proto__: null });
    +  const body = blocks.body.reduce(deepAssign, { __proto__: null });
       return success(body);
     }
     
    
  • toml/parse_test.ts+25 1 modified
    @@ -1,5 +1,5 @@
     // Copyright 2018-2025 the Deno authors. MIT license.
    -import { assertEquals, assertThrows } from "@std/assert";
    +import { assert, assertEquals, assertThrows } from "@std/assert";
     import { parse } from "./mod.ts";
     
     Deno.test({
    @@ -856,3 +856,27 @@ Deno.test({
         assertThrows(() => parse("value = -inf_"));
       },
     });
    +
    +
    +Deno.test({
    +  name: "parse() doesn't pollute prototype with __proto__",
    +  async fn() {
    +    const testCode = `
    +      import { parse } from "${import.meta.resolve("./parse.ts")}";
    +      import { assertEquals } from "@std/assert";
    +      parse('[__proto__.isAdmin]');
    +      assertEquals({}.isAdmin, undefined, "Prototype pollution detected");
    +      parse('[[__proto__.arrayTable]]\\npolluted = true');
    +      assertEquals({}.arrayTable, undefined, "Prototype pollution detected");
    +      parse('[foo]\\n[foo.__proto__.bar]');
    +      assertEquals({}.bar, undefined, "Prototype pollution detected");
    +    `;
    +    const command = new Deno.Command(Deno.execPath(), {
    +      stdout: "inherit",
    +      stderr: "inherit",
    +      args: ["eval", "--no-lock", "--unstable-unsafe-proto", testCode],
    +    });
    +    const { success } = await command.output();
    +    assert(success);
    +  },
    +});
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.