Miggo Logo

CVE-2025-46653: Formidable relies on hexoid to prevent guessing of filenames for untrusted executable content

3.1

CVSS Score
3.1

Basic Information

EPSS Score
0.01383%
Published
4/26/2025
Updated
4/30/2025
KEV Status
No
Technology
TechnologyJavaScript

Technical Details

CVSS Vector
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
Package NameEcosystemVulnerable VersionsFirst Patched Version
formidablenpm>= 3.1.1-canary.20211030, < 3.5.33.5.3
formidablenpm>= 2.1.0, < 2.1.3

Vulnerability Intelligence
Miggo AIMiggo AI

Miggo AIRoot Cause Analysis

The vulnerability description clearly states that Formidable relied on hexoid for generating filenames and that hexoid is not cryptographically secure. I analyzed two provided commits (022c2c5577dfe14d2947f10909d81b03b6070bf5 and 37a3e89fca1ed68ec674a539f13aafd62221ddaa) which both patch this vulnerability. Both commits modify the src/Formidable.js file.

In this file, the IncomingForm class has a method (assigned as a property in the constructor or as a class method, effectively _getNewName) that was responsible for generating new filenames. The patches show that the call to toHexoId() (which was initialized using hexoid) within _getNewName was replaced by a call to createId() (which uses @paralleldrive/cuid2, a more secure alternative).

This directly points to IncomingForm._getNewName as the function that contained the vulnerable code (the use of hexoid for filename generation). The purpose of this function aligns perfectly with the vulnerability description. The patch directly replaces the insecure call within this function, confirming it as the site of the vulnerability.

Vulnerable functions

Only Mi**o us*rs **n s** t*is s**tion

WAF Protection Rules

WAF Rule

*ormi***l* (*k* no**-*ormi***l*) *.*.* t*rou** *.x ***or* *.*.* r*li*s on **xoi* to pr*v*nt *u*ssin* o* *il*n*m*s *or untrust** *x**ut**l* *ont*nt; *ow*v*r, **xoi* is *o*um*nt** *s not "*rypto*r*p*i**lly s**ur*." (*lso, t**r* is * s**n*rio in w*i** o

Reasoning

T** vuln*r**ility **s*ription *l**rly st*t*s t**t *ormi***l* r*li** on `**xoi*` *or **n*r*tin* *il*n*m*s *n* t**t `**xoi*` is not *rypto*r*p*i**lly s**ur*. I *n*lyz** two provi*** *ommits (**************************************** *n* ****************