mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 08:29:42 +02:00
COD-37 add server-side attachment pipeline (registry, magic-link, path guard)
Adds the foundation for serving local files to the browser as live external attachments with a stable id, so requests never carry arbitrary absolute paths. - attachment-registry: in-memory, session-scoped registry. registerExternalAttachment validates an absolute path, resolves symlinks, enforces the path guard, and mints an `att_<uuid>` id; records are cleared when the session is removed. - attachment path guard: a configurable blocklist (secret locations + /root,/etc trees, extendable via attachmentBlockedPaths / CODEMAN_ATTACHMENT_BLOCKED_PATHS) plus an optional, default-off workspace-confinement mode. Shares one sensitive-path blocklist (web/sensitive-path.ts) with /api/download, which is refactored to use the extracted module instead of an inline copy. - terminal magic links: the session scans output for codeman://attach?path=... and emits `attachmentRequested`; the web server registers the file and broadcasts an `attachment:detected` SSE event. `codeman attach <path>` (CLI) prints the magic link or POSTs directly when a session id is known. - image watcher: detects png/pdf/docx/pptx dropped into a session's working dir and emits `attachment:detected`. - routes: POST /api/sessions/:id/attachments (register) and GET /api/sessions/:id/attachments/:attachmentId/raw (serve), both re-checking the guard before streaming. Document previews/thumbnails and the attachment-history drawer build on this foundation and land separately. Verified: tsc --noEmit, lint, format, frontend-syntax, full test:ci (2846 passed), and a server boot smoke (/api/status 200).
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @fileoverview Shared sensitive-path blocklist.
|
||||
*
|
||||
* A small defense-in-depth blocklist of absolute paths that must never be
|
||||
* served to the browser regardless of how the path was obtained (workspace
|
||||
* download, cross-workspace attachment registration, raw/preview serving).
|
||||
*
|
||||
* This is intentionally a BLOCKLIST, not a workspace-confinement check:
|
||||
* cross-workspace attachment is a supported feature (codeman-publish skill +
|
||||
* the automated review-card loop attaching files under ~/.codeman/), so a
|
||||
* strict session-workspace boundary would break legitimate use. The blocklist
|
||||
* rejects well-known secret locations (system password files, SSH keys, cloud
|
||||
* credentials, dotenv files) while leaving ordinary cross-workspace files
|
||||
* attachable.
|
||||
*
|
||||
* Callers MUST resolve symlinks (realpath) BEFORE calling isSensitivePath so a
|
||||
* symlink pointing at a sensitive target is also caught.
|
||||
*/
|
||||
|
||||
import { homedir } from 'node:os';
|
||||
|
||||
const SENSITIVE_PATTERNS: RegExp[] = [
|
||||
/^\/etc\/shadow$/,
|
||||
/^\/etc\/gshadow$/,
|
||||
/^\/etc\/master\.passwd$/,
|
||||
new RegExp(`^${homedir().replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\/\\.ssh\\/`),
|
||||
/\/\.env$/,
|
||||
/\/\.env\./,
|
||||
/\/credentials(\.json|\.yml|\.yaml|\.xml)?$/i,
|
||||
/\/\.aws\/credentials$/,
|
||||
/\/\.gcloud\/credentials\.db$/,
|
||||
/\/\.docker\/config\.json$/,
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns true if the given ABSOLUTE, symlink-resolved path matches the
|
||||
* sensitive-file blocklist and must not be served to the browser.
|
||||
*/
|
||||
export function isSensitivePath(absPath: string): boolean {
|
||||
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(absPath));
|
||||
}
|
||||
Reference in New Issue
Block a user