{"id":"CVE-2026-48758","aliases":["GHSA-jfc7-64v2-mr8c"],"url":"https://o3.security/vulnerability/CVE-2026-48758","summary":"sigstore-js: DSSE payloadType type-binding failure","details":"### Impact\nThe `preAuthEncoding` function in `@sigstore/core` uses Node.js `'ascii'` encoding when converting the PAE (Pre-Authentication Encoding) string to bytes. This allows `payloadType` to be mutated after signing without invalidating the signature, breaking the type-binding guarantee that DSSE is designed to provide.\n\nIn `packages/core/src/dsse.ts`, the PAE function builds a string containing `payloadType` and then encodes it with `Buffer.from(prefix, 'ascii')`.\n\nIn Node.js, `'ascii'` encoding for string-to-Buffer is equivalent to `'latin1'`, which **truncates characters above U+00FF to their low byte**. This means for any ASCII character, there exist Unicode characters (at U+01xx, U+02xx, etc.) that produce the identical encoded byte:\n\n| Original | Codepoint | Mutant | Codepoint | Encoded byte |\n|----------|-----------|--------|-----------|--------------|\n| `t`      | U+0074    | `Ŵ`    | U+0174    | `0x74`       |\n| `e`      | U+0065    | `ť`    | U+0165    | `0x65`       |\n\nAn attacker can substitute every character in `payloadType` with a Unicode variant whose low byte matches, producing **identical PAE bytes** and a passing signature verification.\n\nAdditionally, `payloadType.length` returns the JavaScript string length (UTF-16 code units) rather than the UTF-8 byte length required by the DSSE spec, though this is only a contributing factor for non-ASCII types.\n\n#### Reproduction\n\n```javascript\nconst { preAuthEncoding } = require('@sigstore/core/dist/dsse.js');\nconst payload = Buffer.from('hello world');\n\nconst original = preAuthEncoding('text/plain', payload);\n// U+01xx chars whose low bytes match the original ASCII chars\nconst mutant = preAuthEncoding('\\u0174\\u0165\\u0178\\u0174/\\u0170\\u016c\\u0161\\u0169\\u016e', payload);\n\nconsole.log('PAE bytes equal:', original.equals(mutant)); // true — should be false\n```","published":"2026-07-14T20:36:28.641Z","modified":"2026-10-21T02:58:20.771211921Z","cvss":{"score":5.4,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L"},"epss":{"score":0.00264,"percentile":0.18363,"asOf":"2026-09-12"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"@sigstore/core","fixedVersion":"3.2.1"}],"fix":{"url":"https://github.com/sigstore/sigstore-js/commit/b5aa4f1f8d2db0a9dfa6430fb114d9c2f1c304f7","label":"sigstore/sigstore-js@b5aa4f1"},"references":[{"type":"WEB","url":"https://github.com/sigstore/sigstore-js/releases/tag/%40sigstore%2Fcore%403.2.1"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/48xxx/CVE-2026-48758.json"},{"type":"ADVISORY","url":"https://github.com/sigstore/sigstore-js/security/advisories/GHSA-jfc7-64v2-mr8c"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-48758"},{"type":"FIX","url":"https://github.com/sigstore/sigstore-js/commit/b5aa4f1f8d2db0a9dfa6430fb114d9c2f1c304f7"},{"type":"FIX","url":"https://github.com/sigstore/sigstore-js/pull/1657"},{"type":"PACKAGE","url":"https://github.com/sigstore/sigstore-js"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-21T02:58:20.771211921Z"}}