Commit 2eb0433abd9 for nodejs

commit 2eb0433abd9ddc34d7a661903914f6c0eea24566
Author: Filip Skokan <panva.ip@gmail.com>
Date:   Tue Sep 22 23:18:41 2026 +0200

    crypto: check EC coordinate conversion results

    Propagate coordinate conversion failures instead of importing an
    oversized JWK coordinate as zero. Keep equivalent short and zero-padded
    integer encodings accepted by the native decoder.

    Signed-off-by: Filip Skokan <panva.ip@gmail.com>
    Assisted-by: Codex
    PR-URL: https://github.com/nodejs/node/pull/66237
    Reviewed-By: James M Snell <jasnell@gmail.com>
    Reviewed-By: Aviv Keller <me@aviv.sh>

diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc
index 52f841422c7..44b74e13fd2 100644
--- a/deps/ncrypto/ncrypto.cc
+++ b/deps/ncrypto/ncrypto.cc
@@ -5942,8 +5942,10 @@ bool ECKeyPointer::setPublicKeyRaw(const BignumPointer& x,
   if (!buf) return false;
   unsigned char* ptr = static_cast<unsigned char*>(buf.get());
   ptr[0] = POINT_CONVERSION_UNCOMPRESSED;
-  x.encodePaddedInto(ptr + 1, field_len);
-  y.encodePaddedInto(ptr + 1 + field_len, field_len);
+  if (x.encodePaddedInto(ptr + 1, field_len) != field_len ||
+      y.encodePaddedInto(ptr + 1 + field_len, field_len) != field_len) {
+    return false;
+  }

   auto point = ECPointPointer::New(group);
   if (!point) return false;
@@ -6171,8 +6173,10 @@ bool ECKeyPointer::setPublicKeyRaw(const BignumPointer& x,
   if (!buf) return false;
   unsigned char* ptr = static_cast<unsigned char*>(buf.get());
   ptr[0] = POINT_CONVERSION_UNCOMPRESSED;
-  x.encodePaddedInto(ptr + 1, field_len);
-  y.encodePaddedInto(ptr + 1 + field_len, field_len);
+  if (x.encodePaddedInto(ptr + 1, field_len) != field_len ||
+      y.encodePaddedInto(ptr + 1 + field_len, field_len) != field_len) {
+    return false;
+  }

   auto point = ECPointPointer::New(group_.get());
   if (!point || !point.setFromBuffer({ptr, uncompressed_len}, group_.get())) {
diff --git a/test/parallel/test-crypto-ec-jwk-coordinates.js b/test/parallel/test-crypto-ec-jwk-coordinates.js
new file mode 100644
index 00000000000..8ae3d79e6a3
--- /dev/null
+++ b/test/parallel/test-crypto-ec-jwk-coordinates.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+  common.skip('missing crypto');
+
+const assert = require('assert');
+const { createPublicKey, subtle } = require('crypto');
+
+// This is the valid P-256 point (0, sqrt(b)). A failed conversion of an
+// oversized x coordinate must not silently replace it with zero.
+const jwk = {
+  kty: 'EC',
+  crv: 'P-256',
+  x: Buffer.alloc(32).toString('base64url'),
+  y: 'ZkhceA4vg9ckM71dhKBrtlQcKvMdrocXKL-FahdPk_Q',
+};
+
+(async () => {
+  for (const field of ['x', 'y']) {
+    const invalid = { ...jwk, [field]: Buffer.alloc(33, 1).toString('base64url') };
+    assert.throws(() => createPublicKey({ key: invalid, format: 'jwk' }), {
+      code: 'ERR_CRYPTO_INVALID_JWK',
+    });
+    for (const name of ['ECDSA', 'ECDH']) {
+      await assert.rejects(subtle.importKey(
+        'jwk', invalid, { name, namedCurve: 'P-256' }, true,
+        name === 'ECDSA' ? ['verify'] : []), { name: 'DataError' });
+    }
+  }
+
+  // Equivalent integer encodings remain accepted by the existing decoder.
+  for (const encoded of [
+    jwk,
+    { ...jwk, x: Buffer.alloc(1).toString('base64url') },
+    {
+      ...jwk,
+      x: Buffer.alloc(33).toString('base64url'),
+      y: Buffer.concat([Buffer.alloc(1), Buffer.from(jwk.y, 'base64url')]).toString('base64url'),
+    },
+  ]) {
+    const publicKey = createPublicKey({ key: encoded, format: 'jwk' });
+    assert.deepStrictEqual(publicKey.export({ format: 'jwk' }), jwk);
+    for (const name of ['ECDSA', 'ECDH']) {
+      const key = await subtle.importKey(
+        'jwk', encoded, { name, namedCurve: 'P-256' }, true,
+        name === 'ECDSA' ? ['verify'] : []);
+      const exported = await subtle.exportKey('jwk', key);
+      assert.strictEqual(exported.x, jwk.x);
+      assert.strictEqual(exported.y, jwk.y);
+    }
+  }
+})().then(common.mustCall());