agents-bridge 0.3.9 → 0.3.11

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.
Files changed (66) hide show
  1. package/dist/agents/cli-runner.d.ts.map +1 -1
  2. package/dist/agents/cli-runner.js +5 -29
  3. package/dist/agents/cli-runner.js.map +1 -1
  4. package/dist/agents/codex-app-server-runtime.d.ts.map +1 -1
  5. package/dist/agents/codex-app-server-runtime.js +4 -3
  6. package/dist/agents/codex-app-server-runtime.js.map +1 -1
  7. package/dist/agents/model-control-files.d.ts +10 -4
  8. package/dist/agents/model-control-files.d.ts.map +1 -1
  9. package/dist/agents/model-control-files.js +127 -79
  10. package/dist/agents/model-control-files.js.map +1 -1
  11. package/dist/agents/platform-spawn.d.ts +2 -0
  12. package/dist/agents/platform-spawn.d.ts.map +1 -0
  13. package/dist/agents/platform-spawn.js +4 -0
  14. package/dist/agents/platform-spawn.js.map +1 -0
  15. package/dist/agents/process-tree.d.ts +4 -0
  16. package/dist/agents/process-tree.d.ts.map +1 -0
  17. package/dist/agents/process-tree.js +46 -0
  18. package/dist/agents/process-tree.js.map +1 -0
  19. package/dist/agents/trusted-launcher.d.ts.map +1 -1
  20. package/dist/agents/trusted-launcher.js +7 -3
  21. package/dist/agents/trusted-launcher.js.map +1 -1
  22. package/dist/agents/windows-model-control-security.d.ts +4 -0
  23. package/dist/agents/windows-model-control-security.d.ts.map +1 -0
  24. package/dist/agents/windows-model-control-security.js +116 -0
  25. package/dist/agents/windows-model-control-security.js.map +1 -0
  26. package/dist/channels/botlink.d.ts.map +1 -1
  27. package/dist/channels/botlink.js +3 -1
  28. package/dist/channels/botlink.js.map +1 -1
  29. package/dist/cli/cmd-start.d.ts.map +1 -1
  30. package/dist/cli/cmd-start.js +12 -8
  31. package/dist/cli/cmd-start.js.map +1 -1
  32. package/dist/cli/cmd-stop.d.ts.map +1 -1
  33. package/dist/cli/cmd-stop.js +2 -1
  34. package/dist/cli/cmd-stop.js.map +1 -1
  35. package/dist/cli/cmd-update.d.ts +1 -0
  36. package/dist/cli/cmd-update.d.ts.map +1 -1
  37. package/dist/cli/cmd-update.js +3 -2
  38. package/dist/cli/cmd-update.js.map +1 -1
  39. package/dist/cli/temporary-files.d.ts +8 -0
  40. package/dist/cli/temporary-files.d.ts.map +1 -0
  41. package/dist/cli/temporary-files.js +43 -0
  42. package/dist/cli/temporary-files.js.map +1 -0
  43. package/dist/cli/update-check.d.ts.map +1 -1
  44. package/dist/cli/update-check.js +3 -2
  45. package/dist/cli/update-check.js.map +1 -1
  46. package/dist/cloud/main.js +2 -0
  47. package/dist/cloud/main.js.map +1 -1
  48. package/dist/config/attachment-handoff.d.ts.map +1 -1
  49. package/dist/config/attachment-handoff.js +12 -8
  50. package/dist/config/attachment-handoff.js.map +1 -1
  51. package/dist/config/paths.d.ts.map +1 -1
  52. package/dist/config/paths.js +2 -1
  53. package/dist/config/paths.js.map +1 -1
  54. package/dist/config/platform-paths.d.ts +6 -0
  55. package/dist/config/platform-paths.d.ts.map +1 -0
  56. package/dist/config/platform-paths.js +29 -0
  57. package/dist/config/platform-paths.js.map +1 -0
  58. package/dist/config/zod-schema.d.ts +2 -2
  59. package/dist/config/zod-schema.d.ts.map +1 -1
  60. package/dist/config/zod-schema.js +2 -1
  61. package/dist/config/zod-schema.js.map +1 -1
  62. package/dist/runtime-activity-snapshot.d.ts.map +1 -1
  63. package/dist/runtime-activity-snapshot.js +2 -0
  64. package/dist/runtime-activity-snapshot.js.map +1 -1
  65. package/package.json +7 -3
  66. package/scripts/windows-smoke.mjs +98 -0
