sdlc-agent-4-enterprise-server 1.55.7 → 1.55.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  </p>
7
7
 
8
8
  <p align="center">
9
- <img src="https://img.shields.io/badge/version-1.55.3-blue?style=for-the-badge" alt="Version">
9
+ <img src="https://img.shields.io/badge/version-1.55.8-blue?style=for-the-badge" alt="Version">
10
10
  <img src="https://img.shields.io/badge/tools-66+-teal?style=for-the-badge" alt="Tools">
11
11
  <img src="https://img.shields.io/badge/node-%3E%3D18-green?style=for-the-badge" alt="Node">
12
12
  </p>
@@ -30,9 +30,26 @@ export interface ContentProxyOverride {
30
30
  /** Disable the adapter entirely for this tool. */
31
31
  enabled?: boolean;
32
32
  }
33
- /** Artifact output roots — dedicated sinks for orphaned artifact files. */
34
- export declare function artifactOutputRoots(): readonly string[];
35
- /** Check whether a real path falls inside one of the artifact roots. */
33
+ /**
34
+ * Artifact output roots — the dedicated sinks for orphaned artifact files
35
+ * (SA4E-380 F-01/F-05). Shared single source for OI-14 (immediate cleanup +
36
+ * read confinement) and OI-15 (periodic sweep). The raw OS temp root and the
37
+ * agent workspace are NEVER roots.
38
+ *
39
+ * Resolution order:
40
+ * 1. `ARTIFACT_OUTPUT_ROOTS` env override — `path.delimiter`-separated list
41
+ * (operator trust; see SA-08 for the recommended defense-in-depth checks).
42
+ * 2. Defaults: the dedicated `%TEMP%/sa4e-artifacts` sink, the workspace
43
+ * `tmp/artifacts` directory, and the markdown-exporter child's own
44
+ * artifact home (F-01: without it every local-path read fails confinement).
45
+ */
46
+ export declare function artifactOutputRoots(env?: NodeJS.ProcessEnv): readonly string[];
47
+ /**
48
+ * F-01 containment: is `candidate` (already realpath-canonicalised by the
49
+ * caller) located inside `root`? Compares with `path.relative` — case-folded
50
+ * on win32, cross-device resolves to an absolute path → rejected. Separator
51
+ * boundary is honoured (`<root>-evil` is NOT inside `<root>`).
52
+ */
36
53
  export declare function isPathWithinRoot(root: string, candidate: string): boolean;
37
54
  /** Per-tool escape hatch for tools that defy the naming/description convention. */
38
55
  export declare const CONTENT_PROXY_OVERRIDES: Record<string, ContentProxyOverride>;
@@ -11,7 +11,8 @@
11
11
  *
12
12
  * Overrides exist only for tools that do not follow the convention.
13
13
  */
14
- import * as fs from 'fs';
14
+ import * as os from 'os';
15
+ import * as path from 'path';
15
16
  /** Tool-name prefixes whose result is a file written by the child server. */
16
17
  export const FILE_TOOL_NAME_PREFIXES = ['export_', 'render_', 'generate_'];
17
18
  /** Description fallback: "Convert ... to PDF/DOCX/…" (target must be a file format). */
