<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp" -->

---
title: GHSA-r827-6rm4-59pg (alchemy_cms): Stored XSS via...
description: A stored XSS vulnerability (CVSS 8.7 High) has been disclosed in AlchemyCMS. The SVG sanitizer (SanitizeSvgJob) only runs on after_create_commit callbacks,...
canonical: https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: GHSA-r827-6rm4-59pg (alchemy_cms): Stored XSS via unsanitized SVG attachment replacement | daily.dev
og:description: A stored XSS vulnerability (CVSS 8.7 High) has been disclosed in AlchemyCMS. The SVG sanitizer (SanitizeSvgJob) only runs on after_create_commit callbacks,...
og:url: https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp
og:image: https://api.daily.dev/og/posts/pfpoCZYdp.png
og:image:alt: GHSA-r827-6rm4-59pg (alchemy_cms): Stored XSS via unsanitized SVG attachment replacement
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# GHSA-r827-6rm4-59pg (alchemy_cms): Stored XSS via unsanitized SVG attachment replacement

**[RUBYLAND](https://daily.dev/sources/rubyla)** · 1 min read · 1 upvotes · 0 comments

## Summary

A stored XSS vulnerability (CVSS 8.7 High) has been disclosed in AlchemyCMS. The SVG sanitizer (SanitizeSvgJob) only runs on after_create_commit callbacks, meaning it fires when a new attachment is created but not when an existing attachment's file is replaced via the admin update action. An authenticated user with the low-privilege editor role can PATCH an existing attachment with a malicious SVG containing script or onload payloads. Since AlchemyCMS configures SVG as inline-servable via Active Storage, the public /attachment/:id/show route streams the raw malicious SVG, executing attacker-controlled JavaScript in any visitor's browser. The fix is available in version 8.3.6 and above.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://rubysec.com/advisories/GHSA-r827-6rm4-59pg>

## Questions this post answers

### What is CVE GHSA-r827-6rm4-59pg in AlchemyCMS and how does it lead to stored XSS?

AlchemyCMS's SVG sanitizer only runs when a new attachment is created, not when an existing attachment's file is replaced via the admin update action. A low-privilege editor-role user can PATCH an attachment with a malicious SVG containing script or onload payloads, which then gets served inline through the public attachment show route, executing attacker JavaScript for any visitor.

_Teams tracking AlchemyCMS security fixes can follow advisories like this on daily.dev._

### Which AlchemyCMS version fixes the SVG attachment stored XSS vulnerability?

Version 8.3.6 and later patch the vulnerability. Upgrading past this version restores sanitizer coverage on the attachment replacement path, closing the gap that let editor-role users upload unsanitized SVGs that were served inline to any visitor.

_Ruby developers keeping dependencies current can track fixes like this via daily.dev._

### Why does replacing an attachment file in AlchemyCMS bypass SVG sanitization?

The sanitizer, SanitizeSvgJob, is registered only as an after_create_commit callback on Alchemy::Attachment and Alchemy::Picture, so it fires solely when a new record is created. Replacing an existing attachment's file through the admin update action does not trigger this callback, leaving the new file unsanitized despite AlchemyCMS treating SVG as an inline-servable content type.

_Developers auditing file-upload security paths can find advisories like this through daily.dev._

## Similar posts on daily.dev

- [GHSA-cj75-f6xr-r4g7 \(rails-html-sanitizer\): Possible XSS vulnerability with certain configurations of rails-html-sanitizer](https://daily.dev/posts/ghsa-cj75-f6xr-r4g7-rails-html-sanitizer-possible-xss-vulnerability-with-certain-configurations-o-9lq3cmn5j) · RUBYLAND · 1 upvotes · 0 comments
- [CVE-2026-55877: XSS in symfony/ux-icons via unsanitized SVG content in local files and Iconify on-demand responses \(Symfony Blog\)](https://daily.dev/posts/cve-2026-55877-xss-in-symfony-ux-icons-via-unsanitized-svg-content-in-local-files-and-iconify-on-de-hrpqqcxja) · Symfony · 0 upvotes · 0 comments
- [The woes of sanitizing SVGs](https://daily.dev/posts/the-woes-of-sanitizing-svgs-pwfqj7jvs) · Hacker News · 1 upvotes · 0 comments
- [GHSA-m5f6-4589-m89f \(blazer\): Stored XSS vulnerability](https://daily.dev/posts/ghsa-m5f6-4589-m89f-blazer-stored-xss-vulnerability-3ifg1cgjx) · RUBYLAND · 0 upvotes · 0 comments
- [Hackers use pixel-large SVG trick to hide credit card stealer](https://daily.dev/posts/hackers-use-pixel-large-svg-trick-to-hide-credit-card-stealer-jvltp9ks7) · BleepingComputer · 0 upvotes · 0 comments

---

Tags: [#ruby](https://daily.dev/tags/ruby)

[View this post on daily.dev](https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"GHSA-r827-6rm4-59pg (alchemy_cms): Stored XSS via unsanitized SVG attachment replacement","url":"https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp"},"datePublished":"2026-07-31T12:24:26.284Z","dateModified":"2026-09-14T06:53:57.191Z","description":"A stored XSS vulnerability (CVSS 8.7 High) has been disclosed in AlchemyCMS. The SVG sanitizer (SanitizeSvgJob) only runs on after_create_commit callbacks,...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/5fa7bf38a8a9c178c1d458f9f735556c?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/5fa7bf38a8a9c178c1d458f9f735556c?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"RUBYLAND","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"RUBYLAND","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/rubyla","url":"https://daily.dev/sources/rubyla"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"ruby","timeRequired":"PT1M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"RUBYLAND","item":"https://daily.dev/sources/rubyla"},{"@type":"ListItem","position":3,"name":"GHSA-r827-6rm4-59pg (alchemy_cms): Stored XSS via unsanitized SVG attachment replacement"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/ghsa-r827-6rm4-59pg-alchemy-cms-stored-xss-via-unsanitized-svg-attachment-replacement-pfpoczydp#faq","mainEntity":[{"@type":"Question","name":"What is CVE GHSA-r827-6rm4-59pg in AlchemyCMS and how does it lead to stored XSS?","acceptedAnswer":{"@type":"Answer","text":"AlchemyCMS's SVG sanitizer only runs when a new attachment is created, not when an existing attachment's file is replaced via the admin update action. A low-privilege editor-role user can PATCH an attachment with a malicious SVG containing script or onload payloads, which then gets served inline through the public attachment show route, executing attacker JavaScript for any visitor. Teams tracking AlchemyCMS security fixes can follow advisories like this on daily.dev."}},{"@type":"Question","name":"Which AlchemyCMS version fixes the SVG attachment stored XSS vulnerability?","acceptedAnswer":{"@type":"Answer","text":"Version 8.3.6 and later patch the vulnerability. Upgrading past this version restores sanitizer coverage on the attachment replacement path, closing the gap that let editor-role users upload unsanitized SVGs that were served inline to any visitor. Ruby developers keeping dependencies current can track fixes like this via daily.dev."}},{"@type":"Question","name":"Why does replacing an attachment file in AlchemyCMS bypass SVG sanitization?","acceptedAnswer":{"@type":"Answer","text":"The sanitizer, SanitizeSvgJob, is registered only as an after_create_commit callback on Alchemy::Attachment and Alchemy::Picture, so it fires solely when a new record is created. Replacing an existing attachment's file through the admin update action does not trigger this callback, leaving the new file unsanitized despite AlchemyCMS treating SVG as an inline-servable content type. Developers auditing file-upload security paths can find advisories like this through daily.dev."}}]}
```

