fix(security): mitigate GHSA-9gf9-7xcc-xcq9 & GHSA-vf6c-fgmq-xm78 + bug fixes (#667)
Co-authored-by: zuolingxuan <zuolingxuan@bytedance.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
83858fdf73
commit
b786b773f1
@@ -170,9 +170,19 @@ function createWindow(): BrowserWindow {
|
||||
show: false,
|
||||
});
|
||||
|
||||
// Handle external links
|
||||
// Handle external links — only allow safe protocols to prevent arbitrary
|
||||
// command execution via shell.openExternal() (e.g. file://, ms-msdt:, etc.)
|
||||
win.webContents.setWindowOpenHandler(({ url }) => {
|
||||
shell.openExternal(url);
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
if (parsed.protocol === 'https:' || parsed.protocol === 'http:') {
|
||||
shell.openExternal(url);
|
||||
} else {
|
||||
logger.warn(`Blocked openExternal for disallowed protocol: ${parsed.protocol}`);
|
||||
}
|
||||
} catch {
|
||||
logger.warn(`Blocked openExternal for malformed URL: ${url}`);
|
||||
}
|
||||
return { action: 'deny' };
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ipcMain } from 'electron';
|
||||
import { proxyAwareFetch } from '../../utils/proxy-fetch';
|
||||
import { PORTS } from '../../utils/config';
|
||||
import { getHostApiToken } from '../../api/server';
|
||||
|
||||
type HostApiFetchRequest = {
|
||||
path: string;
|
||||
@@ -10,6 +11,10 @@ type HostApiFetchRequest = {
|
||||
};
|
||||
|
||||
export function registerHostApiProxyHandlers(): void {
|
||||
// Expose the per-session auth token to the renderer so the browser-fallback
|
||||
// path in host-api.ts can authenticate against the Host API server.
|
||||
ipcMain.handle('hostapi:token', () => getHostApiToken());
|
||||
|
||||
ipcMain.handle('hostapi:fetch', async (_, request: HostApiFetchRequest) => {
|
||||
try {
|
||||
const path = typeof request?.path === 'string' ? request.path : '';
|
||||
@@ -19,6 +24,8 @@ export function registerHostApiProxyHandlers(): void {
|
||||
|
||||
const method = (request.method || 'GET').toUpperCase();
|
||||
const headers: Record<string, string> = { ...(request.headers || {}) };
|
||||
// Inject the per-session auth token so the Host API server accepts this request.
|
||||
headers['Authorization'] = `Bearer ${getHostApiToken()}`;
|
||||
let body: string | undefined;
|
||||
|
||||
if (request.body !== undefined && request.body !== null) {
|
||||
@@ -26,9 +33,11 @@ export function registerHostApiProxyHandlers(): void {
|
||||
body = request.body;
|
||||
} else {
|
||||
body = JSON.stringify(request.body);
|
||||
if (!headers['Content-Type'] && !headers['content-type']) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
// Ensure Content-Type is set for requests with a body so the
|
||||
// server's anti-CSRF Content-Type gate does not reject them.
|
||||
if (!headers['Content-Type'] && !headers['content-type']) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user