@@ -32,24 +33,49 @@ export const CONTENT_PARAM_ALIASES = [
32
33
  export const NON_CONTENT_PARAM = /^(content_base64|.*_base64|file_path|.*_path|path|url|uri|dir|.*_id|id|name|.*_name|key|.*_key|token|secret|password|mime|.*_type|type|format|mode|encoding)$/i;
33
34
  /** Maximum artifact size inlined as base64 (mirrors the extension pre-read cap). */
34
35
  export const MAX_ARTIFACT_BYTES = 25 * 1024 * 1024;
35
- /** Artifact output roots — dedicated sinks for orphaned artifact files. */
36
- export function artifactOutputRoots() {
37
- // Convention: ARTIFACT_OUTPUT_ROOTS env var, or default per-workspace roots
38
- const env = process.env.ARTIFACT_OUTPUT_ROOTS;
39
- if (env)
40
- return env.split(':').map((s) => s.trim()).filter(Boolean);
41
- // Default: no roots configured → sweep will find nothing (safe no-op)
42
- return [];
36
+ /**
37
+ * Artifact output roots — the dedicated sinks for orphaned artifact files
38
+ * (SA4E-380 F-01/F-05). Shared single source for OI-14 (immediate cleanup +
39
+ * read confinement) and OI-15 (periodic sweep). The raw OS temp root and the
40
+ * agent workspace are NEVER roots.
41
+ *
42
+ * Resolution order:
43
+ * 1. `ARTIFACT_OUTPUT_ROOTS` env override — `path.delimiter`-separated list
44
+ * (operator trust; see SA-08 for the recommended defense-in-depth checks).
45
+ * 2. Defaults: the dedicated `%TEMP%/sa4e-artifacts` sink, the workspace
46
+ * `tmp/artifacts` directory, and the markdown-exporter child's own
47
+ * artifact home (F-01: without it every local-path read fails confinement).
48
+ */
49
+ export function artifactOutputRoots(env = process.env) {
50
+ const override = parseArtifactRootsEnv(env.ARTIFACT_OUTPUT_ROOTS);
51
+ if (override)
52
+ return override;
53
+ const workspace = path.resolve(process.cwd());
54
+ const childHome = process.platform === 'win32'
55
+ ? path.join(process.env.LOCALAPPDATA ?? '', 'markdown-exporter-mcp', 'artifacts')
56
+ : path.join(process.env.HOME ?? os.homedir(), '.cache', 'markdown-exporter-mcp', 'artifacts');
57
+ return [
58
+ path.join(os.tmpdir(), 'sa4e-artifacts'),
59
+ path.join(workspace, 'tmp', 'artifacts'),
60
+ path.resolve(childHome),
61
+ ];
43
62
  }
44
- /** Check whether a real path falls inside one of the artifact roots. */
63
+ /** SA-08 surface: parse the env override; empty/garbage → fall back to defaults. */
64
+ function parseArtifactRootsEnv(raw) {
65
+ if (!raw)
66
+ return undefined;
67
+ const roots = raw.split(path.delimiter).map((s) => s.trim()).filter(Boolean);
68
+ return roots.length ? roots : undefined;
69
+ }
70
+ /**
71
+ * F-01 containment: is `candidate` (already realpath-canonicalised by the
72
+ * caller) located inside `root`? Compares with `path.relative` — case-folded
73
+ * on win32, cross-device resolves to an absolute path → rejected. Separator
74
+ * boundary is honoured (`<root>-evil` is NOT inside `<root>`).
75
+ */
45
76
  export function isPathWithinRoot(root, candidate) {
46
- try {
47
- const real = fs.realpathSync(candidate);
48
- return artifactOutputRoots().some((r) => real.startsWith(r));
49
- }
50
- catch {
51
- return false;
52
- }
77
+ const rel = path.relative(path.resolve(root), path.resolve(candidate));
78
+ return rel === '' || (rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel));
53
79
  }
54
80
  /** Per-tool escape hatch for tools that defy the naming/description convention. */
55
81
  export const CONTENT_PROXY_OVERRIDES = {};
@@ -1 +1 @@
1
- {"version":3,"file":"ContentProxy.js","sourceRoot":"","sources":["../../src/config/ContentProxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,6EAA6E;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AAE9F,wFAAwF;AACxF,MAAM,CAAC,MAAM,uBAAuB,GAAG,gEAAgE,CAAC;AAExG,qEAAqE;AACrE,MAAM,CAAC,MAAM,qBAAqB,GAAsB;IACtD,UAAU;IACV,kBAAkB;IAClB,SAAS;IACT,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,QAAQ;IACR,UAAU;CACX,CAAC;AAEF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAC5B,gKAAgK,CAAC;AAEnK,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAYnD,2EAA2E;AAC3E,MAAM,UAAU,mBAAmB;IACjC,4EAA4E;IAC5E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAC9C,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpE,sEAAsE;IACtE,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,SAAiB;IAC9D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,mBAAmB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,uBAAuB,GAAyC,EAAE,CAAC"}
1
+ {"version":3,"file":"ContentProxy.js","sourceRoot":"","sources":["../../src/config/ContentProxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,6EAA6E;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AAE9F,wFAAwF;AACxF,MAAM,CAAC,MAAM,uBAAuB,GAAG,gEAAgE,CAAC;AAExG,qEAAqE;AACrE,MAAM,CAAC,MAAM,qBAAqB,GAAsB;IACtD,UAAU;IACV,kBAAkB;IAClB,SAAS;IACT,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,QAAQ;IACR,UAAU;CACX,CAAC;AAEF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAC5B,gKAAgK,CAAC;AAEnK,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAYnD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAClE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,SAAS,GACb,OAAO,CAAC,QAAQ,KAAK,OAAO;QAC1B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,EAAE,uBAAuB,EAAE,WAAW,CAAC;QACjF,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,uBAAuB,EAAE,WAAW,CAAC,CAAC;IAClG,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC;QACxC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;KACxB,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,SAAS,qBAAqB,CAAC,GAAuB;IACpD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7E,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,SAAiB;IAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IACvE,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACnG,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,uBAAuB,GAAyC,EAAE,CAAC"}
@@ -11,11 +11,19 @@
11
11
  * live on another machine. That case is reported as a tool error by the caller,
12
12
  * never silently downgraded to a path.
13
13
  */
14
+ import * as fs from 'fs';
14
15
  export interface ArtifactDeps {
15
16
  /** Read a resource from the child server (works across hosts). */
16
17
  readResource?: (uri: string) => Promise<Buffer | null>;
17
18
  /** Fetch an http(s) URL. Overridable for tests; defaults to global fetch. */
18
19
  fetchUrl?: (url: string) => Promise<Buffer | null>;
20
+ /**
21
+ * OI-14 local-read cleanup hook. Receives the absolute path and the
22
+ * pre-read stat; the default (no hook) deletes the artifact after its
23
+ * bytes are inlined. Only local reads invoke it — resource/URL/blob
24
+ * resolutions never do (UT-46).
25
+ */
26
+ cleanup?: (filePath: string, stat: fs.Stats) => void;
19
27
  }
20
28
  export interface FetchedArtifact {
21
29
  buffer: Buffer;
@@ -15,6 +15,7 @@ import * as fs from 'fs';
15
15
  import * as path from 'path';
16
16
  import { fileURLToPath, pathToFileURL } from 'url';
17
17
  import { MAX_ARTIFACT_BYTES } from '../../../config/ContentProxy.js';
18
+ import { isWithinArtifactRoots } from '../artifact-cleanup/artifact-roots.js';
18
19
  import { nameFromLocation, nameFromMime, safeName } from './artifact-name.js';
19
20
  /** Resolve one `artifacts[]` entry to bytes, or null when nothing is readable. */
20
21
  export async function resolveArtifact(artifact, deps) {
@@ -67,7 +68,7 @@ export async function readLocation(location, deps) {
67
68
  return (deps.fetchUrl ?? fetchHttp)(location);
68
69
  const fileUri = location.startsWith('file:') ? location : toFileUri(location);
69
70
  if (location.startsWith('file:')) {
70
- const local = readLocalFileUri(location);
71
+ const local = readLocalFileUri(location, deps);
71
72
  if (local)
72
73
  return local;
73
74
  return deps.readResource ? deps.readResource(location) : null;
@@ -76,7 +77,7 @@ export async function readLocation(location, deps) {
76
77
  // Any other scheme (artifact://, mcp://, …) is server-owned — ask the server.
77
78
  return deps.readResource ? deps.readResource(location) : null;
78
79
  }
79
- const local = readLocalFile(path.resolve(location));
80
+ const local = readLocalFile(path.resolve(location), deps);
80
81
  if (local)
81
82
  return local;
82
83
  return deps.readResource && fileUri ? deps.readResource(fileUri) : null;
@@ -94,27 +95,71 @@ function fromBase64(value, name, mime) {
94
95
  return null;
95
96
  return { buffer, file_name: name ?? nameFromMime(mime), mime_type: mime };
96
97
  }
97
- /** Read a file on the backend host: regular file only, size-capped, no symlinks. */
98
- function readLocalFile(filePath) {
98
+ /**
99
+ * Read a file on the backend host: regular file only, size-capped, no symlinks.
100
+ *
101
+ * SA4E-380 F-01 (binding): the path's real location (symlinks/junctions/`..`
102
+ * resolved) must fall inside the dedicated ARTIFACT_OUTPUT_ROOTS BEFORE any
103
+ * filesystem access — an out-of-root path is never read and never deleted.
104
+ *
105
+ * SA4E-380 OI-14: once the bytes are inlined the local artifact is garbage —
106
+ * the cleanup hook (default: delete with F-06 stat-identity re-verification)
107
+ * runs after the successful read. A failed read never deletes anything.
108
+ */
109
+ function readLocalFile(filePath, deps) {
110
+ if (!isWithinArtifactRoots(filePath))
111
+ return null;
99
112
  try {
100
113
  const stat = fs.lstatSync(filePath);
101
114
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_ARTIFACT_BYTES)
102
115
  return null;
103
116
  const buffer = fs.readFileSync(filePath);
104
- return buffer.length <= MAX_ARTIFACT_BYTES ? buffer : null;
117
+ if (buffer.length > MAX_ARTIFACT_BYTES)
118
+ return null;
119
+ try {
120
+ (deps.cleanup ?? deleteLocalArtifact)(filePath, stat);
121
+ }
122
+ catch {
123
+ // Cleanup failure never fails the tool call (UT-45) — bytes are safe.
124
+ console.warn(`[artifact-source] cleanup hook failed for '${path.basename(filePath)}'`);
125
+ }
126
+ return buffer;
105
127
  }
106
128
  catch {
107
129
  return null;
108
130
  }
109
131
  }
110
- function readLocalFileUri(uri) {
132
+ function readLocalFileUri(uri, deps) {
111
133
  try {
112
- return readLocalFile(fileURLToPath(uri));
134
+ return readLocalFile(fileURLToPath(uri), deps);
113
135
  }
114
136
  catch {
115
137
  return null;
116
138
  }
117
139
  }
140
+ /**
141
+ * Default OI-14 cleanup: delete the artifact whose bytes were just inlined.
142
+ * F-06 TOCTOU guard — re-stat and verify identity (ino/size/mtimeMs) before
143
+ * unlink so a path swapped between read and delete is never removed.
144
+ */
145
+ function deleteLocalArtifact(filePath, before) {
146
+ let now;
147
+ try {
148
+ now = fs.lstatSync(filePath);
149
+ }
150
+ catch {
151
+ return; // already gone — nothing to delete
152
+ }
153
+ if (now.ino !== before.ino || now.size !== before.size || now.mtimeMs !== before.mtimeMs)
154
+ return;
155
+ try {
156
+ fs.unlinkSync(filePath);
157
+ }
158
+ catch {
159
+ // I-3: basename only — never leak host paths into logs.
160
+ console.warn(`[artifact-source] could not delete local artifact '${path.basename(filePath)}'`);
161
+ }
162
+ }
118
163
  /** Cross-platform file:// URI — a POSIX path stays POSIX even on a Windows host. */
119
164
  function toFileUri(location) {
120
165
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-source.js","sourceRoot":"","sources":["../../../../src/modules/orchestration/content-proxy/artifact-source.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"artifact-source.js","sourceRoot":"","sources":["../../../../src/modules/orchestration/content-proxy/artifact-source.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdlc-agent-4-enterprise-server",
3
- "version": "1.55.7",
3
+ "version": "1.55.8",
4
4
  "description": "Code Intelligence MCP Server — multi-agent SDLC pipeline with semantic memory, code graph, and draw.io integration",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -12,7 +12,8 @@
12
12
  * Overrides exist only for tools that do not follow the convention.
13
13
  */
14
14
 
15
- import * as fs from 'fs';
15
+ import * as os from 'os';
16
+ import * as path from 'path';
16
17
  /** Tool-name prefixes whose result is a file written by the child server. */
17
18
  export const FILE_TOOL_NAME_PREFIXES: readonly string[] = ['export_', 'render_', 'generate_'];
18
19
 
@@ -49,23 +50,50 @@ export interface ContentProxyOverride {
49
50
  enabled?: boolean;
50
51
  }
51
52
 
52
- /** Artifact output roots — dedicated sinks for orphaned artifact files. */
53
- export function artifactOutputRoots(): readonly string[] {
54
- // Convention: ARTIFACT_OUTPUT_ROOTS env var, or default per-workspace roots
55
- const env = process.env.ARTIFACT_OUTPUT_ROOTS;
56
- if (env) return env.split(':').map((s) => s.trim()).filter(Boolean);
57
- // Default: no roots configured → sweep will find nothing (safe no-op)
58
- return [];
53
+ /**
54
+ * Artifact output roots — the dedicated sinks for orphaned artifact files
55
+ * (SA4E-380 F-01/F-05). Shared single source for OI-14 (immediate cleanup +
56
+ * read confinement) and OI-15 (periodic sweep). The raw OS temp root and the
57
+ * agent workspace are NEVER roots.
58
+ *
59
+ * Resolution order:
60
+ * 1. `ARTIFACT_OUTPUT_ROOTS` env override — `path.delimiter`-separated list
61
+ * (operator trust; see SA-08 for the recommended defense-in-depth checks).
62
+ * 2. Defaults: the dedicated `%TEMP%/sa4e-artifacts` sink, the workspace
63
+ * `tmp/artifacts` directory, and the markdown-exporter child's own
64
+ * artifact home (F-01: without it every local-path read fails confinement).
65
+ */
66
+ export function artifactOutputRoots(env: NodeJS.ProcessEnv = process.env): readonly string[] {
67
+ const override = parseArtifactRootsEnv(env.ARTIFACT_OUTPUT_ROOTS);
68
+ if (override) return override;
69
+ const workspace = path.resolve(process.cwd());
70
+ const childHome =
71
+ process.platform === 'win32'
72
+ ? path.join(process.env.LOCALAPPDATA ?? '', 'markdown-exporter-mcp', 'artifacts')
73
+ : path.join(process.env.HOME ?? os.homedir(), '.cache', 'markdown-exporter-mcp', 'artifacts');
74
+ return [
75
+ path.join(os.tmpdir(), 'sa4e-artifacts'),
76
+ path.join(workspace, 'tmp', 'artifacts'),
77
+ path.resolve(childHome),
78
+ ];
59
79
  }
60
80
 
61
- /** Check whether a real path falls inside one of the artifact roots. */
81
+ /** SA-08 surface: parse the env override; empty/garbage → fall back to defaults. */
82
+ function parseArtifactRootsEnv(raw: string | undefined): readonly string[] | undefined {
83
+ if (!raw) return undefined;
84
+ const roots = raw.split(path.delimiter).map((s) => s.trim()).filter(Boolean);
85
+ return roots.length ? roots : undefined;
86
+ }
87
+
88
+ /**
89
+ * F-01 containment: is `candidate` (already realpath-canonicalised by the
90
+ * caller) located inside `root`? Compares with `path.relative` — case-folded
91
+ * on win32, cross-device resolves to an absolute path → rejected. Separator
92
+ * boundary is honoured (`<root>-evil` is NOT inside `<root>`).
93
+ */
62
94
  export function isPathWithinRoot(root: string, candidate: string): boolean {
63
- try {
64
- const real = fs.realpathSync(candidate);
65
- return artifactOutputRoots().some((r) => real.startsWith(r));
66
- } catch {
67
- return false;
68
- }
95
+ const rel = path.relative(path.resolve(root), path.resolve(candidate));
96
+ return rel === '' || (rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel));
69
97
  }
70
98
 
71
99
  /** Per-tool escape hatch for tools that defy the naming/description convention. */
@@ -11,7 +11,12 @@ import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
11
11
  import { McpClientManager } from '../McpClientManager.js';
12
12
  import { silentLogger } from '../../../__tests__/sa4e-testkit.js';
13
13
 
14
- const TMP = fs.mkdtempSync(path.join(os.tmpdir(), 'content-proxy-mgr-'));
14
+ // SA4E-380 F-01: a local artifact is only inlined when it lives inside a
15
+ // dedicated artifact root. The default root is `<os.tmpdir()>/sa4e-artifacts`,
16
+ // so the DOCX fixture must be created there for the containment check to pass.
17
+ const ARTIFACT_ROOT = path.join(os.tmpdir(), 'sa4e-artifacts');
18
+ fs.mkdirSync(ARTIFACT_ROOT, { recursive: true });
19
+ const TMP = fs.mkdtempSync(path.join(ARTIFACT_ROOT, 'content-proxy-mgr-'));
15
20
  afterAll(() => fs.rmSync(TMP, { recursive: true, force: true }));
16
21
 
17
22
  const EXPORT_DOCX_TOOL = {
@@ -13,7 +13,12 @@ import { adaptInvocation } from '../invocation-adapter.js';
13
13
  import { adaptResult } from '../result-adapter.js';
14
14
  import type { ToolDefinition } from '../../../../types/tool.js';
15
15
 
16
- const TMP = fs.mkdtempSync(path.join(os.tmpdir(), 'content-proxy-'));
16
+ // SA4E-380 F-01: local artifacts are only inlined when they live inside a
17
+ // dedicated artifact root. The default root is `<os.tmpdir()>/sa4e-artifacts`,
18
+ // so fixtures must be created there for the containment check to pass.
19
+ const ARTIFACT_ROOT = path.join(os.tmpdir(), 'sa4e-artifacts');
20
+ fs.mkdirSync(ARTIFACT_ROOT, { recursive: true });
21
+ const TMP = fs.mkdtempSync(path.join(ARTIFACT_ROOT, 'content-proxy-'));
17
22
  afterAll(() => fs.rmSync(TMP, { recursive: true, force: true }));
18
23
 
19
24
  const EXPORT_DOCX: ToolDefinition = {
@@ -16,6 +16,7 @@ import * as fs from 'fs';
16
16
  import * as path from 'path';
17
17
  import { fileURLToPath, pathToFileURL } from 'url';
18
18
  import { MAX_ARTIFACT_BYTES } from '../../../config/ContentProxy.js';
19
+ import { isWithinArtifactRoots } from '../artifact-cleanup/artifact-roots.js';
19
20
  import { nameFromLocation, nameFromMime, safeName } from './artifact-name.js';
20
21
 
21
22
  export interface ArtifactDeps {
@@ -23,6 +24,13 @@ export interface ArtifactDeps {
23
24
  readResource?: (uri: string) => Promise<Buffer | null>;
24
25
  /** Fetch an http(s) URL. Overridable for tests; defaults to global fetch. */
25
26
  fetchUrl?: (url: string) => Promise<Buffer | null>;
27
+ /**
28
+ * OI-14 local-read cleanup hook. Receives the absolute path and the
29
+ * pre-read stat; the default (no hook) deletes the artifact after its
30
+ * bytes are inlined. Only local reads invoke it — resource/URL/blob
31
+ * resolutions never do (UT-46).
32
+ */
33
+ cleanup?: (filePath: string, stat: fs.Stats) => void;
26
34
  }
27
35
 
28
36
  export interface FetchedArtifact {
@@ -81,7 +89,7 @@ export async function readLocation(location: string, deps: ArtifactDeps): Promis
81
89
 
82
90
  const fileUri = location.startsWith('file:') ? location : toFileUri(location);
83
91
  if (location.startsWith('file:')) {
84
- const local = readLocalFileUri(location);
92
+ const local = readLocalFileUri(location, deps);
85
93
  if (local) return local;
86
94
  return deps.readResource ? deps.readResource(location) : null;
87
95
  }
@@ -91,7 +99,7 @@ export async function readLocation(location: string, deps: ArtifactDeps): Promis
91
99
  return deps.readResource ? deps.readResource(location) : null;
92
100
  }
93
101
 
94
- const local = readLocalFile(path.resolve(location));
102
+ const local = readLocalFile(path.resolve(location), deps);
95
103
  if (local) return local;
96
104
  return deps.readResource && fileUri ? deps.readResource(fileUri) : null;
97
105
  }
@@ -109,26 +117,65 @@ function fromBase64(value: string, name: string | null, mime?: string): FetchedA
109
117
  return { buffer, file_name: name ?? nameFromMime(mime), mime_type: mime };
110
118
  }
111
119
 
112
- /** Read a file on the backend host: regular file only, size-capped, no symlinks. */
113
- function readLocalFile(filePath: string): Buffer | null {
120
+ /**
121
+ * Read a file on the backend host: regular file only, size-capped, no symlinks.
122
+ *
123
+ * SA4E-380 F-01 (binding): the path's real location (symlinks/junctions/`..`
124
+ * resolved) must fall inside the dedicated ARTIFACT_OUTPUT_ROOTS BEFORE any
125
+ * filesystem access — an out-of-root path is never read and never deleted.
126
+ *
127
+ * SA4E-380 OI-14: once the bytes are inlined the local artifact is garbage —
128
+ * the cleanup hook (default: delete with F-06 stat-identity re-verification)
129
+ * runs after the successful read. A failed read never deletes anything.
130
+ */
131
+ function readLocalFile(filePath: string, deps: ArtifactDeps): Buffer | null {
132
+ if (!isWithinArtifactRoots(filePath)) return null;
114
133
  try {
115
134
  const stat = fs.lstatSync(filePath);
116
135
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_ARTIFACT_BYTES) return null;
117
136
  const buffer = fs.readFileSync(filePath);
118
- return buffer.length <= MAX_ARTIFACT_BYTES ? buffer : null;
137
+ if (buffer.length > MAX_ARTIFACT_BYTES) return null;
138
+ try {
139
+ (deps.cleanup ?? deleteLocalArtifact)(filePath, stat);
140
+ } catch {
141
+ // Cleanup failure never fails the tool call (UT-45) — bytes are safe.
142
+ console.warn(`[artifact-source] cleanup hook failed for '${path.basename(filePath)}'`);
143
+ }
144
+ return buffer;
119
145
  } catch {
120
146
  return null;
121
147
  }
122
148
  }
123
149
 
124
- function readLocalFileUri(uri: string): Buffer | null {
150
+ function readLocalFileUri(uri: string, deps: ArtifactDeps): Buffer | null {
125
151
  try {
126
- return readLocalFile(fileURLToPath(uri));
152
+ return readLocalFile(fileURLToPath(uri), deps);
127
153
  } catch {
128
154
  return null;
129
155
  }
130
156
  }
131
157
 
158
+ /**
159
+ * Default OI-14 cleanup: delete the artifact whose bytes were just inlined.
160
+ * F-06 TOCTOU guard — re-stat and verify identity (ino/size/mtimeMs) before
161
+ * unlink so a path swapped between read and delete is never removed.
162
+ */
163
+ function deleteLocalArtifact(filePath: string, before: fs.Stats): void {
164
+ let now: fs.Stats;
165
+ try {
166
+ now = fs.lstatSync(filePath);
167
+ } catch {
168
+ return; // already gone — nothing to delete
169
+ }
170
+ if (now.ino !== before.ino || now.size !== before.size || now.mtimeMs !== before.mtimeMs) return;
171
+ try {
172
+ fs.unlinkSync(filePath);
173
+ } catch {
174
+ // I-3: basename only — never leak host paths into logs.
175
+ console.warn(`[artifact-source] could not delete local artifact '${path.basename(filePath)}'`);
176
+ }
177
+ }
178
+
132
179
  /** Cross-platform file:// URI — a POSIX path stays POSIX even on a Windows host. */
133
180
  function toFileUri(location: string): string | null {
134
181
  try {
@@ -125,11 +125,14 @@ describe.skipIf(!dockerAvailable)('Sandbox module — Docker integration (TC-01,
125
125
  const createParsed = JSON.parse(create.content[0].text);
126
126
  const sessionId = createParsed.sessionId;
127
127
 
128
- const res = await handlers.get('sandbox_exec')!({ command: 'curl -s -m 5 https://google.com || true', sessionId });
128
+ // No `|| true` here: that would force the shell to exit 0 and mask the very
129
+ // failure we assert. In network:none mode curl cannot resolve/connect, so it
130
+ // exits non-zero (6/7/28) and returns no body — both prove isolation holds.
131
+ const res = await handlers.get('sandbox_exec')!({ command: 'curl -s -m 5 https://google.com', sessionId });
129
132
  const parsed = JSON.parse(res.content[0].text);
130
- // In network:none mode, curl should fail (non-zero exit code) or return empty if it exists.
131
- // Since we are asserting isolation, an exit code of 0 means it reached the internet.
133
+ // An exit code of 0 with a response body would mean the container reached the internet.
132
134
  expect(parsed.exitCode).not.toBe(0);
135
+ expect(parsed.stdout.trim()).toBe('');
133
136
  await handlers.get('sandbox_session')!({ action: 'destroy', sessionId });
134
137
  }, 30000);
135
138