@js-eyes/protocol 2.8.1 → 2.8.2

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/index.js CHANGED
@@ -1,269 +1,269 @@
1
- 'use strict';
2
-
3
- const pkg = require('./package.json');
4
-
5
- const DEFAULT_SERVER_HOST = 'localhost';
6
- const DEFAULT_SERVER_PORT = 18080;
7
- const DEFAULT_REQUEST_TIMEOUT_SECONDS = 1800;
8
- const REQUEST_TIMEOUT_MS = DEFAULT_REQUEST_TIMEOUT_SECONDS * 1000;
9
- const PROTOCOL_VERSION = '1.0';
10
- const PACKAGE_VERSION = pkg.version;
11
- const SKILLS_REGISTRY_URL = 'https://js-eyes.com/skills.json';
12
- const RELEASE_BASE_URL = 'https://github.com/imjszhang/js-eyes/releases/download';
13
-
14
- const FORWARDABLE_ACTIONS = [
15
- 'open_url',
16
- 'close_tab',
17
- 'get_html',
18
- 'execute_script',
19
- 'inject_css',
20
- 'get_cookies',
21
- 'get_cookies_by_domain',
22
- 'get_page_info',
23
- 'upload_file_to_tab',
24
- ];
25
-
26
- const SENSITIVE_TOOL_NAMES = Object.freeze([
27
- 'browser/execute-script',
28
- 'browser/get-cookies',
29
- 'browser/get-cookies-by-domain',
30
- 'browser/inject-css',
31
- 'browser/upload-file',
32
- 'skills/plan-install',
33
- ]);
34
-
35
- const LOOPBACK_HOSTS = Object.freeze(['localhost', '127.0.0.1', '::1', '::ffff:127.0.0.1', '0:0:0:0:0:0:0:1']);
36
-
37
- const DEFAULT_ALLOWED_ORIGINS = Object.freeze([
38
- 'chrome-extension://*',
39
- 'moz-extension://*',
40
- 'http://localhost',
41
- 'https://localhost',
42
- 'http://127.0.0.1',
43
- 'https://127.0.0.1',
44
- 'http://[::1]',
45
- 'https://[::1]',
46
- ]);
47
-
48
- const DEFAULT_TASK_ORIGIN_CONFIG = Object.freeze({
49
- enabled: true,
50
- sources: ['user-message', 'skill-platforms', 'active-tab', 'fetched-links'],
51
- });
52
-
53
- const DEFAULT_TAINT_CONFIG = Object.freeze({
54
- enabled: true,
55
- mode: 'canary+substring',
56
- minValueLength: 6,
57
- });
58
-
59
- const DEFAULT_PROFILE_CONFIG = Object.freeze({
60
- default: 'full',
61
- });
62
-
63
- const POLICY_ENFORCEMENT_LEVELS = Object.freeze(['off', 'soft', 'strict']);
64
-
65
- const DEFAULT_SECURITY_CONFIG = Object.freeze({
66
- allowAnonymous: false,
67
- allowedOrigins: DEFAULT_ALLOWED_ORIGINS.slice(),
68
- allowRemoteBind: false,
69
- allowRawEval: false,
70
- requireLockfile: true,
71
- // 2.6.2 opt-in integrity checks for extraSkillDirs. Default false keeps
72
- // behaviour identical to 2.6.1; flip to true (or run
73
- // `js-eyes skills link`/`relink` with the flag enabled) to start verifying.
74
- verifyExtraSkillDirs: false,
75
- enforcement: 'soft',
76
- taskOrigin: { ...DEFAULT_TASK_ORIGIN_CONFIG, sources: DEFAULT_TASK_ORIGIN_CONFIG.sources.slice() },
77
- egressAllowlist: [],
78
- taint: { ...DEFAULT_TAINT_CONFIG },
79
- profile: { ...DEFAULT_PROFILE_CONFIG },
80
- toolPolicies: {
81
- 'browser/execute-script': 'confirm',
82
- 'browser/get-cookies': 'confirm',
83
- 'browser/get-cookies-by-domain': 'confirm',
84
- 'browser/inject-css': 'confirm',
85
- 'browser/upload-file': 'confirm',
86
- 'skills/plan-install': 'confirm',
87
- },
88
- sensitiveCookieDomains: [
89
- 'bank',
90
- 'paypal.com',
91
- 'google.com',
92
- 'live.com',
93
- 'apple.com',
94
- 'icloud.com',
95
- 'aws.amazon.com',
96
- 'amazon.com',
97
- 'office.com',
98
- 'microsoft.com',
99
- 'github.com',
100
- ],
101
- });
102
-
103
- const WS_CLOSE_CODE_AUTH_REQUIRED = 4401;
104
- const WS_CLOSE_CODE_FORBIDDEN_ORIGIN = 4403;
105
-
106
- const COMPATIBILITY_MATRIX = Object.freeze({
107
- protocolVersion: PROTOCOL_VERSION,
108
- cliVersion: PACKAGE_VERSION,
109
- extensionVersion: PACKAGE_VERSION,
110
- serverCoreVersion: PACKAGE_VERSION,
111
- clientSdkVersion: PACKAGE_VERSION,
112
- openclawPluginVersion: PACKAGE_VERSION,
113
- skillClientSdkVersion: PACKAGE_VERSION,
114
- });
115
-
116
- function isLoopbackHost(host) {
117
- if (!host) return false;
118
- const normalized = String(host).toLowerCase();
119
- if (LOOPBACK_HOSTS.includes(normalized)) return true;
120
- if (normalized.startsWith('127.')) return true;
121
- if (normalized === '::ffff:127.0.0.1') return true;
122
- return false;
123
- }
124
-
125
- function normalizeOriginPattern(pattern) {
126
- if (!pattern) return null;
127
- const trimmed = String(pattern).trim().toLowerCase();
128
- if (!trimmed) return null;
129
- return trimmed.replace(/\/$/, '');
130
- }
131
-
132
- function matchesOriginPattern(origin, pattern) {
133
- if (!origin || !pattern) return false;
134
- const normOrigin = String(origin).trim().toLowerCase().replace(/\/$/, '');
135
- const normPattern = normalizeOriginPattern(pattern);
136
- if (!normPattern) return false;
137
- if (normPattern === '*') return true;
138
- if (normPattern.endsWith('://*')) {
139
- const scheme = normPattern.slice(0, -3);
140
- return normOrigin.startsWith(scheme);
141
- }
142
- if (normPattern.includes('*')) {
143
- const regex = new RegExp(
144
- '^' + normPattern.split('*').map(escapeRegex).join('.*') + '$',
145
- );
146
- return regex.test(normOrigin);
147
- }
148
- if (normOrigin === normPattern) return true;
149
- if (normOrigin.startsWith(normPattern + ':')) return true;
150
- if (normOrigin.startsWith(normPattern + '/')) return true;
151
- return false;
152
- }
153
-
154
- function escapeRegex(text) {
155
- return text.replace(/[.+^${}()|[\]\\]/g, '\\$&');
156
- }
157
-
158
- function isOriginAllowed(origin, allowedOrigins) {
159
- if (!Array.isArray(allowedOrigins)) return false;
160
- for (const pattern of allowedOrigins) {
161
- if (matchesOriginPattern(origin, pattern)) return true;
162
- }
163
- return false;
164
- }
165
-
166
- function resolveSecurityConfig(config = {}) {
167
- const raw = (config && config.security && typeof config.security === 'object')
168
- ? config.security
169
- : {};
170
- const merged = {
171
- ...DEFAULT_SECURITY_CONFIG,
172
- ...raw,
173
- allowedOrigins: Array.isArray(raw.allowedOrigins) && raw.allowedOrigins.length
174
- ? Array.from(new Set([
175
- ...DEFAULT_SECURITY_CONFIG.allowedOrigins,
176
- ...raw.allowedOrigins,
177
- ]))
178
- : DEFAULT_SECURITY_CONFIG.allowedOrigins.slice(),
179
- toolPolicies: {
180
- ...DEFAULT_SECURITY_CONFIG.toolPolicies,
181
- ...(raw.toolPolicies || {}),
182
- },
183
- sensitiveCookieDomains: Array.isArray(raw.sensitiveCookieDomains)
184
- ? raw.sensitiveCookieDomains.slice()
185
- : DEFAULT_SECURITY_CONFIG.sensitiveCookieDomains.slice(),
186
- enforcement: POLICY_ENFORCEMENT_LEVELS.includes(raw.enforcement)
187
- ? raw.enforcement
188
- : DEFAULT_SECURITY_CONFIG.enforcement,
189
- taskOrigin: mergeTaskOriginConfig(raw.taskOrigin),
190
- egressAllowlist: Array.isArray(raw.egressAllowlist)
191
- ? raw.egressAllowlist.slice()
192
- : DEFAULT_SECURITY_CONFIG.egressAllowlist.slice(),
193
- taint: mergeTaintConfig(raw.taint),
194
- profile: mergeProfileConfig(raw.profile),
195
- };
196
- if (process.env.JS_EYES_INSECURE === '1') {
197
- merged.allowAnonymous = true;
198
- }
199
- if (process.env.JS_EYES_ALLOW_REMOTE_BIND === '1') {
200
- merged.allowRemoteBind = true;
201
- }
202
- if (process.env.JS_EYES_POLICY_ENFORCEMENT && POLICY_ENFORCEMENT_LEVELS.includes(process.env.JS_EYES_POLICY_ENFORCEMENT)) {
203
- merged.enforcement = process.env.JS_EYES_POLICY_ENFORCEMENT;
204
- }
205
- return merged;
206
- }
207
-
208
- function mergeTaskOriginConfig(raw) {
209
- if (!raw || typeof raw !== 'object') {
210
- return { ...DEFAULT_TASK_ORIGIN_CONFIG, sources: DEFAULT_TASK_ORIGIN_CONFIG.sources.slice() };
211
- }
212
- return {
213
- enabled: typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULT_TASK_ORIGIN_CONFIG.enabled,
214
- sources: Array.isArray(raw.sources) && raw.sources.length
215
- ? raw.sources.slice()
216
- : DEFAULT_TASK_ORIGIN_CONFIG.sources.slice(),
217
- };
218
- }
219
-
220
- function mergeTaintConfig(raw) {
221
- if (!raw || typeof raw !== 'object') {
222
- return { ...DEFAULT_TAINT_CONFIG };
223
- }
224
- return {
225
- enabled: typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULT_TAINT_CONFIG.enabled,
226
- mode: typeof raw.mode === 'string' && raw.mode ? raw.mode : DEFAULT_TAINT_CONFIG.mode,
227
- minValueLength: Number.isFinite(raw.minValueLength) && raw.minValueLength > 0
228
- ? Math.floor(raw.minValueLength)
229
- : DEFAULT_TAINT_CONFIG.minValueLength,
230
- };
231
- }
232
-
233
- function mergeProfileConfig(raw) {
234
- if (!raw || typeof raw !== 'object') {
235
- return { ...DEFAULT_PROFILE_CONFIG };
236
- }
237
- return {
238
- default: typeof raw.default === 'string' && raw.default
239
- ? raw.default
240
- : DEFAULT_PROFILE_CONFIG.default,
241
- };
242
- }
243
-
244
- module.exports = {
245
- DEFAULT_ALLOWED_ORIGINS,
246
- DEFAULT_SECURITY_CONFIG,
247
- DEFAULT_TASK_ORIGIN_CONFIG,
248
- DEFAULT_TAINT_CONFIG,
249
- DEFAULT_PROFILE_CONFIG,
250
- POLICY_ENFORCEMENT_LEVELS,
251
- DEFAULT_SERVER_HOST,
252
- DEFAULT_SERVER_PORT,
253
- DEFAULT_REQUEST_TIMEOUT_SECONDS,
254
- LOOPBACK_HOSTS,
255
- REQUEST_TIMEOUT_MS,
256
- PROTOCOL_VERSION,
257
- PACKAGE_VERSION,
258
- SKILLS_REGISTRY_URL,
259
- RELEASE_BASE_URL,
260
- FORWARDABLE_ACTIONS,
261
- SENSITIVE_TOOL_NAMES,
262
- COMPATIBILITY_MATRIX,
263
- WS_CLOSE_CODE_AUTH_REQUIRED,
264
- WS_CLOSE_CODE_FORBIDDEN_ORIGIN,
265
- isLoopbackHost,
266
- isOriginAllowed,
267
- matchesOriginPattern,
268
- resolveSecurityConfig,
269
- };
1
+ 'use strict';
2
+
3
+ const pkg = require('./package.json');
4
+
5
+ const DEFAULT_SERVER_HOST = 'localhost';
6
+ const DEFAULT_SERVER_PORT = 18080;
7
+ const DEFAULT_REQUEST_TIMEOUT_SECONDS = 1800;
8
+ const REQUEST_TIMEOUT_MS = DEFAULT_REQUEST_TIMEOUT_SECONDS * 1000;
9
+ const PROTOCOL_VERSION = '1.0';
10
+ const PACKAGE_VERSION = pkg.version;
11
+ const SKILLS_REGISTRY_URL = 'https://js-eyes.com/skills.json';
12
+ const RELEASE_BASE_URL = 'https://github.com/imjszhang/js-eyes/releases/download';
13
+
14
+ const FORWARDABLE_ACTIONS = [
15
+ 'open_url',
16
+ 'close_tab',
17
+ 'get_html',
18
+ 'execute_script',
19
+ 'inject_css',
20
+ 'get_cookies',
21
+ 'get_cookies_by_domain',
22
+ 'get_page_info',
23
+ 'upload_file_to_tab',
24
+ ];
25
+
26
+ const SENSITIVE_TOOL_NAMES = Object.freeze([
27
+ 'browser/execute-script',
28
+ 'browser/get-cookies',
29
+ 'browser/get-cookies-by-domain',
30
+ 'browser/inject-css',
31
+ 'browser/upload-file',
32
+ 'skills/plan-install',
33
+ ]);
34
+
35
+ const LOOPBACK_HOSTS = Object.freeze(['localhost', '127.0.0.1', '::1', '::ffff:127.0.0.1', '0:0:0:0:0:0:0:1']);
36
+
37
+ const DEFAULT_ALLOWED_ORIGINS = Object.freeze([
38
+ 'chrome-extension://*',
39
+ 'moz-extension://*',
40
+ 'http://localhost',
41
+ 'https://localhost',
42
+ 'http://127.0.0.1',
43
+ 'https://127.0.0.1',
44
+ 'http://[::1]',
45
+ 'https://[::1]',
46
+ ]);
47
+
48
+ const DEFAULT_TASK_ORIGIN_CONFIG = Object.freeze({
49
+ enabled: true,
50
+ sources: ['user-message', 'skill-platforms', 'active-tab', 'fetched-links'],
51
+ });
52
+
53
+ const DEFAULT_TAINT_CONFIG = Object.freeze({
54
+ enabled: true,
55
+ mode: 'canary+substring',
56
+ minValueLength: 6,
57
+ });
58
+
59
+ const DEFAULT_PROFILE_CONFIG = Object.freeze({
60
+ default: 'full',
61
+ });
62
+
63
+ const POLICY_ENFORCEMENT_LEVELS = Object.freeze(['off', 'soft', 'strict']);
64
+
65
+ const DEFAULT_SECURITY_CONFIG = Object.freeze({
66
+ allowAnonymous: false,
67
+ allowedOrigins: DEFAULT_ALLOWED_ORIGINS.slice(),
68
+ allowRemoteBind: false,
69
+ allowRawEval: false,
70
+ requireLockfile: true,
71
+ // 2.6.2 opt-in integrity checks for extraSkillDirs. Default false keeps
72
+ // behaviour identical to 2.6.1; flip to true (or run
73
+ // `js-eyes skills link`/`relink` with the flag enabled) to start verifying.
74
+ verifyExtraSkillDirs: false,
75
+ enforcement: 'soft',
76
+ taskOrigin: { ...DEFAULT_TASK_ORIGIN_CONFIG, sources: DEFAULT_TASK_ORIGIN_CONFIG.sources.slice() },
77
+ egressAllowlist: [],
78
+ taint: { ...DEFAULT_TAINT_CONFIG },
79
+ profile: { ...DEFAULT_PROFILE_CONFIG },
80
+ toolPolicies: {
81
+ 'browser/execute-script': 'confirm',
82
+ 'browser/get-cookies': 'confirm',
83
+ 'browser/get-cookies-by-domain': 'confirm',
84
+ 'browser/inject-css': 'confirm',
85
+ 'browser/upload-file': 'confirm',
86
+ 'skills/plan-install': 'confirm',
87
+ },
88
+ sensitiveCookieDomains: [
89
+ 'bank',
90
+ 'paypal.com',
91
+ 'google.com',
92
+ 'live.com',
93
+ 'apple.com',
94
+ 'icloud.com',
95
+ 'aws.amazon.com',
96
+ 'amazon.com',
97
+ 'office.com',
98
+ 'microsoft.com',
99
+ 'github.com',
100
+ ],
101
+ });
102
+
103
+ const WS_CLOSE_CODE_AUTH_REQUIRED = 4401;
104
+ const WS_CLOSE_CODE_FORBIDDEN_ORIGIN = 4403;
105
+
106
+ const COMPATIBILITY_MATRIX = Object.freeze({
107
+ protocolVersion: PROTOCOL_VERSION,
108
+ cliVersion: PACKAGE_VERSION,
109
+ extensionVersion: PACKAGE_VERSION,
110
+ serverCoreVersion: PACKAGE_VERSION,
111
+ clientSdkVersion: PACKAGE_VERSION,
112
+ openclawPluginVersion: PACKAGE_VERSION,
113
+ skillClientSdkVersion: PACKAGE_VERSION,
114
+ });
115
+
116
+ function isLoopbackHost(host) {
117
+ if (!host) return false;
118
+ const normalized = String(host).toLowerCase();
119
+ if (LOOPBACK_HOSTS.includes(normalized)) return true;
120
+ if (normalized.startsWith('127.')) return true;
121
+ if (normalized === '::ffff:127.0.0.1') return true;
122
+ return false;
123
+ }
124
+
125
+ function normalizeOriginPattern(pattern) {
126
+ if (!pattern) return null;
127
+ const trimmed = String(pattern).trim().toLowerCase();
128
+ if (!trimmed) return null;
129
+ return trimmed.replace(/\/$/, '');
130
+ }
131
+
132
+ function matchesOriginPattern(origin, pattern) {
133
+ if (!origin || !pattern) return false;
134
+ const normOrigin = String(origin).trim().toLowerCase().replace(/\/$/, '');
135
+ const normPattern = normalizeOriginPattern(pattern);
136
+ if (!normPattern) return false;
137
+ if (normPattern === '*') return true;
138
+ if (normPattern.endsWith('://*')) {
139
+ const scheme = normPattern.slice(0, -3);
140
+ return normOrigin.startsWith(scheme);
141
+ }
142
+ if (normPattern.includes('*')) {
143
+ const regex = new RegExp(
144
+ '^' + normPattern.split('*').map(escapeRegex).join('.*') + '$',
145
+ );
146
+ return regex.test(normOrigin);
147
+ }
148
+ if (normOrigin === normPattern) return true;
149
+ if (normOrigin.startsWith(normPattern + ':')) return true;
150
+ if (normOrigin.startsWith(normPattern + '/')) return true;
151
+ return false;
152
+ }
153
+
154
+ function escapeRegex(text) {
155
+ return text.replace(/[.+^${}()|[\]\\]/g, '\\$&');
156
+ }
157
+
158
+ function isOriginAllowed(origin, allowedOrigins) {
159
+ if (!Array.isArray(allowedOrigins)) return false;
160
+ for (const pattern of allowedOrigins) {
161
+ if (matchesOriginPattern(origin, pattern)) return true;
162
+ }
163
+ return false;
164
+ }
165
+
166
+ function resolveSecurityConfig(config = {}) {
167
+ const raw = (config && config.security && typeof config.security === 'object')
168
+ ? config.security
169
+ : {};
170
+ const merged = {
171
+ ...DEFAULT_SECURITY_CONFIG,
172
+ ...raw,
173
+ allowedOrigins: Array.isArray(raw.allowedOrigins) && raw.allowedOrigins.length
174
+ ? Array.from(new Set([
175
+ ...DEFAULT_SECURITY_CONFIG.allowedOrigins,
176
+ ...raw.allowedOrigins,
177
+ ]))
178
+ : DEFAULT_SECURITY_CONFIG.allowedOrigins.slice(),
179
+ toolPolicies: {
180
+ ...DEFAULT_SECURITY_CONFIG.toolPolicies,
181
+ ...(raw.toolPolicies || {}),
182
+ },
183
+ sensitiveCookieDomains: Array.isArray(raw.sensitiveCookieDomains)
184
+ ? raw.sensitiveCookieDomains.slice()
185
+ : DEFAULT_SECURITY_CONFIG.sensitiveCookieDomains.slice(),
186
+ enforcement: POLICY_ENFORCEMENT_LEVELS.includes(raw.enforcement)
187
+ ? raw.enforcement
188
+ : DEFAULT_SECURITY_CONFIG.enforcement,
189
+ taskOrigin: mergeTaskOriginConfig(raw.taskOrigin),
190
+ egressAllowlist: Array.isArray(raw.egressAllowlist)
191
+ ? raw.egressAllowlist.slice()
192
+ : DEFAULT_SECURITY_CONFIG.egressAllowlist.slice(),
193
+ taint: mergeTaintConfig(raw.taint),
194
+ profile: mergeProfileConfig(raw.profile),
195
+ };
196
+ if (process.env.JS_EYES_INSECURE === '1') {
197
+ merged.allowAnonymous = true;
198
+ }
199
+ if (process.env.JS_EYES_ALLOW_REMOTE_BIND === '1') {
200
+ merged.allowRemoteBind = true;
201
+ }
202
+ if (process.env.JS_EYES_POLICY_ENFORCEMENT && POLICY_ENFORCEMENT_LEVELS.includes(process.env.JS_EYES_POLICY_ENFORCEMENT)) {
203
+ merged.enforcement = process.env.JS_EYES_POLICY_ENFORCEMENT;
204
+ }
205
+ return merged;
206
+ }
207
+
208
+ function mergeTaskOriginConfig(raw) {
209
+ if (!raw || typeof raw !== 'object') {
210
+ return { ...DEFAULT_TASK_ORIGIN_CONFIG, sources: DEFAULT_TASK_ORIGIN_CONFIG.sources.slice() };
211
+ }
212
+ return {
213
+ enabled: typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULT_TASK_ORIGIN_CONFIG.enabled,
214
+ sources: Array.isArray(raw.sources) && raw.sources.length
215
+ ? raw.sources.slice()
216
+ : DEFAULT_TASK_ORIGIN_CONFIG.sources.slice(),
217
+ };
218
+ }
219
+
220
+ function mergeTaintConfig(raw) {
221
+ if (!raw || typeof raw !== 'object') {
222
+ return { ...DEFAULT_TAINT_CONFIG };
223
+ }
224
+ return {
225
+ enabled: typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULT_TAINT_CONFIG.enabled,
226
+ mode: typeof raw.mode === 'string' && raw.mode ? raw.mode : DEFAULT_TAINT_CONFIG.mode,
227
+ minValueLength: Number.isFinite(raw.minValueLength) && raw.minValueLength > 0
228
+ ? Math.floor(raw.minValueLength)
229
+ : DEFAULT_TAINT_CONFIG.minValueLength,
230
+ };
231
+ }
232
+
233
+ function mergeProfileConfig(raw) {
234
+ if (!raw || typeof raw !== 'object') {
235
+ return { ...DEFAULT_PROFILE_CONFIG };
236
+ }
237
+ return {
238
+ default: typeof raw.default === 'string' && raw.default
239
+ ? raw.default
240
+ : DEFAULT_PROFILE_CONFIG.default,
241
+ };
242
+ }
243
+
244
+ module.exports = {
245
+ DEFAULT_ALLOWED_ORIGINS,
246
+ DEFAULT_SECURITY_CONFIG,
247
+ DEFAULT_TASK_ORIGIN_CONFIG,
248
+ DEFAULT_TAINT_CONFIG,
249
+ DEFAULT_PROFILE_CONFIG,
250
+ POLICY_ENFORCEMENT_LEVELS,
251
+ DEFAULT_SERVER_HOST,
252
+ DEFAULT_SERVER_PORT,
253
+ DEFAULT_REQUEST_TIMEOUT_SECONDS,
254
+ LOOPBACK_HOSTS,
255
+ REQUEST_TIMEOUT_MS,
256
+ PROTOCOL_VERSION,
257
+ PACKAGE_VERSION,
258
+ SKILLS_REGISTRY_URL,
259
+ RELEASE_BASE_URL,
260
+ FORWARDABLE_ACTIONS,
261
+ SENSITIVE_TOOL_NAMES,
262
+ COMPATIBILITY_MATRIX,
263
+ WS_CLOSE_CODE_AUTH_REQUIRED,
264
+ WS_CLOSE_CODE_FORBIDDEN_ORIGIN,
265
+ isLoopbackHost,
266
+ isOriginAllowed,
267
+ matchesOriginPattern,
268
+ resolveSecurityConfig,
269
+ };
package/openclaw-paths.js CHANGED
@@ -1,33 +1,33 @@
1
- 'use strict';
2
-
3
- // openclaw-paths: OpenClaw state/config path resolution.
4
- //
5
- // Intentionally lives in its own module so the `process.env` reads that pick
6
- // up OPENCLAW_CONFIG_PATH / OPENCLAW_STATE_DIR / OPENCLAW_HOME never sit in the
7
- // same file as network clients (see SECURITY_SCAN_NOTES.md, "Environment
8
- // variable access combined with network send"). This file MUST NOT import
9
- // `ws`, `http`, `https`, `net`, or any network helper — that invariant is
10
- // verified by test/import-boundaries.test.js.
11
-
12
- const os = require('os');
13
- const path = require('path');
14
-
15
- function getOpenClawConfigPath(options = {}) {
16
- const env = options.env || process.env;
17
- const home = options.home || os.homedir();
18
-
19
- if (env.OPENCLAW_CONFIG_PATH) {
20
- return path.resolve(env.OPENCLAW_CONFIG_PATH);
21
- }
22
- if (env.OPENCLAW_STATE_DIR) {
23
- return path.resolve(env.OPENCLAW_STATE_DIR, 'openclaw.json');
24
- }
25
- if (env.OPENCLAW_HOME) {
26
- return path.resolve(env.OPENCLAW_HOME, '.openclaw', 'openclaw.json');
27
- }
28
- return path.join(home, '.openclaw', 'openclaw.json');
29
- }
30
-
31
- module.exports = {
32
- getOpenClawConfigPath,
33
- };
1
+ 'use strict';
2
+
3
+ // openclaw-paths: OpenClaw state/config path resolution.
4
+ //
5
+ // Intentionally lives in its own module so the `process.env` reads that pick
6
+ // up OPENCLAW_CONFIG_PATH / OPENCLAW_STATE_DIR / OPENCLAW_HOME never sit in the
7
+ // same file as network clients (see SECURITY_SCAN_NOTES.md, "Environment
8
+ // variable access combined with network send"). This file MUST NOT import
9
+ // `ws`, `http`, `https`, `net`, or any network helper — that invariant is
10
+ // verified by test/import-boundaries.test.js.
11
+
12
+ const os = require('os');
13
+ const path = require('path');
14
+
15
+ function getOpenClawConfigPath(options = {}) {
16
+ const env = options.env || process.env;
17
+ const home = options.home || os.homedir();
18
+
19
+ if (env.OPENCLAW_CONFIG_PATH) {
20
+ return path.resolve(env.OPENCLAW_CONFIG_PATH);
21
+ }
22
+ if (env.OPENCLAW_STATE_DIR) {
23
+ return path.resolve(env.OPENCLAW_STATE_DIR, 'openclaw.json');
24
+ }
25
+ if (env.OPENCLAW_HOME) {
26
+ return path.resolve(env.OPENCLAW_HOME, '.openclaw', 'openclaw.json');
27
+ }
28
+ return path.join(home, '.openclaw', 'openclaw.json');
29
+ }
30
+
31
+ module.exports = {
32
+ getOpenClawConfigPath,
33
+ };