You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DupFileManager's generated report and its advanced options page both load JavaScript from https://www.axter.com/js/, and both pages hold the user's Stash API key. Third-party script therefore executes in a page that has full API access to the user's Stash instance.
This is a design/supply-chain issue rather than an active exploit — nothing is known to be wrong with the domain today. The point is that the security of every DupFileManager user's Stash instance currently depends on a single third-party domain staying under its owner's control indefinitely.
The two facts that combine
1. The pages load remote script with no integrity pinning
DupFileManager_report_config.py:187-189 (the generated duplicate report):
and advance_options.html:100-101 reads it back out of location.search.
Impact
Any party able to serve content at www.axter.com/js/ — through domain expiry and re-registration, DNS or hosting compromise, or an MITM on a user who reaches the page over plain HTTP — gets arbitrary JavaScript execution in a page holding a valid Stash API key. From there: read the entire library, and drive any mutation the API allows, including scene and file deletion.
For users who expose Stash beyond their LAN, that is reachable remotely.
Two smaller issues in the same area:
API key in a query string leaks into browser history, and into Referer headers on any outbound request from that page — including the requests to axter.com. Worth moving out of the URL regardless of the rest.
advance_options.html:126 does console.log("Using apiKey = " + apiKey), writing the key to the browser console.
Suggested fixes
In rough order of value:
Vendor the three files into the plugin directory and reference them relatively. The plugin already ships its own JS and CSS, so this removes the external dependency entirely and costs about 90 KB. This alone closes the main issue.
Stop passing the key in the URL.sessionStorage, or a postMessage from the opener, keeps it out of history and Referer.
Drop the console.log of the key.
If vendoring is genuinely unwanted, a well-known CDN with SRI hashes and crossorigin is a meaningful improvement on an unpinned personal domain — though vendoring is still better for a self-hosted, often-offline application.
Notes
This affects DupFileManager only. The axter.com references in FileMonitor and RenameFile are author-attribution comments in headers, not resource loads.
Raised publicly because the repository has no SECURITY.md and private vulnerability reporting is not enabled. Happy to move this somewhere private if maintainers would prefer.
Not intended as criticism of the plugin or its author — DupFileManager is doing useful work, and this is a pattern that was entirely normal web practice for years. It just sits badly with an API key in the same page.
Summary
DupFileManager's generated report and its advanced options page both load JavaScript from
https://www.axter.com/js/, and both pages hold the user's Stash API key. Third-party script therefore executes in a page that has full API access to the user's Stash instance.This is a design/supply-chain issue rather than an active exploit — nothing is known to be wrong with the domain today. The point is that the security of every DupFileManager user's Stash instance currently depends on a single third-party domain staying under its owner's control indefinitely.
The two facts that combine
1. The pages load remote script with no integrity pinning
DupFileManager_report_config.py:187-189(the generated duplicate report):advance_options.html:93-95loads the same three.No
integrity/ SRI attribute, so a changed file at that URL is executed without complaint.2. Those same pages hold the API key
DupFileManager_report_config.py:191declaresvar apiKey = "", and line 225 attaches it to every request to Stash:Line 349 then passes it to the options page in the URL query string:
and
advance_options.html:100-101reads it back out oflocation.search.Impact
Any party able to serve content at
www.axter.com/js/— through domain expiry and re-registration, DNS or hosting compromise, or an MITM on a user who reaches the page over plain HTTP — gets arbitrary JavaScript execution in a page holding a valid Stash API key. From there: read the entire library, and drive any mutation the API allows, including scene and file deletion.For users who expose Stash beyond their LAN, that is reachable remotely.
Two smaller issues in the same area:
Refererheaders on any outbound request from that page — including the requests toaxter.com. Worth moving out of the URL regardless of the rest.advance_options.html:126doesconsole.log("Using apiKey = " + apiKey), writing the key to the browser console.Suggested fixes
In rough order of value:
sessionStorage, or apostMessagefrom the opener, keeps it out of history andReferer.console.logof the key.crossoriginis a meaningful improvement on an unpinned personal domain — though vendoring is still better for a self-hosted, often-offline application.Notes
axter.comreferences in FileMonitor and RenameFile are author-attribution comments in headers, not resource loads.SECURITY.mdand private vulnerability reporting is not enabled. Happy to move this somewhere private if maintainers would prefer.