Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessReach Shiny app over HTTP
-
DeliverySupply crafted _state_id_ with ../ or absolute path
-
ExploitRestore handler joins path without validation
-
ExecutionServer opens input.json/values.json outside store
-
PersistRead attacker-selected file via input_file copy (server mode)
-
ImpactExfiltrate file existence or contents
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V5 - File Handling Path canonicalization, traversal prevention
MITRE ATT&CK
2 techniques across 2 tactics: Discovery, Collection The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Baseline (default apps, including bookmark_store='disable'): no authentication and no opt-in configuration - the restore handler executed on any request carrying a query string, so a single crafted _state_id_ containing parent-directory ('..') segments or an absolute path triggers the traversal; impact is limited to probing existence and JSON-validity of paths, and only for the file names input.json and values.json. Escalated file-read: requires the application to be configured with bookmark_store='server' AND to call ui.input_file(), in which case the file-input restore handler copies an attacker-named file from an attacker-named directory into the app. Limiting factors: the vulnerability exists only in versions 1.4.0 through 1.6.3; the full file-disclosure impact depends on the non-default server+input_file configuration; and the only available mitigation short of upgrading is stripping the _state_id_ parameter at a reverse proxy or load balancer (no in-app setting disables the vulnerable path on affected versions). |
| Impact | This is a genuine but moderate-priority issue, not a critical emergency. The CVSS 4.0 base score of 6.9 (Medium) with vector AV:N/AC:L/AT:N/PR:N/UI:N and VC:L/VI:N/VA:N correctly captures the baseline: a network-reachable, unauthenticated, low-complexity attack whose worst-case impact in the default configuration is limited confidentiality - a server-side probe that reveals only whether an attacker-chosen path exists and contains valid JSON, constrained to the file names input.json and values.json. No EPSS score, KEV listing, or public POC is present in the supplied intelligence; exploitation status is therefore 'no public exploit identified at time of analysis.' The signals are internally consistent (network vector matches an HTTP query-string parameter; PR:N matches the vendor's statement that restore ran even with bookmark_store='disable' and required no opt-in). The important nuance the single score hides is a conditional escalation: applications configured with bookmark_store='server' AND using ui.input_file() can additionally have an attacker-selected file copied and exposed into the application, which is a materially higher confidentiality impact than VC:L suggests - but that path is config-dependent and not reflected in the base vector. Bottom line: prioritize patching for any py-shiny deployment in the 1.4.0-1.6.3 range, with elevated urgency for server-side-bookmark apps that use file inputs; treat the base score as a floor, not a ceiling. |
| Exploit ScenarioDerived | An unauthenticated attacker appends a crafted _state_id_ query parameter containing ../ sequences or an absolute path to a Shiny for Python app URL, causing the server to attempt to open input.json/values.json outside the shiny_bookmarks store and leaking file existence and JSON-validity by response behavior. Against an app running bookmark_store='server' that uses ui.input_file(), the attacker can further direct the restore handler to copy an attacker-chosen file from an attacker-chosen directory into the application, exposing its contents. No public exploit code is identified, but the technique is straightforward to reproduce from the advisory. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 09, 2026
Unauthenticated path traversal in the bookmark-restore handler of Shiny for Python 1.4.0 through 1.6.3 lets a remote attacker supply a crafted _state_id_ query-string value containing parent-directory ('..') segments or an absolute path, causing the server to join it into the server-side shiny_bookmarks directory and open input.json and values.json from outside the bookmark store. On default applications - including those configured with bookmark_store='disable' - this requires no authentication and no opt-in configuration and yields a limited-confidentiality probe of file existence and JSON validity, but when an application is configured with bookmark_store='server' and uses ui.input_file(), the file-input restore handler can copy and expose an attacker-selected file from an attacker-selected directory. The issue is fixed in 1.6.4, and no public exploit code or active exploitation has been identified at time of analysis.
RemediationAI
Vendor-released patch: 1.6.4 - upgrade with 'pip install --upgrade shiny' (release tag https://github.com/posit-dev/py-shiny/releases/tag/v1.6.4, advisory https://github.com/posit-dev/py-shiny/security/advisories/GHSA-47c3-hpmg-7j6p), which validates bookmark IDs against an allowlist (single path segment [A-Za-z0-9_-]+, max 1024 chars), gates restore on the bookmark_store setting so it no longer runs when bookmarking is disabled, and honors on-disk restore only under bookmark_store='server'. No in-application configuration change mitigates the flaw on affected versions because the restore handler ran even with bookmark_store='disable'; deployments that cannot upgrade immediately should strip the _state_id_ parameter from incoming query strings at a reverse proxy or load balancer, which prevents the vulnerable path from being reached at the cost of disabling legitimate server-side bookmark restoration for users who rely on it. Applications using bookmark_store='server' together with ui.input_file() should be treated as the highest priority for upgrade, since that combination is where attacker-selected file contents could be copied into the application; the trade-off of the proxy-stripping workaround is loss of the bookmark restore feature, but it does not affect the normal page-load path.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 2 packages in pypi, euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
Shiny for Python is a framework for building interactive web applications in Python; server-side bookmarking (shiny_bookmarks) was introduced in 1.4.0. Root cause is CWE-22 (Improper Limitation of a Pathname to a Restricted Directory / Path Traversal): the bookmark restore path accepted the client-supplied _state_id_ query parameter and joined it directly into the server-side bookmark directory as <cwd>/shiny_bookmarks/<id> without validating that the value was a single safe path segment, so '..' sequences or an absolute path escaped the intended store. RestoreContext.from_query_string() was invoked on any request carrying a query string, even when bookmark_store was set to 'disable', meaning the vulnerable code path ran without opt-in. The two readable file names are constrained to input.json and values.json, which bounds the baseline impact to existence and JSON-validity probing; the more serious file-copy behavior arises only from the restore handler used with ui.input_file() under bookmark_store='server'. The upstream fix adds an allowlist regex ([A-Za-z0-9_-]+ with a 1024-character length cap) applied at the point IDs are used to build filesystem paths, gates restore on the bookmark_store setting at a single point, and honors the on-disk restore path only under bookmark_store='server'; Shiny-generated bookmark IDs are unaffected by the allowlist. The affected CPE is cpe:2.3:a:posit-dev:py-shiny and the patched release is v1.6.4.
Know when Python gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
Unauthenticated HTTP query parameter (AV:N/AC:L/PR:N/UI:N); baseline default-config impact is limited confidentiality file/path probing (C:L), with no integrity or availability effect.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
1DescriptionCVE.org
Shiny for Python is a framework for building interactive web applications in Python. From 1.4.0 until 1.6.4, bookmark restore accepts a client-supplied state_id and joins it into the server-side shiny_bookmarks directory without validating that it is a single safe path segment. An unauthenticated request can use parent-directory segments or an absolute path to make the server open input.json and values.json outside the bookmark store, even when bookmark_store is set to disable. In applications configured with bookmark_store set to server and using ui.input_file(), the restore handler can additionally copy and expose an attacker-selected file from an attacker-selected directory. This issue is fixed in version 1.6.4.
Blast Radius
ecosystem impact- 6 pypi packages depend on shiny (6 direct, 0 indirect)
Ecosystem-wide dependent count for version 1.4.0.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Path traversal exploits occur when applications use user-controlled input to construct file system paths without proper validation.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
EUVD-2026-95986
GHSA-47c3-hpmg-7j6p
NVD
CVE.org
EPSS
Exploit-DB