GHSA-JFC7-64V2-MR8C

Vulnerability from github – Published: 2026-06-26 19:11 – Updated: 2026-06-26 19:11
VLAI
Summary
@sigstore/core has DSSE payloadType type-binding failure
Details

Impact

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

In packages/core/src/dsse.ts, the PAE function builds a string containing payloadType and then encodes it with Buffer.from(prefix, 'ascii').

In 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:

Original Codepoint Mutant Codepoint Encoded byte
t U+0074 Ŵ U+0174 0x74
e U+0065 ť U+0165 0x65

An attacker can substitute every character in payloadType with a Unicode variant whose low byte matches, producing identical PAE bytes and a passing signature verification.

Additionally, 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.

Reproduction

const { preAuthEncoding } = require('@sigstore/core/dist/dsse.js');
const payload = Buffer.from('hello world');

const original = preAuthEncoding('text/plain', payload);
// U+01xx chars whose low bytes match the original ASCII chars
const mutant = preAuthEncoding('\u0174\u0165\u0178\u0174/\u0170\u016c\u0161\u0169\u016e', payload);

console.log('PAE bytes equal:', original.equals(mutant)); // true — should be false
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.2.0"
      },
      "package": {
        "ecosystem": "npm",
        "name": "@sigstore/core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.2.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-48758"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-26T19:11:19Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Impact\nThe `preAuthEncoding` function in `@sigstore/core` uses Node.js `\u0027ascii\u0027` 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, \u0027ascii\u0027)`.\n\nIn Node.js, `\u0027ascii\u0027` encoding for string-to-Buffer is equivalent to `\u0027latin1\u0027`, 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    | `\u0174`    | U+0174    | `0x74`       |\n| `e`      | U+0065    | `\u0165`    | 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(\u0027@sigstore/core/dist/dsse.js\u0027);\nconst payload = Buffer.from(\u0027hello world\u0027);\n\nconst original = preAuthEncoding(\u0027text/plain\u0027, payload);\n// U+01xx chars whose low bytes match the original ASCII chars\nconst mutant = preAuthEncoding(\u0027\\u0174\\u0165\\u0178\\u0174/\\u0170\\u016c\\u0161\\u0169\\u016e\u0027, payload);\n\nconsole.log(\u0027PAE bytes equal:\u0027, original.equals(mutant)); // true \u2014 should be false\n```",
  "id": "GHSA-jfc7-64v2-mr8c",
  "modified": "2026-06-26T19:11:20Z",
  "published": "2026-06-26T19:11:19Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/sigstore/sigstore-js/security/advisories/GHSA-jfc7-64v2-mr8c"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/sigstore/sigstore-js"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "@sigstore/core has DSSE payloadType type-binding failure"
}



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…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…