mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 14:39:42 +02:00
fix(review): harden Codex generated-artifact attachment pipeline (PR #150)
- Pass the attachment request `source` through the server deps lambda and make it a required param on SessionListenerDeps.registerAttachment + the wiring event type (the 2-arg lambda silently dropped `source`, force-confining every codex-generated artifact — the feature never worked outside the workspace); new test/session-listener-wiring.test.ts asserts the pass-through - Gate the Codex `Saved to: file://` scanner on mode === 'codex' via a codexArtifacts option threaded from the session call site; magic links stay mode-agnostic; tests assert claude/shell sessions never emit codex-generated requests - Decide the generated-artifact trust policy on the realpath-RESOLVED path (unresolvable → force-confined) and anchor the ~/.codex marker dirs to os.homedir() prefixes with startsWith instead of substring matching; symlink escape + unanchored-marker regression tests added - Run the Codex scanner on stripAnsi'd data so trailing SGR sequences don't ride into the captured URL; styled 'Saved to:' test added - Extend generateFirstPageThumbnail with jpg/jpeg/gif/webp passthrough and per-extension content types (mirrors the png passthrough) so the PR's new image formats render real thumbnails instead of 204 letter-tiles Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+9
-4
@@ -1330,7 +1330,8 @@ export class WebServer extends EventEmitter {
|
||||
}
|
||||
},
|
||||
getStore: () => this.store,
|
||||
registerAttachment: (id: string, filePath: string) => this.registerAttachment(id, filePath),
|
||||
registerAttachment: (id: string, filePath: string, source: 'external' | 'codex-generated') =>
|
||||
this.registerAttachment(id, filePath, source),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1343,13 +1344,17 @@ export class WebServer extends EventEmitter {
|
||||
* session workspace — passive magic links can't expose arbitrary host files.
|
||||
* Deliberate cross-workspace attachment goes through the explicit,
|
||||
* Origin-guarded `POST /attachments` route (and `codeman attach`, which POSTs
|
||||
* directly inside a managed session). Registration also enforces the COD-53
|
||||
* blocklist as defense-in-depth.
|
||||
* directly inside a managed session). Codex-mode `Saved to:` requests
|
||||
* (`source: 'codex-generated'`) instead go through
|
||||
* registerGeneratedArtifactAttachment, which stays force-confined unless the
|
||||
* realpath-resolved target is inside the workspace or a home-anchored
|
||||
* `~/.codex*` generated-artifact directory. Registration also enforces the
|
||||
* COD-53 blocklist as defense-in-depth.
|
||||
*/
|
||||
private async registerAttachment(
|
||||
sessionId: string,
|
||||
filePath: string,
|
||||
source: 'external' | 'codex-generated' = 'external'
|
||||
source: 'external' | 'codex-generated'
|
||||
): Promise<void> {
|
||||
const session = this.sessions.get(sessionId);
|
||||
if (!session) return;
|
||||
|
||||
Reference in New Issue
Block a user