ghsa-2x3r-hwv5-p32x
Vulnerability from github
Published
2025-06-04 20:48
Modified
2025-06-04 22:56
Summary
Deno's AES GCM authentication tags are not verified
Details

Summary

This affects AES-256-GCM and AES-128-GCM in Deno, introduced by commit 0d1beed. Specifically, the authentication tag is not being validated. This means tampered ciphertexts or incorrect keys might not be detected, which breaks the guarantees expected from AES-GCM. Older versions of Deno correctly threw errors in such cases, as does Node.js.

Without authentication tag verification, AES-GCM degrades to essentially CTR mode, removing integrity protection. Authenticated data set with set_aad is also affected, as it is incorporated into the GCM hash (ghash) but this too is not validated, rendering AAD checks ineffective.

PoC

```ts import { Buffer } from "node:buffer"; import { createCipheriv, createDecipheriv, randomBytes, scrypt, } from "node:crypto";

type Encrypted = { salt: string; iv: string; enc: string; authTag: string; };

const deriveKey = (key: string, salt: Buffer) => new Promise((res, rej) => scrypt(key, salt, 32, (err, k) => { if (err) rej(err); else res(k); }) );

async function encrypt(text: string, key: string): Promise { const salt = randomBytes(32); const k = await deriveKey(key, salt);

const iv = randomBytes(16); const enc = createCipheriv("aes-256-gcm", k, iv); const ciphertext = enc.update(text, "binary", "binary") + enc.final("binary");

return { salt: salt.toString("binary"), iv: iv.toString("binary"), enc: ciphertext, authTag: enc.getAuthTag().toString("binary"), }; }

async function decrypt(enc: Encrypted, key: string) { const k = await deriveKey(key, Buffer.from(enc.salt, "binary")); const dec = createDecipheriv("aes-256-gcm", k, Buffer.from(enc.iv, "binary"));

const out = dec.update(enc.enc, "binary", "binary"); dec.setAuthTag(Buffer.from(enc.authTag, "binary")); return out + dec.final("binary"); }

const test = await encrypt("abcdefghi", "key"); test.enc = ""; console.log(await decrypt(test, "")); // no error ```

Impact

While discovered through experimentation, authentication failures that should raise errors may be silently ignored.

Show details on source website


{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "deno"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.46.0"
            },
            {
              "fixed": "2.1.7"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "deno_node"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.102.0"
            },
            {
              "fixed": "0.125.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-24015"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-06-04T20:48:56Z",
    "nvd_published_at": "2025-06-03T23:15:20Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nThis affects AES-256-GCM and AES-128-GCM in Deno, introduced by commit [0d1beed](https://github.com/denoland/deno/commit/0d1beed). Specifically, the authentication tag is not being validated. This means tampered ciphertexts or incorrect keys might not be detected, which breaks the guarantees expected from AES-GCM. Older versions of Deno correctly threw errors in such cases, as does Node.js.\n\nWithout authentication tag verification, AES-GCM degrades to essentially CTR mode, removing integrity protection. Authenticated data set with set_aad is also affected, as it is incorporated into the GCM hash (ghash) but this too is not validated, rendering AAD checks ineffective.\n\n### PoC\n\n```ts\nimport { Buffer } from \"node:buffer\";\nimport {\n  createCipheriv,\n  createDecipheriv,\n  randomBytes,\n  scrypt,\n} from \"node:crypto\";\n\ntype Encrypted = {\n  salt: string;\n  iv: string;\n  enc: string;\n  authTag: string;\n};\n\nconst deriveKey = (key: string, salt: Buffer) =\u003e\n  new Promise\u003cBuffer\u003e((res, rej) =\u003e\n    scrypt(key, salt, 32, (err, k) =\u003e {\n      if (err) rej(err);\n      else res(k);\n    })\n  );\n\nasync function encrypt(text: string, key: string): Promise\u003cEncrypted\u003e {\n  const salt = randomBytes(32);\n  const k = await deriveKey(key, salt);\n\n  const iv = randomBytes(16);\n  const enc = createCipheriv(\"aes-256-gcm\", k, iv);\n  const ciphertext = enc.update(text, \"binary\", \"binary\") + enc.final(\"binary\");\n\n  return {\n    salt: salt.toString(\"binary\"),\n    iv: iv.toString(\"binary\"),\n    enc: ciphertext,\n    authTag: enc.getAuthTag().toString(\"binary\"),\n  };\n}\n\nasync function decrypt(enc: Encrypted, key: string) {\n  const k = await deriveKey(key, Buffer.from(enc.salt, \"binary\"));\n  const dec = createDecipheriv(\"aes-256-gcm\", k, Buffer.from(enc.iv, \"binary\"));\n\n  const out = dec.update(enc.enc, \"binary\", \"binary\");\n  dec.setAuthTag(Buffer.from(enc.authTag, \"binary\"));\n  return out + dec.final(\"binary\");\n}\n\nconst test = await encrypt(\"abcdefghi\", \"key\");\ntest.enc = \"\";\nconsole.log(await decrypt(test, \"\")); // no error\n```\n\n### Impact\n\nWhile discovered through experimentation, authentication failures that should raise errors may be silently ignored.",
  "id": "GHSA-2x3r-hwv5-p32x",
  "modified": "2025-06-04T22:56:13Z",
  "published": "2025-06-04T20:48:56Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/denoland/deno/security/advisories/GHSA-2x3r-hwv5-p32x"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-24015"
    },
    {
      "type": "WEB",
      "url": "https://github.com/denoland/deno/commit/0d1beed"
    },
    {
      "type": "WEB",
      "url": "https://github.com/denoland/deno/commit/0d1beed2e3633d71d5e288e0382b85be361ec13d"
    },
    {
      "type": "WEB",
      "url": "https://github.com/denoland/deno/commit/4f27d7cdc02e3edfb9d36275341fb8185d6e99ed"
    },
    {
      "type": "WEB",
      "url": "https://github.com/denoland/deno/commit/a4003a5292bd0affefad3ecb24a8732886900f67"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/denoland/deno"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Deno\u0027s AES GCM authentication tags are not verified"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…