Files
Toju/electron/path-jail.spec.ts
Myx bb0ac930ad
All checks were successful
Queue Release Build / prepare (push) Successful in 20s
Deploy Web Apps / deploy (push) Successful in 9m2s
Queue Release Build / build-windows (push) Successful in 28m8s
Queue Release Build / build-linux (push) Successful in 47m26s
Queue Release Build / build-android (push) Successful in 19m52s
Queue Release Build / finalize (push) Successful in 4m42s
Improve attachment memory safety, downloads, and high-memory alert UX.
Stream large receives to disk with chunk acks to cap renderer RAM, evict
off-screen display blobs, and route exports through a disk-aware download
service. Fix the high-memory dialog (backdrop dismiss, copy, log actions),
allow diagnostics paths in the path jail, and restore persisted image
hydration after reload.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 00:25:22 +02:00

85 lines
2.7 KiB
TypeScript

import {
describe,
it,
expect,
beforeEach,
afterEach
} from 'vitest';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import {
assertPathUnderRoot,
clearGrantedPluginReadRoots,
grantPluginReadRoot,
resolveReadablePath
} from './path-jail';
describe('path-jail', () => {
let tempRoot = '';
beforeEach(() => {
tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'metoyou-path-jail-'));
fs.mkdirSync(path.join(tempRoot, 'server', 'room-1'), { recursive: true });
fs.writeFileSync(path.join(tempRoot, 'server', 'room-1', 'file.txt'), 'ok');
});
afterEach(() => {
clearGrantedPluginReadRoots();
fs.rmSync(tempRoot, { recursive: true, force: true });
});
it('accepts paths inside allowed subdirectories', async () => {
const allowedPath = path.join(tempRoot, 'server', 'room-1', 'file.txt');
await expect(assertPathUnderRoot(tempRoot, allowedPath, ['server'])).resolves.toBe(allowedPath);
});
it('accepts diagnostics log paths under diagnostics', async () => {
const diagnosticsDir = path.join(tempRoot, 'diagnostics');
fs.mkdirSync(diagnosticsDir, { recursive: true });
const logPath = path.join(diagnosticsDir, 'perf-session.jsonl');
fs.writeFileSync(logPath, '{}');
await expect(assertPathUnderRoot(tempRoot, logPath)).resolves.toBe(logPath);
});
it('accepts cached plugin bundle paths under plugin-bundles', async () => {
const bundleDir = path.join(tempRoot, 'plugin-bundles', 'example.plugin', '1.0.0');
fs.mkdirSync(bundleDir, { recursive: true });
const bundlePath = path.join(bundleDir, 'main.js');
fs.writeFileSync(bundlePath, 'export default {}');
await expect(assertPathUnderRoot(tempRoot, bundlePath)).resolves.toBe(bundlePath);
});
it('rejects paths outside the user data root', async () => {
const outsidePath = path.join(os.tmpdir(), 'outside.txt');
await expect(assertPathUnderRoot(tempRoot, outsidePath, ['server'])).rejects.toThrow('outside allowed app-data paths');
});
it('rejects paths outside allowed subdirectories', async () => {
const pluginsPath = path.join(tempRoot, 'plugins', 'evil.txt');
await expect(assertPathUnderRoot(tempRoot, pluginsPath, ['server'])).rejects.toThrow('outside allowed app-data paths');
});
it('allows user-granted plugin source roots outside app data', async () => {
const externalRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'metoyou-plugin-source-'));
const manifestPath = path.join(externalRoot, 'plugin-source.json');
fs.writeFileSync(manifestPath, '{}');
grantPluginReadRoot(externalRoot);
await expect(resolveReadablePath(manifestPath)).resolves.toBe(manifestPath);
fs.rmSync(externalRoot, { recursive: true, force: true });
});
});