VYPR
Moderate severityNVD Advisory· Published Dec 23, 2022· Updated Apr 10, 2025

Cross-site Scripting (XSS) - Stored in usememos/memos

CVE-2022-4691

Description

Cross-site Scripting (XSS) - Stored in GitHub repository usememos/memos prior to 0.9.0.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Stored XSS in usememos/memos prior to 0.9.0 allows attackers to inject arbitrary JavaScript via crafted resource uploads.

Vulnerability

Overview

CVE-2022-4691 is a stored cross-site scripting (XSS) vulnerability in the open-source note-taking application usememos/memos, affecting versions prior to 0.9.0. The root cause lies in how the application serves uploaded resources: when a resource's MIME type is text/html, the server originally forced the Content-Type header to text/plain as a mitigation. However, this override was removed in a later commit, and the server now serves resources with their original Content-Type [1][3]. This allows an attacker to upload a file with a crafted Content-Type (e.g., text/html) that, when accessed by other users, is rendered as HTML in the browser, enabling script execution.

Exploitation

An attacker must have the ability to upload resources to the memos instance (e.g., as a registered user). By uploading a file with a malicious Content-Type header—such as text/html—and containing embedded JavaScript, the resource is stored on the server. When another user views the resource (e.g., via a direct link or embedded in a memo), the browser interprets the response as HTML and executes the injected script. No additional authentication is required beyond the upload capability, and the attack can be triggered by simply visiting the resource URL [4].

Impact

Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of the victim's session. This can lead to theft of sensitive data (e.g., session cookies, authentication tokens), defacement of the application, or further actions such as performing operations on behalf of the victim. Since the XSS is stored, the payload persists until the resource is removed, affecting all users who view the malicious resource.

Mitigation

The vulnerability is fixed in memos version 0.9.0. The fix, introduced in commit c07b4a57caa89905e54b800f4d8fb720bbf5bf82, removes the problematic Content-Type override and adds a secure middleware that likely enforces proper security headers (e.g., Content-Security-Policy) to prevent script execution [3]. Users are strongly advised to upgrade to the latest version. No workarounds are documented, and the vulnerability is not currently listed in CISA's Known Exploited Vulnerabilities catalog.

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.

PackageAffected versionsPatched versions
github.com/usememos/memosGo
< 0.9.00.9.0

Affected products

2

Patches

1
c07b4a57caa8

feat: add secure middleware (#832)

https://github.com/usememos/memosboojackDec 23, 2022via ghsa
2 files changed · +5 6
  • server/resource.go+1 6 modified
    @@ -7,7 +7,6 @@ import (
     	"net/http"
     	"net/url"
     	"strconv"
    -	"strings"
     	"time"
     
     	"github.com/usememos/memos/api"
    @@ -263,11 +262,7 @@ func (s *Server) registerResourcePublicRoutes(g *echo.Group) {
     			return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to fetch resource ID: %v", resourceID)).SetInternal(err)
     		}
     
    -		if strings.HasPrefix(resource.Type, echo.MIMETextHTML) {
    -			c.Response().Writer.Header().Set("Content-Type", echo.MIMETextPlain)
    -		} else {
    -			c.Response().Writer.Header().Set("Content-Type", resource.Type)
    -		}
    +		c.Response().Writer.Header().Set("Content-Type", resource.Type)
     		c.Response().Writer.WriteHeader(http.StatusOK)
     		c.Response().Writer.Header().Set(echo.HeaderCacheControl, "max-age=31536000, immutable")
     		if _, err := c.Response().Writer.Write(resource.Blob); err != nil {
    
  • server/server.go+4 0 modified
    @@ -44,6 +44,10 @@ func NewServer(profile *profile.Profile) *Server {
     		Timeout:      30 * time.Second,
     	}))
     
    +	e.Use(middleware.SecureWithConfig(middleware.SecureConfig{
    +		ContentSecurityPolicy: "default-src 'self'",
    +	}))
    +
     	embedFrontend(e)
     
     	// In dev mode, set the const secret key to make signin session persistence.
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.