Publify - Stored Cross-Site Scripting (XSS) due to Unrestricted File Upload
Description
In publify, versions v8.0 to v9.2.4 are vulnerable to stored XSS as a result of an unrestricted file upload. This issue allows a user with “publisher” role to inject malicious JavaScript via the uploaded html file.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Stored XSS in Publify v8.0 to v9.2.4 via unrestricted upload of HTML files by publisher users.
Vulnerability
Publify versions v8.0 to v9.2.4 are vulnerable to stored cross-site scripting (XSS) due to an unrestricted file upload mechanism [1]. The ResourceUploader class in CarrierWave did not validate file types, allowing a user with the "publisher" role to upload arbitrary HTML files [3]. The issue was present in the file upload endpoint for resources [3].
Exploitation
An attacker with a valid "publisher" account can upload a malicious HTML file containing JavaScript code via the resource upload functionality [1]. No other special network position or user interaction is required beyond the upload step. When other users view the uploaded resource, the injected JavaScript executes in their browser.
Impact
Successful exploitation leads to stored XSS, which can result in disclosure of sensitive information, session hijacking, or arbitrary actions performed in the context of the victim user [1]. The attacker's JavaScript runs in the security context of the Publify application, potentially compromising administrator accounts or leaking data.
Mitigation
The fix was implemented in commit d99c087 by adding a content_type_allowlist that restricts uploads to image/*, audio/*, video/*, and text/plain MIME types [3]. The patched version has not been explicitly assigned a release number; administrators should update to the latest commit or apply the content type validation manually. No workaround other than patching is documented, and this CVE is not listed in the KEV catalog as of the publication date.
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
publify_coreRubyGems | >= 8.0, < 9.2.5 | 9.2.5 |
Affected products
3- osv-coords2 versions
>= 8.0.0, < 9.2.4+ 1 more
- (no CPE)range: >= 8.0.0, < 9.2.4
- (no CPE)range: >= 8.0, < 9.2.5
- publify_core/publify_corev5Range: v8.0
Patches
1d99c0870d3dbOnly allow certain file types to be uploaded as resources
4 files changed · +37 −0
publify_core/app/uploaders/resource_uploader.rb+4 −0 modified@@ -6,6 +6,10 @@ class ResourceUploader < CarrierWave::Uploader::Base include CarrierWave::MiniMagick before :cache, :check_image_content_type! + def content_type_allowlist + [%r{image/}, %r{audio/}, %r{video/}, "text/plain"] + end + def store_dir "files/#{model.class.to_s.underscore}/#{model.id}" end
publify_core/lib/publify_core/testing_support/fixtures/just_some.html+5 −0 added@@ -0,0 +1,5 @@ +<html> + <body> + <p>Hello!</p> + </body> +</html>
publify_core/Manifest.txt+1 −0 modified@@ -417,6 +417,7 @@ lib/publify_core/testing_support/factories.rb lib/publify_core/testing_support/feed_assertions.rb lib/publify_core/testing_support/fixtures/exploit.svg lib/publify_core/testing_support/fixtures/fakepng.png +lib/publify_core/testing_support/fixtures/just_some.html lib/publify_core/testing_support/fixtures/otherfile.txt lib/publify_core/testing_support/fixtures/testfile.png lib/publify_core/testing_support/fixtures/testfile.txt
publify_core/spec/controllers/admin/resources_controller_spec.rb+27 −0 modified@@ -160,6 +160,33 @@ end end + context "when attempting to upload an html file" do + let(:upload) { file_upload("just_some.html", "text/html") } + + it "does not create a new Resource" do + expect { post :upload, params: { upload: upload } }. + not_to change(Resource, :count) + end + + it "warns the user they can't upload this type of file" do + post :upload, params: { upload: upload } + result = assigns(:up) + expect(result.errors[:upload]). + to match_array [ + %r{You are not allowed to upload text/html files}, + "can't be blank", + ] + end + + it "sets the flash to failure" do + post :upload, params: { upload: upload } + aggregate_failures do + expect(flash[:success]).to be_nil + expect(flash[:warning]).not_to be_nil + end + end + end + context "when uploading nothing" do it "does not create a new Resource" do expect { post :upload }.
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-3h7v-wqw7-ff28ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-25975ghsaADVISORY
- github.com/publify/publify/commit/d99c0870d3dbbfde7febdc6cad33199b84770101ghsax_refsource_MISCWEB
- www.whitesourcesoftware.com/vulnerability-database/CVE-2021-25974ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.