{"url":"http://public2.vulnerablecode.io/api/packages/1003262?format=json","purl":"pkg:composer/j0k3r/graby@1.19.0","type":"composer","namespace":"j0k3r","name":"graby","version":"1.19.0","qualifiers":{},"subpath":"","is_vulnerable":true,"next_non_vulnerable_version":"2.5.1","latest_non_vulnerable_version":"2.5.1","affected_by_vulnerabilities":[{"url":"http://public2.vulnerablecode.io/api/vulnerabilities/90852?format=json","vulnerability_id":"VCID-zmgd-y1rg-ckcw","summary":"Graby has stored XSS via iframe srcdoc Attribute in htmLawed Sanitization Config\n## Summary\n\nGraby'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.\n\n## Root Cause\n\n**`src/Graby.php` lines 1038-1048:**\n```php\nhtmLawed($html, [\n    'safe' => 1,                    // removes <iframe>\n    'elements' => '*+iframe-meta',  // re-adds <iframe>, overrides safe=1\n    'deny_attribute' => 'style',    // srcdoc is NOT denied\n]);\n```\n\nThe `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.\n\n## Proof of Concept\n\nInput to `cleanupXss()`:\n```html\n<iframe srcdoc=\"&lt;script&gt;alert(document.domain)&lt;/script&gt;\"></iframe>\n```\n\nOutput (unchanged — htmLawed passes it through):\n```html\n<iframe srcdoc=\"&lt;script&gt;alert(document.domain)&lt;/script&gt;\"></iframe>\n```\n\nWhen 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.**\n\nValidated on Wallabag (which uses Graby) via Docker: entry created via API with iframe-only content body triggers Readability failure → falls through to `cleanupXss()` path.\n\n## Impact\n\n- Stored XSS in any application rendering Graby-sanitized content via `|raw`\n- In Wallabag: affects both authenticated views and public share pages (unauthenticated)\n- No CSP headers in default Wallabag config — no secondary mitigation\n\n## Suggested Fix\n\nEither remove `+iframe` from the elements config to keep iframes blocked:\n```php\n'elements' => '*-iframe-meta',\n```\n\nOr explicitly deny the `srcdoc` attribute:\n```php\n'deny_attribute' => 'style srcdoc',\n```\n\n## Credit\n\nDiscovered by @tikket1, 2026-03-25. Redirected from wallabag/wallabag advisory by @j0k3r.","references":[{"reference_url":"https://github.com/j0k3r/graby","reference_id":"","reference_type":"","scores":[{"value":"2.1","scoring_system":"cvssv4","scoring_elements":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:P"},{"value":"LOW","scoring_system":"generic_textual","scoring_elements":""}],"url":"https://github.com/j0k3r/graby"},{"reference_url":"https://github.com/j0k3r/graby/commit/0295d828822f7a59c5751a8199973a4f965a99b0","reference_id":"","reference_type":"","scores":[{"value":"2.1","scoring_system":"cvssv4","scoring_elements":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:P"},{"value":"LOW","scoring_system":"generic_textual","scoring_elements":""}],"url":"https://github.com/j0k3r/graby/commit/0295d828822f7a59c5751a8199973a4f965a99b0"},{"reference_url":"https://github.com/j0k3r/graby/releases/tag/2.5.1","reference_id":"","reference_type":"","scores":[{"value":"2.1","scoring_system":"cvssv4","scoring_elements":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:P"},{"value":"LOW","scoring_system":"generic_textual","scoring_elements":""}],"url":"https://github.com/j0k3r/graby/releases/tag/2.5.1"},{"reference_url":"https://github.com/j0k3r/graby/security/advisories/GHSA-3h6j-9x8m-rg3g","reference_id":"","reference_type":"","scores":[{"value":"LOW","scoring_system":"cvssv3.1_qr","scoring_elements":""},{"value":"2.1","scoring_system":"cvssv4","scoring_elements":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:P"},{"value":"LOW","scoring_system":"generic_textual","scoring_elements":""}],"url":"https://github.com/j0k3r/graby/security/advisories/GHSA-3h6j-9x8m-rg3g"},{"reference_url":"https://github.com/advisories/GHSA-3h6j-9x8m-rg3g","reference_id":"GHSA-3h6j-9x8m-rg3g","reference_type":"","scores":[{"value":"LOW","scoring_system":"cvssv3.1_qr","scoring_elements":""}],"url":"https://github.com/advisories/GHSA-3h6j-9x8m-rg3g"}],"fixed_packages":[{"url":"http://public2.vulnerablecode.io/api/packages/112728?format=json","purl":"pkg:composer/j0k3r/graby@2.5.1","is_vulnerable":false,"affected_by_vulnerabilities":[],"resource_url":"http://public2.vulnerablecode.io/packages/pkg:composer/j0k3r/graby@2.5.1"}],"aliases":["GHSA-3h6j-9x8m-rg3g"],"risk_score":1.4,"exploitability":"0.5","weighted_severity":"2.7","resource_url":"http://public2.vulnerablecode.io/vulnerabilities/VCID-zmgd-y1rg-ckcw"}],"fixing_vulnerabilities":[],"risk_score":"1.4","resource_url":"http://public2.vulnerablecode.io/packages/pkg:composer/j0k3r/graby@1.19.0"}