VYPR
High severity7.5OSV Advisory· Published Oct 15, 2025· Updated Apr 15, 2026

CVE-2025-62370

CVE-2025-62370

Description

Alloy Core libraries at the root of the Rust Ethereum ecosystem. Prior to 0.8.26 and 1.4.1, an uncaught panic triggered by malformed input to alloy_dyn_abi::TypedData could lead to a denial-of-service (DoS) via eip712_signing_hash(). Software with high availability requirements such as network services may be particularly impacted. If in use, external auto-restarting mechanisms can partially mitigate the availability issues unless repeated attacks are possible. The vulnerability was patched by adding a check to ensure the element is not empty before accessing its first element; an error is returned if it is empty. The fix is included in version v1.4.1 and backported to v0.8.26.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
alloy-dyn-abicrates.io
< 0.8.260.8.26
alloy-dyn-abicrates.io
>= 1.0.0, < 1.4.11.4.1

Affected products

1

Patches

1
7823e9af8c20

Merge commit from fork

https://github.com/alloy-rs/coreDaniPopesOct 14, 2025via ghsa
2 files changed · +83 0
  • crates/dyn-abi/src/eip712/resolver.rs+3 0 modified
    @@ -421,6 +421,9 @@ impl Resolver {
         /// <https://eips.ethereum.org/EIPS/eip-712#definition-of-encodetype>
         pub fn encode_type(&self, name: &str) -> Result<String> {
             let linear = self.linearize(name)?;
    +        if linear.is_empty() {
    +            return Err(Error::missing_type(name));
    +        }
             let first = linear.first().unwrap().eip712_encode_type();
     
             // Sort references by name (eip-712 encodeType spec)
    
  • crates/dyn-abi/src/eip712/typed_data.rs+80 0 modified
    @@ -770,4 +770,84 @@ mod tests {
             let typed_data: TypedData = serde_json::from_value(json).unwrap();
             let _hash = typed_data.eip712_signing_hash().unwrap();
         }
    +
    +    #[test]
    +    fn primary_types() {
    +        let get_typed_data = |primary: &str, set_types: bool| {
    +            let types = if set_types {
    +                json!({
    +                    primary: [
    +                        { "name": "whatever", "type": "string" }
    +                    ]
    +                })
    +            } else {
    +                json!({})
    +            };
    +            let json = json!({
    +                "types": types,
    +                "primaryType": primary,
    +                "domain": {},
    +                "message": {
    +                    "whatever": "hi"
    +                }
    +            });
    +            serde_json::from_value::<TypedData>(json).unwrap()
    +        };
    +
    +        // Valid syntax.
    +        for primary in ["T", "T:U"] {
    +            let typed_data = get_typed_data(primary, false);
    +            let err = typed_data.eip712_signing_hash().unwrap_err();
    +            assert_eq!(err, Error::missing_type(primary));
    +
    +            let typed_data = get_typed_data(primary, true);
    +            let _hash = typed_data.eip712_signing_hash().unwrap();
    +        }
    +
    +        // Invalid syntax, but still parses.
    +        // - `.` in the name is re-parsed as `uint8` for the enum hack;
    +        // - the rest are basic Solidity types;
    +        // Therefore the `try_as_basic_solidity` skips over them, returning `MissingType` because
    +        // the list of linearized types is empty.
    +        for primary in ["T.", "T.U", "bool", "uint256"] {
    +            for set_types in [false, true] {
    +                let typed_data = get_typed_data(primary, set_types);
    +                let err = typed_data.eip712_signing_hash().unwrap_err();
    +                assert_eq!(err, Error::missing_type(primary));
    +            }
    +        }
    +
    +        // Invalid syntax.
    +        for primary in ["T[]", "string[]", "uint256[]", "(bool,string)", "(bool,string)[]"] {
    +            for set_types in [false, true] {
    +                let typed_data = get_typed_data(primary, set_types);
    +                let err = typed_data.eip712_signing_hash().unwrap_err();
    +                assert!(err.to_string().contains("parser error"), "{err}");
    +            }
    +        }
    +    }
    +
    +    #[test]
    +    fn missing_types() {
    +        let json = json!({
    +            "types": {
    +                "User": [
    +                    {
    +                        "name": "name",
    +                        "type": "Unknown"
    +                    },
    +                ]
    +            },
    +            "primaryType": "User",
    +            "domain": {}
    +        });
    +        let typed_data = serde_json::from_value::<TypedData>(json).unwrap();
    +        let expected_error = Error::missing_type("Unknown");
    +
    +        let ty = typed_data.encode_type().unwrap_err();
    +        assert_eq!(ty, expected_error);
    +
    +        let err = typed_data.eip712_signing_hash().unwrap_err();
    +        assert_eq!(err, expected_error);
    +    }
     }
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

7

News mentions

0

No linked articles in our index yet.