@kenhkl/agent-moss 0.17.12 → 0.17.14
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/dist/cli.js +54 -25
- package/dist/engine/coordinator.d.ts +2 -0
- package/dist/engine/coordinator.js +50 -24
- package/dist/rules/l1_rules.json +3 -3
- package/dist/scenarios/bank/rules.json +14 -2
- package/dist/server.js +54 -25
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1964,9 +1964,9 @@ function runLogicCheck(input, opts) {
|
|
|
1964
1964
|
}
|
|
1965
1965
|
}
|
|
1966
1966
|
}
|
|
1967
|
-
const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory, input.osType);
|
|
1967
|
+
const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory, input.osType, aNext);
|
|
1968
1968
|
if (pwdResult) return pwdResult;
|
|
1969
|
-
const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory, input.osType);
|
|
1969
|
+
const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory, input.osType, aNext);
|
|
1970
1970
|
if (userDelResult) return userDelResult;
|
|
1971
1971
|
const comboResult = checkComboChain(actionHistory, aNext.actionDetail);
|
|
1972
1972
|
if (comboResult) return comboResult;
|
|
@@ -2162,28 +2162,48 @@ function checkReadBeforeWrite(actionType, actionDetail, actionHistory, reason, c
|
|
|
2162
2162
|
}
|
|
2163
2163
|
return null;
|
|
2164
2164
|
}
|
|
2165
|
-
function
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2165
|
+
function isAskUserAction(actionType) {
|
|
2166
|
+
if (ASK_USER_ACTION_TYPES.includes(actionType)) return true;
|
|
2167
|
+
return actionType.endsWith("-askuser");
|
|
2168
|
+
}
|
|
2169
|
+
function consentWithinTtl(asked, aNext) {
|
|
2170
|
+
const raw = String(process.env.AGENT_MOSS_CONSENT_TTL_SECONDS || "").trim();
|
|
2171
|
+
const parsed = raw ? Number(raw) : CONSENT_TTL_SECONDS;
|
|
2172
|
+
const ttl = Number.isFinite(parsed) ? parsed : CONSENT_TTL_SECONDS;
|
|
2173
|
+
if (ttl <= 0) return true;
|
|
2174
|
+
const askedAt = String(asked.calledAt || "").trim();
|
|
2175
|
+
const nextAt = String(aNext?.calledAt || "").trim();
|
|
2176
|
+
if (!askedAt || !nextAt) return true;
|
|
2177
|
+
const a = Date.parse(askedAt);
|
|
2178
|
+
const b = Date.parse(nextAt);
|
|
2179
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) return true;
|
|
2180
|
+
return Math.abs(b - a) <= ttl * 1e3;
|
|
2181
|
+
}
|
|
2182
|
+
function hasValidConsent(actionHistory, aNext) {
|
|
2183
|
+
if (!actionHistory.length) return false;
|
|
2184
|
+
const tail = actionHistory.slice(-CONSENT_MAX_DISTANCE);
|
|
2185
|
+
for (let i = tail.length - 1; i >= 0; i--) {
|
|
2186
|
+
const h = tail[i];
|
|
2187
|
+
if (!isAskUserAction(String(h.actionType || "").toLowerCase())) continue;
|
|
2188
|
+
const output = String(h.output || "").trim();
|
|
2189
|
+
if (!output) return false;
|
|
2190
|
+
const question = String(h.actionDetail || "");
|
|
2191
|
+
if (!CONSENT_TOPIC.test(question)) return false;
|
|
2192
|
+
if (CONSENT_NEGATIVE.test(output)) return false;
|
|
2193
|
+
if (!CONSENT_INPUT_REQUEST.test(question) && !CONSENT_AFFIRMATIVE.test(output)) return false;
|
|
2194
|
+
return consentWithinTtl(h, aNext);
|
|
2195
|
+
}
|
|
2196
|
+
return false;
|
|
2176
2197
|
}
|
|
2177
|
-
function checkPasswordConsent(actionType, actionDetail, actionHistory, osType) {
|
|
2178
|
-
if (actionType
|
|
2198
|
+
function checkPasswordConsent(actionType, actionDetail, actionHistory, osType, aNext) {
|
|
2199
|
+
if (!BASH_LIKE_ACTION_TYPES.includes(actionType)) return null;
|
|
2179
2200
|
const pwdPatterns = runtimeConfigBridge.current?.effectivePasswordPatterns(osType) ?? PASSWORD_MODIFY_PATTERNS;
|
|
2180
2201
|
const isPasswordModify = pwdPatterns.some((p) => p.test(actionDetail));
|
|
2181
2202
|
if (!isPasswordModify) return null;
|
|
2182
|
-
if (
|
|
2183
|
-
if (hasWeakConsent(actionHistory)) return null;
|
|
2203
|
+
if (hasValidConsent(actionHistory, aNext)) return null;
|
|
2184
2204
|
return {
|
|
2185
2205
|
allowed: false,
|
|
2186
|
-
reason: "\u6267\u884C\u975E\u4EA4\u4E92\u5F0F\u5BC6\u7801\u4FEE\u6539\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\
|
|
2206
|
+
reason: "\u6267\u884C\u975E\u4EA4\u4E92\u5F0F\u5BC6\u7801\u4FEE\u6539\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\u7528\u6237\u660E\u786E\u6388\u6743\u7684 ask_user_question\uFF08\u987B\u7528\u6237\u6B63\u9762\u56DE\u7B54\u4E14\u4E0E\u672C\u6B21\u64CD\u4F5C\u76F8\u5173\uFF09\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u6388\u6743\u7684\u5BC6\u7801\u4FEE\u6539\u98CE\u9669",
|
|
2187
2207
|
riskLevel: "high",
|
|
2188
2208
|
riskType: "consent_missing",
|
|
2189
2209
|
confidence: 85,
|
|
@@ -2191,16 +2211,15 @@ function checkPasswordConsent(actionType, actionDetail, actionHistory, osType) {
|
|
|
2191
2211
|
violatedLayers: ["L2.1"]
|
|
2192
2212
|
};
|
|
2193
2213
|
}
|
|
2194
|
-
function checkUserDeletionConsent(actionType, actionDetail, actionHistory, osType) {
|
|
2195
|
-
if (actionType
|
|
2214
|
+
function checkUserDeletionConsent(actionType, actionDetail, actionHistory, osType, aNext) {
|
|
2215
|
+
if (!BASH_LIKE_ACTION_TYPES.includes(actionType)) return null;
|
|
2196
2216
|
const udPatterns = runtimeConfigBridge.current?.effectiveUserDeletionPatterns(osType) ?? USER_DELETION_PATTERNS;
|
|
2197
2217
|
const isUserDeletion = udPatterns.some((p) => p.test(actionDetail));
|
|
2198
2218
|
if (!isUserDeletion) return null;
|
|
2199
|
-
if (
|
|
2200
|
-
if (hasWeakConsent(actionHistory)) return null;
|
|
2219
|
+
if (hasValidConsent(actionHistory, aNext)) return null;
|
|
2201
2220
|
return {
|
|
2202
2221
|
allowed: false,
|
|
2203
|
-
reason: "\u6267\u884C\u5220\u9664\u7CFB\u7EDF\u7528\u6237\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\
|
|
2222
|
+
reason: "\u6267\u884C\u5220\u9664\u7CFB\u7EDF\u7528\u6237\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\u7528\u6237\u660E\u786E\u6388\u6743\u7684 ask_user_question\uFF08\u987B\u7528\u6237\u6B63\u9762\u56DE\u7B54\u4E14\u4E0E\u672C\u6B21\u64CD\u4F5C\u76F8\u5173\uFF09\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u6388\u6743\u7684\u7528\u6237\u5220\u9664\u98CE\u9669",
|
|
2204
2223
|
riskLevel: "high",
|
|
2205
2224
|
riskType: "consent_missing",
|
|
2206
2225
|
confidence: 85,
|
|
@@ -2299,7 +2318,7 @@ function checkIndirectFileAccess(actionType, actionDetail, cwd, osType) {
|
|
|
2299
2318
|
violatedLayers: ["L2.1"]
|
|
2300
2319
|
};
|
|
2301
2320
|
}
|
|
2302
|
-
var _LOGIC, _HEURISTIC, EXCLUDED_PREFIXES, TEMP_DIRS, ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, ROOT_SENSITIVE_PATHS_WINDOWS, HOME_SENSITIVE_PATHS_WINDOWS, CREDENTIAL_PATHS_WINDOWS, ROOT_SENSITIVE_PATHS_MACOS, HOME_SENSITIVE_PATHS_MACOS, CREDENTIAL_PATHS_MACOS, ROOT_SENSITIVE_PATHS_HARMONY, HOME_SENSITIVE_PATHS_HARMONY, CREDENTIAL_PATHS_HARMONY, _scopeIndex, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, PSEUDO_FS_PREFIXES, WRITE_KEYWORDS, SED_INPLACE_RE, DEVNULL_REDIRECT_RE, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, COMBO_STAGES, COMBO_CHAINS, CONSENT_TOPIC, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW, _IFA, IFA_READ_KEYWORDS, IFA_WRITE_KEYWORDS, IFA_EXEC_KEYWORDS, IFA_OPEN_KEYWORDS;
|
|
2321
|
+
var _LOGIC, _HEURISTIC, EXCLUDED_PREFIXES, TEMP_DIRS, ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, ROOT_SENSITIVE_PATHS_WINDOWS, HOME_SENSITIVE_PATHS_WINDOWS, CREDENTIAL_PATHS_WINDOWS, ROOT_SENSITIVE_PATHS_MACOS, HOME_SENSITIVE_PATHS_MACOS, CREDENTIAL_PATHS_MACOS, ROOT_SENSITIVE_PATHS_HARMONY, HOME_SENSITIVE_PATHS_HARMONY, CREDENTIAL_PATHS_HARMONY, _scopeIndex, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, PSEUDO_FS_PREFIXES, WRITE_KEYWORDS, SED_INPLACE_RE, DEVNULL_REDIRECT_RE, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, COMBO_STAGES, COMBO_CHAINS, CONSENT_TOPIC, CONSENT_NEGATIVE, CONSENT_AFFIRMATIVE, CONSENT_INPUT_REQUEST, CONSENT_MAX_DISTANCE, CONSENT_TTL_SECONDS, BASH_LIKE_ACTION_TYPES, ASK_USER_ACTION_TYPES, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW, _IFA, IFA_READ_KEYWORDS, IFA_WRITE_KEYWORDS, IFA_EXEC_KEYWORDS, IFA_OPEN_KEYWORDS;
|
|
2303
2322
|
var init_logic_rules = __esm({
|
|
2304
2323
|
"src/engine/logic-rules.ts"() {
|
|
2305
2324
|
"use strict";
|
|
@@ -2387,6 +2406,13 @@ var init_logic_rules = __esm({
|
|
|
2387
2406
|
}));
|
|
2388
2407
|
})();
|
|
2389
2408
|
CONSENT_TOPIC = /密码|口令|passwd|password|凭据|凭证|用户|账户|账号|userdel|deluser|groupdel/i;
|
|
2409
|
+
CONSENT_NEGATIVE = /(?:否|不|别|取消|拒绝|停止|终止|算了|\bno\b|\bnope\b|\bcancel\b|\babort\b|\bstop\b|\bdeny\b|\breject\b|\bdecline\b|\bdon'?t\b|\bdo\s+not\b)/i;
|
|
2410
|
+
CONSENT_AFFIRMATIVE = /(?:是|好|可以|行|嗯|对|确认|同意|继续|执行|删除|删掉|移除|修改|重置|改密|\byes\b|\by\b|\byep\b|\byeah\b|\bok\b|\bokay\b|\bconfirm(?:ed)?\b|\bproceed\b|\bcontinue\b|\bsure\b|\bapprove\b|\baccept\b|\bagree\b|\bdo\s+it\b|\bgo\s+ahead\b)/i;
|
|
2411
|
+
CONSENT_INPUT_REQUEST = /(?:请|输入|提供|填写|给出|告诉我).{0,8}(?:新的?)?(?:密码|口令|passwd|password)/i;
|
|
2412
|
+
CONSENT_MAX_DISTANCE = 5;
|
|
2413
|
+
CONSENT_TTL_SECONDS = 300;
|
|
2414
|
+
BASH_LIKE_ACTION_TYPES = ["bash", "executebash", "terminal-executebash"];
|
|
2415
|
+
ASK_USER_ACTION_TYPES = ["ask_user_question", "askuser"];
|
|
2390
2416
|
INLINE_SCRIPT_RE = /(?:^|\s)(?:python|python3|python3\.\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\s+)/i;
|
|
2391
2417
|
DIR_TRAVERSAL_KW = loadInline().dir_traversal_keywords ?? [];
|
|
2392
2418
|
_IFA = loadLogicRules().indirect_file_access ?? {};
|
|
@@ -12459,7 +12485,10 @@ async function analyzeRoute(c) {
|
|
|
12459
12485
|
aNext: {
|
|
12460
12486
|
actionType: req.a_next.action_type,
|
|
12461
12487
|
actionDetail: req.a_next.action_detail,
|
|
12462
|
-
instanceId
|
|
12488
|
+
instanceId,
|
|
12489
|
+
// called_at 一并透传:L2 授权(consent)的时效窗需要「提问时刻」与
|
|
12490
|
+
// 「本次动作时刻」两侧都有时间戳才生效(对齐 Python routes.py)。
|
|
12491
|
+
calledAt: req.a_next.called_at
|
|
12463
12492
|
},
|
|
12464
12493
|
reason: req.reason,
|
|
12465
12494
|
osType,
|
|
@@ -66,6 +66,7 @@ interface AnalysisInput {
|
|
|
66
66
|
actionType: string;
|
|
67
67
|
actionDetail: string;
|
|
68
68
|
output?: string;
|
|
69
|
+
calledAt?: string;
|
|
69
70
|
}[];
|
|
70
71
|
/** 完整的交错历史 prompt(可选),每轮 {text, actions} 或纯文本 string(AgentGate v3 旧格式),按时间序。
|
|
71
72
|
* 供 L2 意图一致性与 L3 语义分析使用;空则回退单条 promptSession。 */
|
|
@@ -92,6 +93,7 @@ interface AnalysisInput {
|
|
|
92
93
|
actionType: string;
|
|
93
94
|
actionDetail: string;
|
|
94
95
|
instanceId?: string;
|
|
96
|
+
calledAt?: string;
|
|
95
97
|
};
|
|
96
98
|
reason: string;
|
|
97
99
|
osType: string;
|
|
@@ -1141,9 +1141,9 @@ function runLogicCheck(input, opts) {
|
|
|
1141
1141
|
}
|
|
1142
1142
|
}
|
|
1143
1143
|
}
|
|
1144
|
-
const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory, input.osType);
|
|
1144
|
+
const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory, input.osType, aNext);
|
|
1145
1145
|
if (pwdResult) return pwdResult;
|
|
1146
|
-
const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory, input.osType);
|
|
1146
|
+
const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory, input.osType, aNext);
|
|
1147
1147
|
if (userDelResult) return userDelResult;
|
|
1148
1148
|
const comboResult = checkComboChain(actionHistory, aNext.actionDetail);
|
|
1149
1149
|
if (comboResult) return comboResult;
|
|
@@ -1339,28 +1339,48 @@ function checkReadBeforeWrite(actionType, actionDetail, actionHistory, reason, c
|
|
|
1339
1339
|
}
|
|
1340
1340
|
return null;
|
|
1341
1341
|
}
|
|
1342
|
-
function
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1342
|
+
function isAskUserAction(actionType) {
|
|
1343
|
+
if (ASK_USER_ACTION_TYPES.includes(actionType)) return true;
|
|
1344
|
+
return actionType.endsWith("-askuser");
|
|
1345
|
+
}
|
|
1346
|
+
function consentWithinTtl(asked, aNext) {
|
|
1347
|
+
const raw = String(process.env.AGENT_MOSS_CONSENT_TTL_SECONDS || "").trim();
|
|
1348
|
+
const parsed = raw ? Number(raw) : CONSENT_TTL_SECONDS;
|
|
1349
|
+
const ttl = Number.isFinite(parsed) ? parsed : CONSENT_TTL_SECONDS;
|
|
1350
|
+
if (ttl <= 0) return true;
|
|
1351
|
+
const askedAt = String(asked.calledAt || "").trim();
|
|
1352
|
+
const nextAt = String(aNext?.calledAt || "").trim();
|
|
1353
|
+
if (!askedAt || !nextAt) return true;
|
|
1354
|
+
const a = Date.parse(askedAt);
|
|
1355
|
+
const b = Date.parse(nextAt);
|
|
1356
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) return true;
|
|
1357
|
+
return Math.abs(b - a) <= ttl * 1e3;
|
|
1358
|
+
}
|
|
1359
|
+
function hasValidConsent(actionHistory, aNext) {
|
|
1360
|
+
if (!actionHistory.length) return false;
|
|
1361
|
+
const tail = actionHistory.slice(-CONSENT_MAX_DISTANCE);
|
|
1362
|
+
for (let i = tail.length - 1; i >= 0; i--) {
|
|
1363
|
+
const h = tail[i];
|
|
1364
|
+
if (!isAskUserAction(String(h.actionType || "").toLowerCase())) continue;
|
|
1365
|
+
const output = String(h.output || "").trim();
|
|
1366
|
+
if (!output) return false;
|
|
1367
|
+
const question = String(h.actionDetail || "");
|
|
1368
|
+
if (!CONSENT_TOPIC.test(question)) return false;
|
|
1369
|
+
if (CONSENT_NEGATIVE.test(output)) return false;
|
|
1370
|
+
if (!CONSENT_INPUT_REQUEST.test(question) && !CONSENT_AFFIRMATIVE.test(output)) return false;
|
|
1371
|
+
return consentWithinTtl(h, aNext);
|
|
1372
|
+
}
|
|
1373
|
+
return false;
|
|
1353
1374
|
}
|
|
1354
|
-
function checkPasswordConsent(actionType, actionDetail, actionHistory, osType) {
|
|
1355
|
-
if (actionType
|
|
1375
|
+
function checkPasswordConsent(actionType, actionDetail, actionHistory, osType, aNext) {
|
|
1376
|
+
if (!BASH_LIKE_ACTION_TYPES.includes(actionType)) return null;
|
|
1356
1377
|
const pwdPatterns = runtimeConfigBridge.current?.effectivePasswordPatterns(osType) ?? PASSWORD_MODIFY_PATTERNS;
|
|
1357
1378
|
const isPasswordModify = pwdPatterns.some((p) => p.test(actionDetail));
|
|
1358
1379
|
if (!isPasswordModify) return null;
|
|
1359
|
-
if (
|
|
1360
|
-
if (hasWeakConsent(actionHistory)) return null;
|
|
1380
|
+
if (hasValidConsent(actionHistory, aNext)) return null;
|
|
1361
1381
|
return {
|
|
1362
1382
|
allowed: false,
|
|
1363
|
-
reason: "\u6267\u884C\u975E\u4EA4\u4E92\u5F0F\u5BC6\u7801\u4FEE\u6539\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\
|
|
1383
|
+
reason: "\u6267\u884C\u975E\u4EA4\u4E92\u5F0F\u5BC6\u7801\u4FEE\u6539\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\u7528\u6237\u660E\u786E\u6388\u6743\u7684 ask_user_question\uFF08\u987B\u7528\u6237\u6B63\u9762\u56DE\u7B54\u4E14\u4E0E\u672C\u6B21\u64CD\u4F5C\u76F8\u5173\uFF09\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u6388\u6743\u7684\u5BC6\u7801\u4FEE\u6539\u98CE\u9669",
|
|
1364
1384
|
riskLevel: "high",
|
|
1365
1385
|
riskType: "consent_missing",
|
|
1366
1386
|
confidence: 85,
|
|
@@ -1368,16 +1388,15 @@ function checkPasswordConsent(actionType, actionDetail, actionHistory, osType) {
|
|
|
1368
1388
|
violatedLayers: ["L2.1"]
|
|
1369
1389
|
};
|
|
1370
1390
|
}
|
|
1371
|
-
function checkUserDeletionConsent(actionType, actionDetail, actionHistory, osType) {
|
|
1372
|
-
if (actionType
|
|
1391
|
+
function checkUserDeletionConsent(actionType, actionDetail, actionHistory, osType, aNext) {
|
|
1392
|
+
if (!BASH_LIKE_ACTION_TYPES.includes(actionType)) return null;
|
|
1373
1393
|
const udPatterns = runtimeConfigBridge.current?.effectiveUserDeletionPatterns(osType) ?? USER_DELETION_PATTERNS;
|
|
1374
1394
|
const isUserDeletion = udPatterns.some((p) => p.test(actionDetail));
|
|
1375
1395
|
if (!isUserDeletion) return null;
|
|
1376
|
-
if (
|
|
1377
|
-
if (hasWeakConsent(actionHistory)) return null;
|
|
1396
|
+
if (hasValidConsent(actionHistory, aNext)) return null;
|
|
1378
1397
|
return {
|
|
1379
1398
|
allowed: false,
|
|
1380
|
-
reason: "\u6267\u884C\u5220\u9664\u7CFB\u7EDF\u7528\u6237\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\
|
|
1399
|
+
reason: "\u6267\u884C\u5220\u9664\u7CFB\u7EDF\u7528\u6237\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\u7528\u6237\u660E\u786E\u6388\u6743\u7684 ask_user_question\uFF08\u987B\u7528\u6237\u6B63\u9762\u56DE\u7B54\u4E14\u4E0E\u672C\u6B21\u64CD\u4F5C\u76F8\u5173\uFF09\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u6388\u6743\u7684\u7528\u6237\u5220\u9664\u98CE\u9669",
|
|
1381
1400
|
riskLevel: "high",
|
|
1382
1401
|
riskType: "consent_missing",
|
|
1383
1402
|
confidence: 85,
|
|
@@ -1476,7 +1495,7 @@ function checkIndirectFileAccess(actionType, actionDetail, cwd, osType) {
|
|
|
1476
1495
|
violatedLayers: ["L2.1"]
|
|
1477
1496
|
};
|
|
1478
1497
|
}
|
|
1479
|
-
var _LOGIC, _HEURISTIC, EXCLUDED_PREFIXES, TEMP_DIRS, ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, ROOT_SENSITIVE_PATHS_WINDOWS, HOME_SENSITIVE_PATHS_WINDOWS, CREDENTIAL_PATHS_WINDOWS, ROOT_SENSITIVE_PATHS_MACOS, HOME_SENSITIVE_PATHS_MACOS, CREDENTIAL_PATHS_MACOS, ROOT_SENSITIVE_PATHS_HARMONY, HOME_SENSITIVE_PATHS_HARMONY, CREDENTIAL_PATHS_HARMONY, _scopeIndex, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, PSEUDO_FS_PREFIXES, WRITE_KEYWORDS, SED_INPLACE_RE, DEVNULL_REDIRECT_RE, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, COMBO_STAGES, COMBO_CHAINS, CONSENT_TOPIC, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW, _IFA, IFA_READ_KEYWORDS, IFA_WRITE_KEYWORDS, IFA_EXEC_KEYWORDS, IFA_OPEN_KEYWORDS;
|
|
1498
|
+
var _LOGIC, _HEURISTIC, EXCLUDED_PREFIXES, TEMP_DIRS, ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, ROOT_SENSITIVE_PATHS_WINDOWS, HOME_SENSITIVE_PATHS_WINDOWS, CREDENTIAL_PATHS_WINDOWS, ROOT_SENSITIVE_PATHS_MACOS, HOME_SENSITIVE_PATHS_MACOS, CREDENTIAL_PATHS_MACOS, ROOT_SENSITIVE_PATHS_HARMONY, HOME_SENSITIVE_PATHS_HARMONY, CREDENTIAL_PATHS_HARMONY, _scopeIndex, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, PSEUDO_FS_PREFIXES, WRITE_KEYWORDS, SED_INPLACE_RE, DEVNULL_REDIRECT_RE, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, COMBO_STAGES, COMBO_CHAINS, CONSENT_TOPIC, CONSENT_NEGATIVE, CONSENT_AFFIRMATIVE, CONSENT_INPUT_REQUEST, CONSENT_MAX_DISTANCE, CONSENT_TTL_SECONDS, BASH_LIKE_ACTION_TYPES, ASK_USER_ACTION_TYPES, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW, _IFA, IFA_READ_KEYWORDS, IFA_WRITE_KEYWORDS, IFA_EXEC_KEYWORDS, IFA_OPEN_KEYWORDS;
|
|
1480
1499
|
var init_logic_rules = __esm({
|
|
1481
1500
|
"src/engine/logic-rules.ts"() {
|
|
1482
1501
|
"use strict";
|
|
@@ -1564,6 +1583,13 @@ var init_logic_rules = __esm({
|
|
|
1564
1583
|
}));
|
|
1565
1584
|
})();
|
|
1566
1585
|
CONSENT_TOPIC = /密码|口令|passwd|password|凭据|凭证|用户|账户|账号|userdel|deluser|groupdel/i;
|
|
1586
|
+
CONSENT_NEGATIVE = /(?:否|不|别|取消|拒绝|停止|终止|算了|\bno\b|\bnope\b|\bcancel\b|\babort\b|\bstop\b|\bdeny\b|\breject\b|\bdecline\b|\bdon'?t\b|\bdo\s+not\b)/i;
|
|
1587
|
+
CONSENT_AFFIRMATIVE = /(?:是|好|可以|行|嗯|对|确认|同意|继续|执行|删除|删掉|移除|修改|重置|改密|\byes\b|\by\b|\byep\b|\byeah\b|\bok\b|\bokay\b|\bconfirm(?:ed)?\b|\bproceed\b|\bcontinue\b|\bsure\b|\bapprove\b|\baccept\b|\bagree\b|\bdo\s+it\b|\bgo\s+ahead\b)/i;
|
|
1588
|
+
CONSENT_INPUT_REQUEST = /(?:请|输入|提供|填写|给出|告诉我).{0,8}(?:新的?)?(?:密码|口令|passwd|password)/i;
|
|
1589
|
+
CONSENT_MAX_DISTANCE = 5;
|
|
1590
|
+
CONSENT_TTL_SECONDS = 300;
|
|
1591
|
+
BASH_LIKE_ACTION_TYPES = ["bash", "executebash", "terminal-executebash"];
|
|
1592
|
+
ASK_USER_ACTION_TYPES = ["ask_user_question", "askuser"];
|
|
1567
1593
|
INLINE_SCRIPT_RE = /(?:^|\s)(?:python|python3|python3\.\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\s+)/i;
|
|
1568
1594
|
DIR_TRAVERSAL_KW = loadInline().dir_traversal_keywords ?? [];
|
|
1569
1595
|
_IFA = loadLogicRules().indirect_file_access ?? {};
|
package/dist/rules/l1_rules.json
CHANGED
|
@@ -697,14 +697,14 @@
|
|
|
697
697
|
"reason": "检测到 MongoDB 删除集合 (db.<col>.drop())"
|
|
698
698
|
},
|
|
699
699
|
{
|
|
700
|
-
"pattern": "(?:del|rmdir|rd)\\s+[\\\\/][a-zA-Z]:",
|
|
700
|
+
"pattern": "(?:del|rmdir|rd)\\s+[\\\\/]?[a-zA-Z]:",
|
|
701
701
|
"risk_level": "critical",
|
|
702
702
|
"risk_type": "script_execution",
|
|
703
703
|
"reason": "检测到递归删除关键路径 (del/rmdir C:\\)",
|
|
704
704
|
"os": "windows"
|
|
705
705
|
},
|
|
706
706
|
{
|
|
707
|
-
"pattern": "del\\s+[\\\\/][a-zA-Z]:",
|
|
707
|
+
"pattern": "del\\s+[\\\\/]?[a-zA-Z]:",
|
|
708
708
|
"risk_level": "critical",
|
|
709
709
|
"risk_type": "script_execution",
|
|
710
710
|
"reason": "检测到删除卷根目录文件 (del C:\\)",
|
|
@@ -816,7 +816,7 @@
|
|
|
816
816
|
"os": "windows"
|
|
817
817
|
},
|
|
818
818
|
{
|
|
819
|
-
"pattern": "\\bSet-Content\\b[^;&|\\n]*\\
|
|
819
|
+
"pattern": "\\bSet-Content\\b[^;&|\\n]*\\s-[A-Za-z]*Stream\\b",
|
|
820
820
|
"risk_level": "high",
|
|
821
821
|
"risk_type": "script_execution",
|
|
822
822
|
"reason": "检测到写入 NTFS 备用数据流(用于隐藏载荷)",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"scenario_id": "bank",
|
|
3
|
-
"description": "银行沙箱场景定制规则。客户约束:沙箱用户(sandbox)仅允许读写 /home/sandbox、/opt/sandbox、/tmp 三个目录,其他根目录一律禁止读写;禁止远程访问/横向移动(ssh 家族 + scp/sftp/sshpass/ssh-copy-id + 用 ssh 的 rsync)。本地操作(ssh-keygen/ssh-add/ssh-agent、本地 rsync)不受影响。另放行 /dev/null、/dev/stdout、/dev/stderr —— 这三个是 666/可写、仅作流丢弃与输出重定向用的标准设备文件(`2>/dev/null` 是最常见的运维写法),不放行会让大量正常命令被误拦;/dev 下**其余**文件(/dev/mem、/dev/sda、/dev/shm
|
|
3
|
+
"description": "银行沙箱场景定制规则。客户约束:沙箱用户(sandbox)仅允许读写 /home/sandbox、/opt/sandbox、/tmp 三个目录,其他根目录一律禁止读写;禁止远程访问/横向移动(ssh 家族 + scp/sftp/sshpass/ssh-copy-id + 用 ssh 的 rsync)。本地操作(ssh-keygen/ssh-add/ssh-agent、本地 rsync)不受影响。另放行 /dev/null、/dev/stdout、/dev/stderr —— 这三个是 666/可写、仅作流丢弃与输出重定向用的标准设备文件(`2>/dev/null` 是最常见的运维写法),不放行会让大量正常命令被误拦;/dev 下**其余**文件(/dev/mem、/dev/sda、/dev/shm…)照常拦。。另:`/bin/ls`、`/usr/bin/python3` 这类**命令的绝对路径写法**属正常执行,不算路径访问(2026-10 修误报);但用 `>/cp/mv/tee/install/ln` 往这些目录**写文件**仍然拦。",
|
|
4
4
|
"extra_command_patterns": [
|
|
5
5
|
{
|
|
6
|
-
"pattern": "(?<![\\w.:~/-])/(?:(?!home/sandbox(?:\\s|/|$)|opt/sandbox(?:\\s|/|$)|tmp(?:\\s|/|$)|dev/null(?=[\\s;&|<>)\"'`]|$)|dev/stdout(?=[\\s;&|<>)\"'`]|$)|dev/stderr(?=[\\s;&|<>)\"'`]|$))[^\\s;&|>\"'`]*|[^\\s;&|>\"'`]*/\\.\\.[^\\s;&|>\"'`]*)|(?:^|[\\s;&|<>=(`'\"!/])(?:\\.\\./|\\.\\.(?=\\s|$|[;&|]))|(?:^|[\\s;&|<>=(`'\"!])~(?!sandbox\\b)[\\w-]+",
|
|
6
|
+
"pattern": "(?<![\\w.:~/-])/(?:(?!home/sandbox(?:\\s|/|$)|opt/sandbox(?:\\s|/|$)|tmp(?:\\s|/|$)|dev/null(?=[\\s;&|<>)\"'`]|$)|dev/stdout(?=[\\s;&|<>)\"'`]|$)|dev/stderr(?=[\\s;&|<>)\"'`]|$)|(?:usr/)?(?:local/)?s?bin/(?!.*\\.\\.)[^\\s;&|>\"'`]*(?=[\\s;&|<>)\"'`]|$))[^\\s;&|>\"'`]*|[^\\s;&|>\"'`]*/\\.\\.[^\\s;&|>\"'`]*)|(?:^|[\\s;&|<>=(`'\"!/])(?:\\.\\./|\\.\\.(?=\\s|$|[;&|]))|(?:^|[\\s;&|<>=(`'\"!])~(?!sandbox\\b)[\\w-]+",
|
|
7
7
|
"risk_level": "high",
|
|
8
8
|
"risk_type": "file_access",
|
|
9
9
|
"reason": "bank 场景:访问允许目录(/home/sandbox、/opt/sandbox、/tmp,以及 /dev/null、/dev/stdout、/dev/stderr 三个标准流重定向目标)之外的路径(含根目录 /),或用 .. 逃逸 / ~其它用户"
|
|
@@ -13,6 +13,18 @@
|
|
|
13
13
|
"risk_level": "critical",
|
|
14
14
|
"risk_type": "network_access",
|
|
15
15
|
"reason": "bank 场景:禁止远程访问 / 横向移动(ssh / scp / sftp / sshpass / ssh-copy-id / rsync -e ssh)"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"pattern": "(?:^|[\\s;&|(])(?:>|>>|\\btee\\b|\\bcp\\b|\\bmv\\b|\\binstall\\b|\\bln\\b)[^;&|\\n]*?/(?:usr/)?(?:local/)?s?bin/",
|
|
19
|
+
"risk_level": "high",
|
|
20
|
+
"risk_type": "file_access",
|
|
21
|
+
"reason": "bank 场景:向系统可执行目录(/bin、/sbin、/usr/bin、/usr/local/bin 等)写入文件 —— 可执行路径本身作为命令运行是放行的,但把它当写目标不行"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"pattern": "(?:^|[;&|(\\n])\\s*(?:sudo\\s+)?crontab\\s+(?!-l\\b)\\S",
|
|
25
|
+
"risk_level": "high",
|
|
26
|
+
"risk_type": "persistence",
|
|
27
|
+
"reason": "bank 场景:禁止写系统定时任务(crontab 安装/编辑/删除)——写操作落在 /var/spool/cron,属白名单外,且是持久化后门;`crontab -l` 只读放行"
|
|
16
28
|
}
|
|
17
29
|
],
|
|
18
30
|
"extra_injection_keywords": [],
|
package/dist/server.js
CHANGED
|
@@ -1672,9 +1672,9 @@ function runLogicCheck(input, opts) {
|
|
|
1672
1672
|
}
|
|
1673
1673
|
}
|
|
1674
1674
|
}
|
|
1675
|
-
const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory, input.osType);
|
|
1675
|
+
const pwdResult = checkPasswordConsent(actionType, actionDetail, actionHistory, input.osType, aNext);
|
|
1676
1676
|
if (pwdResult) return pwdResult;
|
|
1677
|
-
const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory, input.osType);
|
|
1677
|
+
const userDelResult = checkUserDeletionConsent(actionType, actionDetail, actionHistory, input.osType, aNext);
|
|
1678
1678
|
if (userDelResult) return userDelResult;
|
|
1679
1679
|
const comboResult = checkComboChain(actionHistory, aNext.actionDetail);
|
|
1680
1680
|
if (comboResult) return comboResult;
|
|
@@ -1870,28 +1870,48 @@ function checkReadBeforeWrite(actionType, actionDetail, actionHistory, reason, c
|
|
|
1870
1870
|
}
|
|
1871
1871
|
return null;
|
|
1872
1872
|
}
|
|
1873
|
-
function
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1873
|
+
function isAskUserAction(actionType) {
|
|
1874
|
+
if (ASK_USER_ACTION_TYPES.includes(actionType)) return true;
|
|
1875
|
+
return actionType.endsWith("-askuser");
|
|
1876
|
+
}
|
|
1877
|
+
function consentWithinTtl(asked, aNext) {
|
|
1878
|
+
const raw = String(process.env.AGENT_MOSS_CONSENT_TTL_SECONDS || "").trim();
|
|
1879
|
+
const parsed = raw ? Number(raw) : CONSENT_TTL_SECONDS;
|
|
1880
|
+
const ttl = Number.isFinite(parsed) ? parsed : CONSENT_TTL_SECONDS;
|
|
1881
|
+
if (ttl <= 0) return true;
|
|
1882
|
+
const askedAt = String(asked.calledAt || "").trim();
|
|
1883
|
+
const nextAt = String(aNext?.calledAt || "").trim();
|
|
1884
|
+
if (!askedAt || !nextAt) return true;
|
|
1885
|
+
const a = Date.parse(askedAt);
|
|
1886
|
+
const b = Date.parse(nextAt);
|
|
1887
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) return true;
|
|
1888
|
+
return Math.abs(b - a) <= ttl * 1e3;
|
|
1889
|
+
}
|
|
1890
|
+
function hasValidConsent(actionHistory, aNext) {
|
|
1891
|
+
if (!actionHistory.length) return false;
|
|
1892
|
+
const tail = actionHistory.slice(-CONSENT_MAX_DISTANCE);
|
|
1893
|
+
for (let i = tail.length - 1; i >= 0; i--) {
|
|
1894
|
+
const h = tail[i];
|
|
1895
|
+
if (!isAskUserAction(String(h.actionType || "").toLowerCase())) continue;
|
|
1896
|
+
const output = String(h.output || "").trim();
|
|
1897
|
+
if (!output) return false;
|
|
1898
|
+
const question = String(h.actionDetail || "");
|
|
1899
|
+
if (!CONSENT_TOPIC.test(question)) return false;
|
|
1900
|
+
if (CONSENT_NEGATIVE.test(output)) return false;
|
|
1901
|
+
if (!CONSENT_INPUT_REQUEST.test(question) && !CONSENT_AFFIRMATIVE.test(output)) return false;
|
|
1902
|
+
return consentWithinTtl(h, aNext);
|
|
1903
|
+
}
|
|
1904
|
+
return false;
|
|
1884
1905
|
}
|
|
1885
|
-
function checkPasswordConsent(actionType, actionDetail, actionHistory, osType) {
|
|
1886
|
-
if (actionType
|
|
1906
|
+
function checkPasswordConsent(actionType, actionDetail, actionHistory, osType, aNext) {
|
|
1907
|
+
if (!BASH_LIKE_ACTION_TYPES.includes(actionType)) return null;
|
|
1887
1908
|
const pwdPatterns = runtimeConfigBridge.current?.effectivePasswordPatterns(osType) ?? PASSWORD_MODIFY_PATTERNS;
|
|
1888
1909
|
const isPasswordModify = pwdPatterns.some((p) => p.test(actionDetail));
|
|
1889
1910
|
if (!isPasswordModify) return null;
|
|
1890
|
-
if (
|
|
1891
|
-
if (hasWeakConsent(actionHistory)) return null;
|
|
1911
|
+
if (hasValidConsent(actionHistory, aNext)) return null;
|
|
1892
1912
|
return {
|
|
1893
1913
|
allowed: false,
|
|
1894
|
-
reason: "\u6267\u884C\u975E\u4EA4\u4E92\u5F0F\u5BC6\u7801\u4FEE\u6539\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\
|
|
1914
|
+
reason: "\u6267\u884C\u975E\u4EA4\u4E92\u5F0F\u5BC6\u7801\u4FEE\u6539\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\u7528\u6237\u660E\u786E\u6388\u6743\u7684 ask_user_question\uFF08\u987B\u7528\u6237\u6B63\u9762\u56DE\u7B54\u4E14\u4E0E\u672C\u6B21\u64CD\u4F5C\u76F8\u5173\uFF09\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u6388\u6743\u7684\u5BC6\u7801\u4FEE\u6539\u98CE\u9669",
|
|
1895
1915
|
riskLevel: "high",
|
|
1896
1916
|
riskType: "consent_missing",
|
|
1897
1917
|
confidence: 85,
|
|
@@ -1899,16 +1919,15 @@ function checkPasswordConsent(actionType, actionDetail, actionHistory, osType) {
|
|
|
1899
1919
|
violatedLayers: ["L2.1"]
|
|
1900
1920
|
};
|
|
1901
1921
|
}
|
|
1902
|
-
function checkUserDeletionConsent(actionType, actionDetail, actionHistory, osType) {
|
|
1903
|
-
if (actionType
|
|
1922
|
+
function checkUserDeletionConsent(actionType, actionDetail, actionHistory, osType, aNext) {
|
|
1923
|
+
if (!BASH_LIKE_ACTION_TYPES.includes(actionType)) return null;
|
|
1904
1924
|
const udPatterns = runtimeConfigBridge.current?.effectiveUserDeletionPatterns(osType) ?? USER_DELETION_PATTERNS;
|
|
1905
1925
|
const isUserDeletion = udPatterns.some((p) => p.test(actionDetail));
|
|
1906
1926
|
if (!isUserDeletion) return null;
|
|
1907
|
-
if (
|
|
1908
|
-
if (hasWeakConsent(actionHistory)) return null;
|
|
1927
|
+
if (hasValidConsent(actionHistory, aNext)) return null;
|
|
1909
1928
|
return {
|
|
1910
1929
|
allowed: false,
|
|
1911
|
-
reason: "\u6267\u884C\u5220\u9664\u7CFB\u7EDF\u7528\u6237\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\
|
|
1930
|
+
reason: "\u6267\u884C\u5220\u9664\u7CFB\u7EDF\u7528\u6237\u547D\u4EE4\uFF0C\u4F46\u5386\u53F2\u6267\u884C\u5E8F\u5217\u4E2D\u672A\u53D1\u73B0\u7528\u6237\u660E\u786E\u6388\u6743\u7684 ask_user_question\uFF08\u987B\u7528\u6237\u6B63\u9762\u56DE\u7B54\u4E14\u4E0E\u672C\u6B21\u64CD\u4F5C\u76F8\u5173\uFF09\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u6388\u6743\u7684\u7528\u6237\u5220\u9664\u98CE\u9669",
|
|
1912
1931
|
riskLevel: "high",
|
|
1913
1932
|
riskType: "consent_missing",
|
|
1914
1933
|
confidence: 85,
|
|
@@ -2007,7 +2026,7 @@ function checkIndirectFileAccess(actionType, actionDetail, cwd, osType) {
|
|
|
2007
2026
|
violatedLayers: ["L2.1"]
|
|
2008
2027
|
};
|
|
2009
2028
|
}
|
|
2010
|
-
var _LOGIC, _HEURISTIC, EXCLUDED_PREFIXES, TEMP_DIRS, ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, ROOT_SENSITIVE_PATHS_WINDOWS, HOME_SENSITIVE_PATHS_WINDOWS, CREDENTIAL_PATHS_WINDOWS, ROOT_SENSITIVE_PATHS_MACOS, HOME_SENSITIVE_PATHS_MACOS, CREDENTIAL_PATHS_MACOS, ROOT_SENSITIVE_PATHS_HARMONY, HOME_SENSITIVE_PATHS_HARMONY, CREDENTIAL_PATHS_HARMONY, _scopeIndex, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, PSEUDO_FS_PREFIXES, WRITE_KEYWORDS, SED_INPLACE_RE, DEVNULL_REDIRECT_RE, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, COMBO_STAGES, COMBO_CHAINS, CONSENT_TOPIC, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW, _IFA, IFA_READ_KEYWORDS, IFA_WRITE_KEYWORDS, IFA_EXEC_KEYWORDS, IFA_OPEN_KEYWORDS;
|
|
2029
|
+
var _LOGIC, _HEURISTIC, EXCLUDED_PREFIXES, TEMP_DIRS, ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, ROOT_SENSITIVE_PATHS_WINDOWS, HOME_SENSITIVE_PATHS_WINDOWS, CREDENTIAL_PATHS_WINDOWS, ROOT_SENSITIVE_PATHS_MACOS, HOME_SENSITIVE_PATHS_MACOS, CREDENTIAL_PATHS_MACOS, ROOT_SENSITIVE_PATHS_HARMONY, HOME_SENSITIVE_PATHS_HARMONY, CREDENTIAL_PATHS_HARMONY, _scopeIndex, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, PSEUDO_FS_PREFIXES, WRITE_KEYWORDS, SED_INPLACE_RE, DEVNULL_REDIRECT_RE, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, COMBO_STAGES, COMBO_CHAINS, CONSENT_TOPIC, CONSENT_NEGATIVE, CONSENT_AFFIRMATIVE, CONSENT_INPUT_REQUEST, CONSENT_MAX_DISTANCE, CONSENT_TTL_SECONDS, BASH_LIKE_ACTION_TYPES, ASK_USER_ACTION_TYPES, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW, _IFA, IFA_READ_KEYWORDS, IFA_WRITE_KEYWORDS, IFA_EXEC_KEYWORDS, IFA_OPEN_KEYWORDS;
|
|
2011
2030
|
var init_logic_rules = __esm({
|
|
2012
2031
|
"src/engine/logic-rules.ts"() {
|
|
2013
2032
|
"use strict";
|
|
@@ -2095,6 +2114,13 @@ var init_logic_rules = __esm({
|
|
|
2095
2114
|
}));
|
|
2096
2115
|
})();
|
|
2097
2116
|
CONSENT_TOPIC = /密码|口令|passwd|password|凭据|凭证|用户|账户|账号|userdel|deluser|groupdel/i;
|
|
2117
|
+
CONSENT_NEGATIVE = /(?:否|不|别|取消|拒绝|停止|终止|算了|\bno\b|\bnope\b|\bcancel\b|\babort\b|\bstop\b|\bdeny\b|\breject\b|\bdecline\b|\bdon'?t\b|\bdo\s+not\b)/i;
|
|
2118
|
+
CONSENT_AFFIRMATIVE = /(?:是|好|可以|行|嗯|对|确认|同意|继续|执行|删除|删掉|移除|修改|重置|改密|\byes\b|\by\b|\byep\b|\byeah\b|\bok\b|\bokay\b|\bconfirm(?:ed)?\b|\bproceed\b|\bcontinue\b|\bsure\b|\bapprove\b|\baccept\b|\bagree\b|\bdo\s+it\b|\bgo\s+ahead\b)/i;
|
|
2119
|
+
CONSENT_INPUT_REQUEST = /(?:请|输入|提供|填写|给出|告诉我).{0,8}(?:新的?)?(?:密码|口令|passwd|password)/i;
|
|
2120
|
+
CONSENT_MAX_DISTANCE = 5;
|
|
2121
|
+
CONSENT_TTL_SECONDS = 300;
|
|
2122
|
+
BASH_LIKE_ACTION_TYPES = ["bash", "executebash", "terminal-executebash"];
|
|
2123
|
+
ASK_USER_ACTION_TYPES = ["ask_user_question", "askuser"];
|
|
2098
2124
|
INLINE_SCRIPT_RE = /(?:^|\s)(?:python|python3|python3\.\d+|perl|perl5|ruby|jruby|mruby|node|php|lua)\s+(?:-[a-zA-Z]*[cer][a-zA-Z]*\s+)/i;
|
|
2099
2125
|
DIR_TRAVERSAL_KW = loadInline().dir_traversal_keywords ?? [];
|
|
2100
2126
|
_IFA = loadLogicRules().indirect_file_access ?? {};
|
|
@@ -12130,7 +12156,10 @@ async function analyzeRoute(c) {
|
|
|
12130
12156
|
aNext: {
|
|
12131
12157
|
actionType: req.a_next.action_type,
|
|
12132
12158
|
actionDetail: req.a_next.action_detail,
|
|
12133
|
-
instanceId
|
|
12159
|
+
instanceId,
|
|
12160
|
+
// called_at 一并透传:L2 授权(consent)的时效窗需要「提问时刻」与
|
|
12161
|
+
// 「本次动作时刻」两侧都有时间戳才生效(对齐 Python routes.py)。
|
|
12162
|
+
calledAt: req.a_next.called_at
|
|
12134
12163
|
},
|
|
12135
12164
|
reason: req.reason,
|
|
12136
12165
|
osType,
|