Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions plugins/draw/src/server/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ export function createHttpServer(opts: HttpServerOptions): http.Server {
return;
}

// API: preview a drawing session file
if (url.pathname === '/api/session/file' && req.method === 'GET') {
const requestedPath = url.searchParams.get('path');
if (!requestedPath) {
res.writeHead(400);
res.end('Missing file path');
return;
}

res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(fs.readFileSync(requestedPath, 'utf-8'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict preview reads to the drawing directory

When a draw server is exposed through its collaboration tunnel, any remote caller can supply an absolute path such as an SSH key or .env file and receive its contents because requestedPath is passed directly to readFileSync without authorization or containment. Resolve and validate the real path against the intended drawing-session directory, including rejecting traversal and symlink escapes, before reading it. SECURITY.mdL45-L48

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Handle unreadable preview paths without terminating the server

When any local or tunneled client requests a nonexistent, directory, or otherwise unreadable path, readFileSync throws from the HTTP request callback; because this server installs no exception handler, the uncaught error terminates the draw process and disconnects the collaboration session. Catch filesystem errors and return an appropriate 4xx response instead.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Security: Restrict session-file reads to the session directory

When a draw session is reachable through its collaboration tunnel (the default for new sessions when a supported tunnel is installed), any participant with the share URL can call GET /api/session/file?path=/home/... without application authentication. The query parameter is passed directly to readFileSync, before the UI containment check, so the plugin returns any developer-readable file, including SSH keys, tokens, .env files, or private source. Canonicalize the path, reject absolute/traversal/symlink escapes, and allow reads only inside the intended session directory. This violates the trusted-parent path-confinement requirement.

SECURITY.md reference: SECURITY.md:L45-L48

Useful? React with 👍 / 👎.

return;
}

// Serve static UI files
let filePath = url.pathname === '/' ? '/index.html' : url.pathname;
const fullPath = path.join(uiDistDir, filePath);
Expand Down