Summary
Graby has stored XSS via iframe srcdoc Attribute in htmLawed Sanitization Config
Graby's cleanupXss() function configures htmLawed with conflicting settings: safe=1 (which removes <iframe>) combined with 'elements' => '*+iframe-meta' (which re-enables <iframe>). htmLawed does not sanitize the srcdoc attribute, allowing injection of arbitrary JavaScript that executes when the content is rendered via |raw in templates.
Root Cause
src/Graby.php lines 1038-1048:
htmLawed($html, [
'safe' => 1, // removes <iframe>
'elements' => '*+iframe-meta', // re-adds <iframe>, overrides safe=1
'deny_attribute' => 'style', // srcdoc is NOT denied
]);
The safe=1 and +iframe combination is a conflict: safe mode is designed to strip dangerous elements, but the elements override re-enables <iframe> without also blocking the dangerous srcdoc attribute.
Proof of Concept
Input to cleanupXss():
<iframe srcdoc="<script>alert(document.domain)</script>"></iframe>
Output (unchanged, htmLawed passes it through):
<iframe srcdoc="<script>alert(document.domain)</script>"></iframe>
When rendered via {{ content|raw }} in a template, srcdoc executes in an about:srcdoc frame with the same origin as the page. Confirmed via Puppeteer/Chromium headless: alert(document.domain) fires.
Validated on Wallabag (which uses Graby) via Docker: entry created via API with iframe-only content body triggers Readability failure → falls through to cleanupXss() path.
Credit
Discovered by @tikket1, 2026-03-25. Redirected from wallabag/wallabag advisory by @j0k3r.
Impact
- Stored XSS in any application rendering Graby-sanitized content via
|raw - In Wallabag: affects both authenticated views and public share pages (unauthenticated)
- No CSP headers in default Wallabag config, no secondary mitigation
Untrusted input is rendered as active markup in a victim's browser, which can run script in their session. Typical impact: session or credential theft, and actions taken as the user.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Either remove +iframe from the elements config to keep iframes blocked:
'elements' => '*-iframe-meta',
Or explicitly deny the srcdoc attribute:
'deny_attribute' => 'style srcdoc',
Frequently Asked Questions
- What is GHSA-3H6J-9X8M-RG3G? GHSA-3H6J-9X8M-RG3G is a low-severity cross-site scripting (XSS) vulnerability in j0k3r/graby (composer), affecting versions <= 2.5.0. It is fixed in 2.5.1. Untrusted input is rendered as active markup in a victim's browser, which can run script in their session.
- Which versions of j0k3r/graby are affected by GHSA-3H6J-9X8M-RG3G? j0k3r/graby (composer) versions <= 2.5.0 is affected.
- Is there a fix for GHSA-3H6J-9X8M-RG3G? Yes. GHSA-3H6J-9X8M-RG3G is fixed in 2.5.1. Upgrade to this version or later.
- Is GHSA-3H6J-9X8M-RG3G exploitable, and should I be worried? Whether GHSA-3H6J-9X8M-RG3G is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether GHSA-3H6J-9X8M-RG3G is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix GHSA-3H6J-9X8M-RG3G? Upgrade
j0k3r/grabyto 2.5.1 or later.