@@ -2,100 +2,148 @@ import { constants } from 'node:fs';
2
2
  import { lstat, mkdir, open, realpath, rename, unlink } from 'node:fs/promises';
3
3
  import { dirname, resolve } from 'node:path';
4
4
  import { randomUUID } from 'node:crypto';
5
+ import { ensureWindowsModelControlSecurity, sameWindowsModelControlPath } from './windows-model-control-security.js';
5
6
  const MAX_MODEL_CONTROL_FILE_BYTES = 64 * 1024;
6
7
  function expectedUid() {
7
8
  return typeof process.geteuid === 'function' ? process.geteuid() : typeof process.getuid === 'function' ? process.getuid() : undefined;
8
9
  }
9
- export async function ensureSecureModelControlDirectory(path) {
10
- const directory = resolve(path);
11
- await mkdir(directory, { recursive: true, mode: 0o700 });
12
- const info = await lstat(directory);
13
- if (!info.isDirectory() || info.isSymbolicLink())
14
- throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY');
15
- const uid = expectedUid();
16
- if (uid !== undefined && info.uid !== uid)
17
- throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_OWNER');
18
- if ((info.mode & 0o022) !== 0)
19
- throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_MODE');
20
- if (await realpath(directory) !== directory)
21
- throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_PATH');
22
- }
23
- async function validateOpenFile(file) {
24
- const info = await file.stat();
25
- if (!info.isFile() || info.isSymbolicLink())
26
- throw new Error('INSECURE_MODEL_CONTROL_FILE_TYPE');
27
- const uid = expectedUid();
28
- if (uid !== undefined && info.uid !== uid)
29
- throw new Error('INSECURE_MODEL_CONTROL_FILE_OWNER');
30
- if ((info.mode & 0o777) !== 0o600)
31
- throw new Error('INSECURE_MODEL_CONTROL_FILE_MODE');
32
- if (info.size > MAX_MODEL_CONTROL_FILE_BYTES)
33
- throw new Error('MODEL_CONTROL_FILE_TOO_LARGE');
34
- }
35
- export async function readSecureModelControlFile(path) {
36
- await ensureSecureModelControlDirectory(dirname(path));
37
- const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
38
- try {
39
- await validateOpenFile(file);
40
- return await file.readFile('utf8');
41
- }
42
- finally {
43
- await file.close();
10
+ // The explicit platform/security dependencies let non-Windows CI exercise the
11
+ // complete Windows IO lifecycle without claiming native ACL/OS acceptance.
12
+ export function createModelControlFileAccess({ platform = process.platform, windowsSecurity = ensureWindowsModelControlSecurity, } = {}) {
13
+ const windows = platform === 'win32';
14
+ const noFollow = windows ? 0 : constants.O_NOFOLLOW;
15
+ async function ensureSecureModelControlDirectory(path) {
16
+ const directory = resolve(path);
17
+ await mkdir(directory, { recursive: true, mode: 0o700 });
18
+ const info = await lstat(directory);
19
+ if (!info.isDirectory() || info.isSymbolicLink())
20
+ throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY');
21
+ const uid = expectedUid();
22
+ if (!windows && uid !== undefined && info.uid !== uid)
23
+ throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_OWNER');
24
+ if (!windows && (info.mode & 0o022) !== 0)
25
+ throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_MODE');
26
+ const canonical = await realpath(directory);
27
+ if (windows ? !sameWindowsModelControlPath(canonical, directory) : canonical !== directory)
28
+ throw new Error('INSECURE_MODEL_CONTROL_DIRECTORY_PATH');
29
+ if (windows)
30
+ await windowsSecurity(directory, 'directory');
44
31
  }
45
- }
46
- async function syncDirectory(path) {
47
- const directory = await open(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
48
- try {
49
- await directory.sync();
50
- }
51
- finally {
52
- await directory.close();
32
+ async function validateOpenFile(file, path) {
33
+ const info = await file.stat();
34
+ if (!info.isFile() || info.isSymbolicLink())
35
+ throw new Error('INSECURE_MODEL_CONTROL_FILE_TYPE');
36
+ const uid = expectedUid();
37
+ if (!windows && uid !== undefined && info.uid !== uid)
38
+ throw new Error('INSECURE_MODEL_CONTROL_FILE_OWNER');
39
+ if (!windows && (info.mode & 0o777) !== 0o600)
40
+ throw new Error('INSECURE_MODEL_CONTROL_FILE_MODE');
41
+ if (info.size > MAX_MODEL_CONTROL_FILE_BYTES)
42
+ throw new Error('MODEL_CONTROL_FILE_TOO_LARGE');
43
+ if (windows) {
44
+ const entry = await lstat(path);
45
+ if (!entry.isFile() || entry.isSymbolicLink() || entry.dev !== info.dev || entry.ino !== info.ino || entry.nlink !== 1)
46
+ throw new Error('INSECURE_MODEL_CONTROL_FILE_TYPE');
47
+ const canonical = await realpath(path);
48
+ if (!sameWindowsModelControlPath(canonical, resolve(path)))
49
+ throw new Error('INSECURE_MODEL_CONTROL_FILE_PATH');
50
+ await windowsSecurity(path, 'file');
51
+ }
53
52
  }
54
- }
55
- export async function createSecureModelControlFile(path, contents) {
56
- await ensureSecureModelControlDirectory(dirname(path));
57
- const file = await open(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
58
- try {
59
- await validateOpenFile(file);
60
- await file.writeFile(contents);
61
- await validateOpenFile(file);
62
- await file.sync();
53
+ async function openExisting(path) {
54
+ // O_NOFOLLOW is unavailable on Windows. Check before opening, then compare
55
+ // the opened file's identity to lstat before reading any secret bytes.
56
+ if (windows) {
57
+ const entry = await lstat(path);
58
+ if (!entry.isFile() || entry.isSymbolicLink())
59
+ throw new Error('INSECURE_MODEL_CONTROL_FILE_TYPE');
60
+ }
61
+ return open(path, constants.O_RDONLY | noFollow);
63
62
  }
64
- finally {
65
- await file.close();
63
+ async function readSecureModelControlFile(path) {
64
+ await ensureSecureModelControlDirectory(dirname(path));
65
+ const file = await openExisting(path);
66
+ try {
67
+ await validateOpenFile(file, path);
68
+ return await file.readFile('utf8');
69
+ }
70
+ finally {
71
+ await file.close();
72
+ }
66
73
  }
67
- await syncDirectory(dirname(path));
68
- }
69
- export async function writeSecureModelControlFile(path, contents) {
70
- await ensureSecureModelControlDirectory(dirname(path));
71
- try {
72
- const existing = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
74
+ async function syncDirectory(path) {
75
+ // Node cannot open/fsync a Windows directory with these POSIX flags.
76
+ // File contents are still fsynced before close/atomic rename below.
77
+ if (windows)
78
+ return;
79
+ const directory = await open(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
73
80
  try {
74
- await validateOpenFile(existing);
81
+ await directory.sync();
75
82
  }
76
83
  finally {
77
- await existing.close();
84
+ await directory.close();
78
85
  }
79
86
  }
80
- catch (error) {
81
- if (error?.code !== 'ENOENT')
87
+ async function createSecureModelControlFile(path, contents) {
88
+ if (Buffer.byteLength(contents, 'utf8') > MAX_MODEL_CONTROL_FILE_BYTES)
89
+ throw new Error('MODEL_CONTROL_FILE_TOO_LARGE');
90
+ await ensureSecureModelControlDirectory(dirname(path));
91
+ const file = await open(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow, 0o600);
92
+ try {
93
+ await validateOpenFile(file, path);
94
+ await file.writeFile(contents);
95
+ await validateOpenFile(file, path);
96
+ await file.sync();
97
+ }
98
+ catch (error) {
99
+ await file.close().catch(() => undefined);
100
+ await unlink(path).catch(() => undefined);
82
101
  throw error;
102
+ }
103
+ await file.close();
104
+ await syncDirectory(dirname(path));
83
105
  }
84
- const temporaryPath = `${path}.${randomUUID()}.tmp`;
85
- const file = await open(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
86
- try {
87
- await validateOpenFile(file);
88
- await file.writeFile(contents);
89
- await validateOpenFile(file);
90
- await file.sync();
91
- }
92
- catch (error) {
93
- await file.close().catch(() => undefined);
94
- await unlink(temporaryPath).catch(() => undefined);
95
- throw error;
106
+ async function writeSecureModelControlFile(path, contents) {
107
+ if (Buffer.byteLength(contents, 'utf8') > MAX_MODEL_CONTROL_FILE_BYTES)
108
+ throw new Error('MODEL_CONTROL_FILE_TOO_LARGE');
109
+ await ensureSecureModelControlDirectory(dirname(path));
110
+ try {
111
+ const existing = await openExisting(path);
112
+ try {
113
+ await validateOpenFile(existing, path);
114
+ }
115
+ finally {
116
+ await existing.close();
117
+ }
118
+ }
119
+ catch (error) {
120
+ if (error?.code !== 'ENOENT')
121
+ throw error;
122
+ }
123
+ const temporaryPath = `${path}.${randomUUID()}.tmp`;
124
+ const file = await open(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow, 0o600);
125
+ try {
126
+ await validateOpenFile(file, temporaryPath);
127
+ await file.writeFile(contents);
128
+ await validateOpenFile(file, temporaryPath);
129
+ await file.sync();
130
+ }
131
+ catch (error) {
132
+ await file.close().catch(() => undefined);
133
+ await unlink(temporaryPath).catch(() => undefined);
134
+ throw error;
135
+ }
136
+ await file.close();
137
+ try {
138
+ await rename(temporaryPath, path);
139
+ }
140
+ catch (error) {
141
+ await unlink(temporaryPath).catch(() => undefined);
142
+ throw error;
143
+ }
144
+ await syncDirectory(dirname(path));
96
145
  }
97
- await file.close();
98
- await rename(temporaryPath, path);
99
- await syncDirectory(dirname(path));
146
+ return { ensureSecureModelControlDirectory, readSecureModelControlFile, createSecureModelControlFile, writeSecureModelControlFile };
100
147
  }
148
+ export const { ensureSecureModelControlDirectory, readSecureModelControlFile, createSecureModelControlFile, writeSecureModelControlFile, } = createModelControlFileAccess();
101
149
  //# sourceMappingURL=model-control-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-control-files.js","sourceRoot":"","sources":["../../src/agents/model-control-files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model-control-files.js","sourceRoot":"","sources":["../../src/agents/model-control-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const spawn: typeof import("child_process").spawn;
2
+ //# sourceMappingURL=platform-spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-spawn.d.ts","sourceRoot":"","sources":["../../src/agents/platform-spawn.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK,sCAAmB,CAAA"}
@@ -0,0 +1,4 @@
1
+ import crossSpawn from 'cross-spawn';
2
+ // Retain Node's overloads/stream types and cross-spawn's Windows shim escaping.
3
+ export const spawn = crossSpawn.spawn;
4
+ //# sourceMappingURL=platform-spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-spawn.js","sourceRoot":"","sources":["../../src/agents/platform-spawn.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAA;AAEpC,gFAAgF;AAChF,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ export declare function terminateProcess(pid: number, signal?: NodeJS.Signals, platform?: NodeJS.Platform): Promise<void>;
3
+ export declare function terminateChildProcess(child: ChildProcess): void;
4
+ //# sourceMappingURL=process-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-tree.d.ts","sourceRoot":"","sources":["../../src/agents/process-tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGhE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,OAAmB,EAAE,QAAQ,kBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5H;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAM/D"}
@@ -0,0 +1,46 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { win32 } from 'node:path';
3
+ export function terminateProcess(pid, signal = 'SIGTERM', platform = process.platform) {
4
+ if (!Number.isSafeInteger(pid) || pid <= 0)
5
+ return Promise.reject(new Error('Invalid owned process id'));
6
+ if (platform !== 'win32') {
7
+ try {
8
+ process.kill(pid, signal);
9
+ return Promise.resolve();
10
+ }
11
+ catch (error) {
12
+ return Promise.reject(error);
13
+ }
14
+ }
15
+ // Node kills only the cmd.exe shim on Windows; taskkill /T also stops the
16
+ // owned CLI descendant. Never pass a process name, wildcard, or a shell.
17
+ return new Promise((resolve, reject) => {
18
+ execFile(win32.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'taskkill.exe'), ['/PID', String(pid), '/T', '/F'], { windowsHide: true }, error => {
19
+ if (!error) {
20
+ resolve();
21
+ return;
22
+ }
23
+ try {
24
+ process.kill(pid, 0);
25
+ }
26
+ catch (gone) {
27
+ reject(gone);
28
+ return;
29
+ }
30
+ reject(error);
31
+ });
32
+ });
33
+ }
34
+ export function terminateChildProcess(child) {
35
+ if (child.exitCode !== null || child.signalCode !== null)
36
+ return;
37
+ if (process.platform !== 'win32' || !child.pid) {
38
+ child.kill();
39
+ return;
40
+ }
41
+ void terminateProcess(child.pid).catch(() => {
42
+ if (child.exitCode === null && child.signalCode === null)
43
+ child.kill();
44
+ });
45
+ }
46
+ //# sourceMappingURL=process-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-tree.js","sourceRoot":"","sources":["../../src/agents/process-tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAqB,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAEjC,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,SAAyB,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ;IAC3G,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAA;IACxG,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,IAAI,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAAC,CAAC;IAC5G,CAAC;IACD,0EAA0E;IAC1E,yEAAyE;IACzE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,EAAE;YAC1J,IAAI,CAAC,KAAK,EAAE,CAAC;gBAAC,OAAO,EAAE,CAAC;gBAAC,OAAM;YAAC,CAAC;YACjC,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAAC,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC;gBAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAAC,OAAM;YAAC,CAAC;YAClE,MAAM,CAAC,KAAK,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAmB;IACvD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,OAAM;IAChE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAAC,OAAM;IAAC,CAAC;IACxE,KAAK,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QAC1C,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,EAAE,CAAA;IACxE,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"trusted-launcher.d.ts","sourceRoot":"","sources":["../../src/agents/trusted-launcher.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CACxB,GAAG,YAAY,CAoBf"}
1
+ {"version":3,"file":"trusted-launcher.d.ts","sourceRoot":"","sources":["../../src/agents/trusted-launcher.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CACxB,GAAG,YAAY,CAuBf"}
@@ -1,17 +1,21 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
- import { basename, relative, resolve } from 'node:path';
2
+ import { basename, relative, resolve, sep } from 'node:path';
3
3
  export function resolveTrustedSpawn(input) {
4
4
  const cwd = resolve(input.cwd ?? process.cwd());
5
5
  const launcherSocket = process.env.RUNTIME_LAUNCHER_SOCKET;
6
6
  if (!launcherSocket) {
7
- return { command: input.command, args: input.args, cwd, env: input.env ?? process.env, shell: process.platform === 'win32' };
7
+ // Consumers use cross-spawn for Windows npm shims. Enabling shell here
8
+ // would bypass its escaping and break paths/user arguments containing spaces.
9
+ return { command: input.command, args: input.args, cwd, env: input.env ?? process.env, shell: false };
8
10
  }
11
+ if (process.platform === 'win32')
12
+ throw new Error('TRUSTED_RUNTIME_LAUNCHER_REQUIRES_LINUX');
9
13
  const profile = profileForCommand(input.command);
10
14
  if (!profile)
11
15
  throw new Error('CLI executable is not authorized by the trusted launcher');
12
16
  const workspace = resolve(process.env.WORKSPACE_ROOT ?? '/workspace');
13
17
  const cwdRel = relative(workspace, cwd) || '.';
14
- if (cwdRel === '..' || cwdRel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
18
+ if (cwdRel === '..' || cwdRel.startsWith(`..${sep}`)) {
15
19
  throw new Error('CLI working directory is outside the trusted workspace');
16
20
  }
17
21
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"trusted-launcher.js","sourceRoot":"","sources":["../../src/agents/trusted-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAUvD,MAAM,UAAU,mBAAmB,CAAC,KAKnC;IACC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC/C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAA;IAC1D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAA;IAC9H,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IACzF,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,YAAY,CAAC,CAAA;IACrE,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,GAAG,CAAA;IAC9C,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC;IACD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,uBAAuB;QACvE,IAAI,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC;QAC9F,GAAG,EAAE,SAAS;QACd,GAAG,EAAE,wBAAwB,CAAC,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC;QACxD,KAAK,EAAE,KAAK;KACb,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,MAAyB,EAAE;IACrE,MAAM,cAAc,GAAG,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAA;IACjD,IAAI,CAAC,cAAc;QAAE,OAAO,UAAU,EAAE,CAAA;IACxC,MAAM,SAAS,GAAG,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAA;IAC5C,MAAM,QAAQ,GAAG,SAAS;QACxB,CAAC,CAAC,GAAG,OAAO,KAAK,cAAc,KAAK,SAAS,EAAE;QAC/C,CAAC,CAAC,GAAG,OAAO,KAAK,cAAc,EAAE,CAAA;IACnC,OAAO,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAA;AAClF,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,QAAQ,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,KAAK,OAAO,CAAC,CAAC,OAAO,UAAU,CAAA;QAC/B,KAAK,QAAQ,CAAC,CAAC,OAAO,WAAW,CAAA;QACjC,OAAO,CAAC,CAAC,OAAO,IAAI,CAAA;IACtB,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,MAAc,EAAE,SAA4B,EAAE;IAC9E,MAAM,GAAG,GAAsB;QAC7B,IAAI,EAAE,uBAAuB;QAC7B,IAAI,EAAE,8BAA8B;QACpC,uBAAuB,EAAE,MAAM;KAChC,CAAA;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACnD,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACvF,IAAI,MAAM,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"trusted-launcher.js","sourceRoot":"","sources":["../../src/agents/trusted-launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function sameWindowsModelControlPath(left: string, right: string): boolean;
2
+ export declare function validateWindowsModelControlAcl(value: unknown, kind?: 'directory' | 'file'): void;
3
+ export declare function ensureWindowsModelControlSecurity(path: string, kind?: 'directory' | 'file'): Promise<void>;
4
+ //# sourceMappingURL=windows-model-control-security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-model-control-security.d.ts","sourceRoot":"","sources":["../../src/agents/windows-model-control-security.ts"],"names":[],"mappings":"AAuDA,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEhF;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAE,WAAW,GAAG,MAAe,GAAG,IAAI,CA+BxG;AAED,wBAAsB,iCAAiC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAW,GAAG,MAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBxH"}
@@ -0,0 +1,116 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { win32 } from 'node:path';
3
+ import { promisify } from 'node:util';
4
+ const execute = promisify(execFile);
5
+ const TRUSTED_SYSTEM_SIDS = new Set(['S-1-5-18', 'S-1-5-32-544']); // SYSTEM, Administrators
6
+ // Use SIDs rather than localized account names. Inspect inherited ACEs too; a
7
+ // Unix mode returned by stat on Windows says nothing about the actual DACL.
8
+ const INSPECT_ACL = `
9
+ $ErrorActionPreference = 'Stop'
10
+ $item = Get-Item -LiteralPath $env:AGENTS_BRIDGE_ACL_TARGET -Force
11
+ $cursor = $item
12
+ while ($null -ne $cursor) {
13
+ if (($cursor.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) { throw 'MODEL_CONTROL_REPARSE_POINT' }
14
+ if ($cursor -is [IO.DirectoryInfo]) { $cursor = $cursor.Parent } else { $cursor = $cursor.Directory }
15
+ }
16
+ $acl = Get-Acl -LiteralPath $env:AGENTS_BRIDGE_ACL_TARGET
17
+ $current = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
18
+ $owner = $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value
19
+ if ($env:AGENTS_BRIDGE_ACL_KIND -eq 'file') {
20
+ if ($item -isnot [IO.FileInfo] -or $owner -notin @($current, 'S-1-5-18', 'S-1-5-32-544')) { throw 'MODEL_CONTROL_UNTRUSTED_OWNER' }
21
+ # Only model-control files are privatized, before any secret bytes are read
22
+ # or written. Never change a parent directory or a user's workspace ACL.
23
+ $needsPrivacy = $false
24
+ foreach ($rule in @($acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier]))) {
25
+ if ($rule.AccessControlType -eq [Security.AccessControl.AccessControlType]::Allow -and $rule.IdentityReference.Value -notin @($current, 'S-1-5-18', 'S-1-5-32-544') -and [long]$rule.FileSystemRights -ne 0) { $needsPrivacy = $true }
26
+ }
27
+ if ($needsPrivacy) {
28
+ $acl.SetAccessRuleProtection($true, $false)
29
+ foreach ($rule in @($acl.GetAccessRules($true, $false, [Security.Principal.SecurityIdentifier]))) { [void]$acl.RemoveAccessRuleSpecific($rule) }
30
+ foreach ($sid in @($current, 'S-1-5-18', 'S-1-5-32-544')) {
31
+ $identity = [Security.Principal.SecurityIdentifier]::new($sid)
32
+ $rule = [Security.AccessControl.FileSystemAccessRule]::new($identity, [Security.AccessControl.FileSystemRights]::FullControl, [Security.AccessControl.AccessControlType]::Allow)
33
+ [void]$acl.AddAccessRule($rule)
34
+ }
35
+ Set-Acl -LiteralPath $env:AGENTS_BRIDGE_ACL_TARGET -AclObject $acl
36
+ $acl = Get-Acl -LiteralPath $env:AGENTS_BRIDGE_ACL_TARGET
37
+ }
38
+ }
39
+ $rules = @($acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier]) | ForEach-Object {
40
+ @{
41
+ sid = $_.IdentityReference.Value
42
+ allow = ($_.AccessControlType -eq [Security.AccessControl.AccessControlType]::Allow)
43
+ rights = [long]$_.FileSystemRights
44
+ inheritOnly = (($_.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -ne 0)
45
+ }
46
+ })
47
+ @{
48
+ currentSid = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
49
+ ownerSid = $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value
50
+ rules = $rules
51
+ } | ConvertTo-Json -Depth 4 -Compress
52
+ `;
53
+ export function sameWindowsModelControlPath(left, right) {
54
+ return win32.normalize(left).toLowerCase() === win32.normalize(right).toLowerCase();
55
+ }
56
+ export function validateWindowsModelControlAcl(value, kind = 'file') {
57
+ const invalid = (detail = 'invalid ACL data') => new Error(`INSECURE_MODEL_CONTROL_WINDOWS_ACL: ${kind}: ${detail}`);
58
+ if (!value || typeof value !== 'object')
59
+ throw invalid();
60
+ const acl = value;
61
+ if (typeof acl.currentSid !== 'string' || !/^S-1-\d+(?:-\d+)+$/.test(acl.currentSid)
62
+ || typeof acl.ownerSid !== 'string' || !Array.isArray(acl.rules))
63
+ throw invalid();
64
+ const trusted = new Set([acl.currentSid, ...TRUSTED_SYSTEM_SIDS]);
65
+ if (!trusted.has(acl.ownerSid))
66
+ throw invalid(`untrusted owner ${acl.ownerSid}`);
67
+ let effectiveAllow = false;
68
+ for (const entry of acl.rules) {
69
+ if (!entry || typeof entry !== 'object')
70
+ throw invalid();
71
+ const rule = entry;
72
+ if (typeof rule.sid !== 'string' || typeof rule.allow !== 'boolean'
73
+ || typeof rule.inheritOnly !== 'boolean' || typeof rule.rights !== 'number'
74
+ || !Number.isSafeInteger(rule.rights) || rule.rights < -0x80000000 || rule.rights > 0xffffffff)
75
+ throw invalid();
76
+ if (!rule.allow || rule.rights === 0)
77
+ continue;
78
+ // Inherit-only grants still expose newly created state/temporary files.
79
+ if (!trusted.has(rule.sid) && !(rule.sid === 'S-1-3-0' && rule.inheritOnly)) {
80
+ // Match the POSIX directory policy: listing/traversal is safe; creating,
81
+ // replacing, deleting or changing permissions is not. Inherited file
82
+ // grants are removed by the private-file policy before accessing bytes.
83
+ // ReadData/ReadEA/Execute/ReadAttributes/ReadControl/Synchronize plus
84
+ // GenericRead/GenericExecute. Reject unknown rights as well as writes.
85
+ const outsideReadRights = (rule.rights >>> 0) & ~0xa01200a9;
86
+ if (kind === 'file' || (!rule.inheritOnly && outsideReadRights !== 0))
87
+ throw invalid(`unsafe allow ${rule.sid} rights=${rule.rights}`);
88
+ }
89
+ if (!rule.inheritOnly)
90
+ effectiveAllow = true;
91
+ }
92
+ // Also rejects empty/missing and null DACL representations rather than
93
+ // treating "no rules returned" as proof of privacy.
94
+ if (!effectiveAllow)
95
+ throw invalid();
96
+ }
97
+ export async function ensureWindowsModelControlSecurity(path, kind = 'file') {
98
+ const executable = win32.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
99
+ let snapshot;
100
+ try {
101
+ const { stdout } = await execute(executable, [
102
+ '-NoLogo', '-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(INSPECT_ACL, 'utf16le').toString('base64'),
103
+ ], {
104
+ env: { ...process.env, AGENTS_BRIDGE_ACL_TARGET: path, AGENTS_BRIDGE_ACL_KIND: kind },
105
+ windowsHide: true, timeout: 10_000, maxBuffer: 128 * 1024,
106
+ });
107
+ snapshot = JSON.parse(stdout.replace(/^\uFEFF/, '').trim());
108
+ }
109
+ catch {
110
+ // Do not include shell output, environment, or a control-file path in logs.
111
+ // Fail closed if PowerShell/ACL inspection is unavailable.
112
+ throw new Error('MODEL_CONTROL_WINDOWS_ACL_UNAVAILABLE: Windows PowerShell ACL inspection failed');
113
+ }
114
+ validateWindowsModelControlAcl(snapshot, kind);
115
+ }
116
+ //# sourceMappingURL=windows-model-control-security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-model-control-security.js","sourceRoot":"","sources":["../../src/agents/windows-model-control-security.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"botlink.d.ts","sourceRoot":"","sources":["../../src/channels/botlink.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAmB,MAAM,mBAAmB,CAAA;AAgBvF,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAmDD,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM;CAIjB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;gBAD7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,SAAS,EACtC,MAAM,EAAE,MAAM;CAIjB;AAED,KAAK,aAAa,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAiBvE,qBAAa,cAAe,YAAW,aAAa;IAMtC,OAAO,CAAC,QAAQ,CAAC,IAAI;IALjC,EAAE,SAAY;IAEd,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,GAAG,CAA8B;gBAEZ,IAAI,GAAE,aAAqB;IAElD,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB7D,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B9D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAejB,YAAY;YAoCZ,cAAc;YAQd,aAAa;IAsB3B,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,qBAAqB;YAQf,WAAW;YAYX,QAAQ;IA2ItB,OAAO,CAAC,gBAAgB;YAwBV,kBAAkB;YAmBlB,cAAc;IAS5B,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,kBAAkB;YAqBZ,OAAO;YAmDP,iBAAiB;YAwEjB,mBAAmB;YAoCnB,YAAY;IA8B1B,OAAO,CAAC,mBAAmB;CAY5B;AAuCD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAY5F"}
1
+ {"version":3,"file":"botlink.d.ts","sourceRoot":"","sources":["../../src/channels/botlink.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAmB,MAAM,mBAAmB,CAAA;AAgBvF,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAmDD,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM;CAIjB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;gBAD7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,SAAS,EACtC,MAAM,EAAE,MAAM;CAIjB;AAED,KAAK,aAAa,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAiBvE,qBAAa,cAAe,YAAW,aAAa;IAMtC,OAAO,CAAC,QAAQ,CAAC,IAAI;IALjC,EAAE,SAAY;IAEd,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,GAAG,CAA8B;gBAEZ,IAAI,GAAE,aAAqB;IAElD,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB7D,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B9D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAejB,YAAY;YAoCZ,cAAc;YAQd,aAAa;IAsB3B,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,qBAAqB;YAQf,WAAW;YAYX,QAAQ;IA2ItB,OAAO,CAAC,gBAAgB;YAwBV,kBAAkB;YAmBlB,cAAc;IAS5B,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,kBAAkB;YAqBZ,OAAO;YAmDP,iBAAiB;YAwEjB,mBAAmB;YAoCnB,YAAY;IA+B1B,OAAO,CAAC,mBAAmB;CAY5B;AAuCD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAY5F"}
@@ -4,6 +4,7 @@ import { mkdirSync, renameSync, rmSync } from 'node:fs';
4
4
  import { randomUUID } from 'node:crypto';
5
5
  import { ManagedReceipts } from './managed-receipts.js';
6
6
  import { basename, join } from 'node:path';
7
+ import { assertAttachmentStorageId, safeAttachmentFileName } from '../config/platform-paths.js';
7
8
  import { createWriteStream } from 'node:fs';
8
9
  import { pipeline } from 'node:stream/promises';
9
10
  import { registerChannel } from './registry.js';
@@ -487,6 +488,7 @@ export class BotlinkChannel {
487
488
  return attachments;
488
489
  }
489
490
  async downloadFile(account, fileId, fileName, signal) {
491
+ assertAttachmentStorageId(String(fileId));
490
492
  const fileInfo = await this.request(account, 'getFile', { file_id: fileId }, signal);
491
493
  const baseUrl = account.config.gateway_url.replace(/\/+$/, '');
492
494
  const fileUrl = `${baseUrl}/file/bot${account.config.bot_token}/${fileInfo.file_path.replace(/^\/+/, '')}`;
@@ -560,7 +562,7 @@ export function resolveTelegramSenderName(user) {
560
562
  return username || undefined;
561
563
  }
562
564
  function sanitizeFileName(fileName) {
563
- return fileName.replace(/[^a-zA-Z0-9._-]/g, '_');
565
+ return safeAttachmentFileName(fileName);
564
566
  }
565
567
  function getNextOffset(update) {
566
568
  return Number.isInteger(update.update_id) ? Number(update.update_id) + 1 : undefined;