diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-01 11:47:39 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-01 11:47:39 +0200 |
| commit | 760ac421b1944cd69a80e3a92127a1a966f15938 (patch) | |
| tree | c894b655d4f21698ebb91c0865ddf3e04985586d /packages/meshbay-node/src/meshbay_node/roots.py | |
| parent | 752b160c7c5e671e0db8f402a52fac27bb85ab06 (diff) | |
| download | meshbay-760ac421b1944cd69a80e3a92127a1a966f15938.tar.gz | |
fix: downloads are marked and keep their extension; Explorer files are refused
The desktop app writes the Mark-of-the-Web on each file it saves on Windows, as
a browser does. Bidirectional controls are reserved characters in a saved name
(portable-name.js and paths.sanitize_for_download, and again in the main
process), so a name cannot display one extension and carry another. The node
refuses uploads of files Windows Explorer acts on by itself: desktop.ini,
.lnk, .url, .scf, .library-ms, .searchConnector-ms (F-19).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/roots.py')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/roots.py | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/roots.py b/packages/meshbay-node/src/meshbay_node/roots.py index a4f9cc9..2de0708 100644 --- a/packages/meshbay-node/src/meshbay_node/roots.py +++ b/packages/meshbay-node/src/meshbay_node/roots.py @@ -53,6 +53,21 @@ SAFE_UPLOAD_NAME = re.compile( re.UNICODE) +# Files Windows Explorer acts on by itself when it shows a folder: a link's +# icon, a folder's settings, a search connector. Placed by a member in a folder +# the operator browses, any of them can make Explorer contact a server of the +# member's choosing with the operator's Windows credentials — a known attack, +# and why mail providers refuse the same types. Refused for every node: a +# Linux node's folder may be shared to Windows machines. +SHELL_ACTIVE_NAMES = frozenset({"desktop.ini"}) +SHELL_ACTIVE_SUFFIXES = (".lnk", ".url", ".scf", ".library-ms", ".searchconnector-ms") + + +def shell_active(filename: str) -> bool: + name = filename.lower() + return name in SHELL_ACTIVE_NAMES or name.endswith(SHELL_ACTIVE_SUFFIXES) + + def _free_name(directory: Path, filename: str, taken: frozenset[str] | set[str] = frozenset()) -> str: """ |