Miggo Logo

CVE-2025-59717: @digitalocean/do-markdownit has Type Confusion vulnerability

5.4

CVSS Score
3.1

Basic Information

EPSS Score
0.06127%
Published
9/19/2025
Updated
9/19/2025
KEV Status
No
Technology
TechnologyJavaScript

Technical Details

CVSS Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Package NameEcosystemVulnerable VersionsFirst Patched Version
@digitalocean/do-markdownitnpm<= 1.16.1

Vulnerability Intelligence
Miggo AIMiggo AI

Miggo AIRoot Cause Analysis

The vulnerability exists in the @digitalocean/do-markdownit library and is a classic case of Type Confusion. The root cause lies in two plugins, callout and fence_environment, which are intended to filter user-provided classes and environments against an allowlist. The plugins expect the allowedClasses and allowedEnvironments options to be arrays of strings. When these options are misconfigured as a single comma-separated string, the JavaScript includes() method is called on a string object instead of an array object. For strings, includes() performs a substring search, while for arrays, it checks for the presence of an element. This discrepancy allows an attacker to bypass the intended security control. For example, if allowedClasses is the string "admin,info", an attacker can use the class "in" which is a substring of "admin,info", and the check will pass, granting unauthorized access or styling. The analysis of the proof-of-concept and the source code of rules/embeds/callout.js and modifiers/fence_environment.js confirms this behavior. The vulnerable functions are the internal calloutRule and render functions where these checks are performed.

Vulnerable functions

calloutRule
rules/embeds/callout.js
The `calloutRule` function is responsible for parsing callout blocks. It checks if the extracted `className` is present in the `allowedClasses` option. The vulnerability occurs because the code does not validate the type of `allowedClasses`. If it is a string instead of an array, the `String.prototype.includes()` method is used, which performs a substring check. This allows an attacker to bypass the restriction by using a class name that is a substring of the string of allowed classes (e.g., using 'in' when the allowed classes are 'admin,info').
render
modifiers/fence_environment.js
The `render` function in the `fence_environment` modifier is a wrapper around the original fence renderer. It checks if the environment `name` is in the `allowedEnvironments` list. Due to a type confusion vulnerability, if `allowedEnvironments` is a string, the code performs a substring search using `String.prototype.includes()`. This allows an attacker to specify an environment that is a substring of the allowed environments string (e.g., 'pro' when allowed environments are 'production,test'), bypassing the access control.

WAF Protection Rules

WAF Rule

In t** @*i*it*lo***n/*o-m*rk*ownit p**k*** t*rou** *.**.* (in npm), t** **llout *n* **n**_*nvironm*nt plu*ins p*r*orm .in*lu**s su*strin* m*t**in* i* *llow***l*ss*s or *llow***nvironm*nts is * strin* (inst*** o* *n *rr*y).

Reasoning

T** vuln*r**ility *xists in t** `@*i*it*lo***n/*o-m*rk*ownit` li*r*ry *n* is * *l*ssi* **s* o* Typ* *on*usion. T** root **us* li*s in two plu*ins, `**llout` *n* `**n**_*nvironm*nt`, w*i** *r* int*n*** to *ilt*r us*r-provi*** *l*ss*s *n* *nvironm*nts