In #1149 I proposed allowing ADD_ATTR to accept a function, and this was implemented in #1150. I've since discovered that attributes allowed via the function form do not go through URI validation, whereas attributes allowed via the array form (or via ALLOWED_ATTR) do.
Consider this input:
<a href="javascript:alert(1)">click</a>
Configuration A (array form):
DOMPurify.sanitize(input, {
ADD_ATTR: ['href']
});
Result: <a>click</a> — the dangerous URI is stripped. This is correct.
Configuration B (function form):
DOMPurify.sanitize(input, {
ADD_ATTR: (attr, tag) => attr === 'href' && tag === 'a'
});
Result: <a href="javascript:alert(1)">click</a> — the dangerous URI passes through. This is incorrect.
The two configurations should behave identically with respect to URI validation. The function form was intended to enable per-element attribute allowlisting, not to bypass value sanitization.
The root cause is in _isValidAttribute: when the ADD_ATTR callback returns true, execution falls through to return true without checking the value against IS_ALLOWED_URI. Attributes allowed via the array form do go through this check.
I'm happy to submit a PR to fix this.
In #1149 I proposed allowing
ADD_ATTRto accept a function, and this was implemented in #1150. I've since discovered that attributes allowed via the function form do not go through URI validation, whereas attributes allowed via the array form (or viaALLOWED_ATTR) do.Consider this input:
Configuration A (array form):
Result:
<a>click</a>— the dangerous URI is stripped. This is correct.Configuration B (function form):
Result:
<a href="javascript:alert(1)">click</a>— the dangerous URI passes through. This is incorrect.The two configurations should behave identically with respect to URI validation. The function form was intended to enable per-element attribute allowlisting, not to bypass value sanitization.
The root cause is in
_isValidAttribute: when theADD_ATTRcallback returns true, execution falls through toreturn truewithout checking the value againstIS_ALLOWED_URI. Attributes allowed via the array form do go through this check.I'm happy to submit a PR to fix this.