I've recently discovered a potential vulnerability in the type system of Haskell, a functional programming language in use in critical applications at Facebook, Standard Chartered, Input Output et cetera. For context, Haskell's type system distinguishes functions which don't have side effects such as add :: Int -> Int -> Int
from functions which do such as putStrLn :: String -> IO ()
in order to reduce the risk of bugs from unexpected side effects. There are escape hatches such as unsafePerformIO :: IO a -> a
, but the user can disallow them using a pragma. In theory this should allow one to use pure functions from third-party modules without fear; the worst thing a pure function should be able to do is run out of memory or diverge, not encrypt your files for example.
The Haskell side of the attack isn't relevant to crypto, but in brief: if one can find two Haskell datatype names with a colliding MD5 hash, one can break the type system in the "safe" subset of the language, coerce between any two types and perform side effects in "pure" code. That could enable malicious package authors to launch supply chain attacks, made more devastating by the type system providing an illusion of safety.
Datatype names are strings starting with an uppercase letter and followed by any number of alphanumeric characters, _ or '. Marc Stevens found a colliding pair of such strings https://x.com/realhashbreaker/status/1770161965006008570, but fortunately Haskell applies a nonstandard string encoding before hashing. The encoding expands each (unicode) code point to 4 bytes in big-endian order; since unicode only goes up to 0x10ffff, that means the first byte is always 0. Furthermore, since only about 100,000 unicode characters are alphanumeric, one is restricted to about 17 bits of entropy per 32 bits of bytestring.
A concrete example:
The string "ab" is encoded to the bytestring 0000006100000062, which hashes to 6fdc87b2b00d3283ee55bc17ca1466b0.
Would it be viable to find a collision of encoded strings in that format? I've looked at Hashclash, but it seems to only support one-byte alphabets.