mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-17 03:38:32 +02:00
* fix(desktop): route attachment downloads through Electron native system on Linux Replaces shell.openExternal with webContents.downloadURL for attachment downloads in the Electron desktop app. On Linux/Ubuntu, opening a CloudFront URL serving Content-Type: text/html via the system browser causes the browser to render the HTML inline instead of downloading. Electron's native downloadURL shows a save dialog and saves the file directly, fixing HTML downloads regardless of Content-Type. * test(views): update desktop download test to match the new downloadURL bridge The test still referenced the old openExternal bridge. Updated it to assert desktopAPI.downloadURL() instead. * fix(desktop): add URL scheme allowlist to download IPC handler Addresses review feedback on PR #2441. The file:download-url IPC handler called webContents.downloadURL directly, bypassing the http/https allowlist enforced by openExternalSafely. Adds downloadURLSafely() alongside the existing openExternalSafely wrapper, reuses the same isSafeExternalHttpUrl check, and extends the ESLint no-restricted-syntax rule to ban direct webContents.downloadURL calls. Also handles nits: observable warning on null mainWindow, removes dead openExternal field from DesktopBridge, adds desktop-branch failure test.
45 lines
1.4 KiB
JavaScript
45 lines
1.4 KiB
JavaScript
import globals from "globals";
|
|
import reactConfig from "@multica/eslint-config/react";
|
|
|
|
export default [
|
|
...reactConfig,
|
|
{ ignores: ["out/", "dist/"] },
|
|
{
|
|
files: ["scripts/**/*.{mjs,js}"],
|
|
languageOptions: {
|
|
globals: { ...globals.node },
|
|
},
|
|
},
|
|
// Security: every renderer-controlled URL that reaches the OS shell or the
|
|
// native download system must flow through the safe wrappers in
|
|
// src/main/external-url.ts (scheme allowlist). Enforce it statically so
|
|
// direct shell.openExternal / webContents.downloadURL calls cannot silently
|
|
// regress the protection.
|
|
{
|
|
files: ["src/main/**/*.ts"],
|
|
rules: {
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
selector:
|
|
"CallExpression[callee.object.name='shell'][callee.property.name='openExternal']",
|
|
message:
|
|
"Do not call shell.openExternal directly. Use openExternalSafely from './external-url' so the http/https allowlist stays enforced.",
|
|
},
|
|
{
|
|
selector:
|
|
"CallExpression[callee.object.property.name='webContents'][callee.property.name='downloadURL']",
|
|
message:
|
|
"Do not call webContents.downloadURL directly. Use downloadURLSafely from './external-url' so the http/https allowlist stays enforced.",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
files: ["src/main/external-url.ts"],
|
|
rules: {
|
|
"no-restricted-syntax": "off",
|
|
},
|
|
},
|
|
];
|