Monitor vulnerabilities like this one. Sign up free to get alerted when software you use is affected.
8.3

Deno's AES GCM encryption fails to verify authentication tags

JLSEC-2026-108
Summary

Deno's AES encryption doesn't check if encrypted data has been tampered with, which can lead to data being compromised. This affects Deno's AES-256-GCM and AES-128-GCM encryption. To protect your data, update to a version that fixes this issue.

What to do
  • Update deno_jll to version 2.2.6+0.
Affected software
VendorProductAffected versionsFix available
– deno_jll > 2.0.0+0 , <= 2.2.6+0 2.2.6+0
Original title
Deno's AES GCM authentication tags are not verified
Original description
### Summary

This 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.

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<Buffer>((res, rej) =>
scrypt(key, salt, 32, (err, k) => {
if (err) rej(err);
else res(k);
})
);

async function encrypt(text: string, key: string): Promise<Encrypted> {
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.
osv CVSS4.0 8.3
Published: 14 Apr 2026 · Updated: 14 Apr 2026 · First seen: 14 Apr 2026