@kenhkl/agent-moss 0.10.2 → 0.10.4
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 +139 -22
- package/dist/cli.js.map +1 -1
- package/dist/engine/coordinator.js +131 -20
- package/dist/engine/coordinator.js.map +1 -1
- package/dist/server.js +139 -22
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -411,6 +411,27 @@ var init_inline_analyzer = __esm({
|
|
|
411
411
|
|
|
412
412
|
// src/engine/logic-rules.ts
|
|
413
413
|
import * as fs2 from "fs";
|
|
414
|
+
function isWriteOperation(actionType, actionDetail, writeKeywords = WRITE_KEYWORDS) {
|
|
415
|
+
if (writeKeywords.some((kw) => actionType.includes(kw) || actionDetail.includes(kw))) return true;
|
|
416
|
+
if (WRITE_COMMAND_RES.some((rx) => rx.test(actionDetail))) return true;
|
|
417
|
+
if (/\bsed\s+-[a-zA-Z]*i/i.test(actionDetail)) return true;
|
|
418
|
+
if (actionDetail.includes(">")) {
|
|
419
|
+
const detailWithoutDevnull = actionDetail.replace(DEVNULL_REDIRECT_RE, "");
|
|
420
|
+
if (detailWithoutDevnull.includes(">")) {
|
|
421
|
+
const firstWord = actionDetail.trim().split(/\s+/)[0]?.toLowerCase() || "";
|
|
422
|
+
if (!READ_ONLY_COMMANDS.has(firstWord)) return true;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
function matchDangerousAction(actionDetail, action) {
|
|
428
|
+
if (/[^\x00-\x7f]/.test(action)) {
|
|
429
|
+
return actionDetail.includes(action);
|
|
430
|
+
}
|
|
431
|
+
const escaped = action.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
432
|
+
const re = new RegExp(`(?<![-\\w])${escaped}\\b`, "i");
|
|
433
|
+
return re.test(actionDetail);
|
|
434
|
+
}
|
|
414
435
|
function runLogicCheck(input) {
|
|
415
436
|
const { actionHistory, aNext, cwd } = input;
|
|
416
437
|
const actionDetail = aNext.actionDetail.toLowerCase();
|
|
@@ -425,7 +446,7 @@ function runLogicCheck(input) {
|
|
|
425
446
|
const promptLower = input.promptSession.toLowerCase();
|
|
426
447
|
for (const pattern of INTENT_DEVIATION_PATTERNS) {
|
|
427
448
|
const intentMatched = pattern.intentKeywords.some((kw) => promptLower.includes(kw));
|
|
428
|
-
const dangerousMatched = pattern.dangerousActions.some((kw) => actionDetail
|
|
449
|
+
const dangerousMatched = pattern.dangerousActions.some((kw) => matchDangerousAction(actionDetail, kw));
|
|
429
450
|
if (intentMatched && dangerousMatched) {
|
|
430
451
|
return {
|
|
431
452
|
allowed: false,
|
|
@@ -480,16 +501,7 @@ function checkReadBeforeWrite(actionType, actionDetail, actionHistory, reason, c
|
|
|
480
501
|
if (NON_WRITE_TOOL_PREFIXES.some((p) => actionType.startsWith(p))) return null;
|
|
481
502
|
if (NON_WRITE_TOOLS.has(actionType)) return null;
|
|
482
503
|
const isBashLike = actionType === "bash" || actionType === "executebash" || actionType === "terminal-executebash";
|
|
483
|
-
|
|
484
|
-
if (!isWrite && actionDetail.includes(">")) {
|
|
485
|
-
const detailWithoutDevnull = actionDetail.replace(/(?:2|&|1)?\s*>\s*\/dev\/null\b/g, "");
|
|
486
|
-
if (detailWithoutDevnull.includes(">")) {
|
|
487
|
-
const firstWord = actionDetail.split(/\s/)[0]?.toLowerCase() || "";
|
|
488
|
-
if (!READ_ONLY_REDIR_CMDS.has(firstWord)) {
|
|
489
|
-
isWrite = true;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
504
|
+
const isWrite = isBashLike ? isWriteOperation(actionType, actionDetail) : WRITE_KEYWORDS.some((kw) => actionType.includes(kw));
|
|
493
505
|
if (!isWrite) return null;
|
|
494
506
|
const targetPaths = extractFilePaths(actionDetail);
|
|
495
507
|
if (targetPaths.length === 0) return null;
|
|
@@ -646,7 +658,7 @@ function checkIndirectFileAccess(actionType, actionDetail, cwd) {
|
|
|
646
658
|
violatedLayers: ["2"]
|
|
647
659
|
};
|
|
648
660
|
}
|
|
649
|
-
var ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES,
|
|
661
|
+
var ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS, CREDENTIAL_PATHS, NON_WRITE_TOOLS, NON_WRITE_TOOL_PREFIXES, WRITE_KEYWORDS, WRITE_COMMAND_RES, READ_ONLY_COMMANDS, DEVNULL_REDIRECT_RE, READ_KEYWORDS, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW;
|
|
650
662
|
var init_logic_rules = __esm({
|
|
651
663
|
"src/engine/logic-rules.ts"() {
|
|
652
664
|
"use strict";
|
|
@@ -718,8 +730,105 @@ var init_logic_rules = __esm({
|
|
|
718
730
|
"cat"
|
|
719
731
|
]);
|
|
720
732
|
NON_WRITE_TOOL_PREFIXES = ["memory-", "skill-manager-", "mailbox-", "app-"];
|
|
721
|
-
READ_ONLY_REDIR_CMDS = /* @__PURE__ */ new Set(["cat", "head", "tail", "less", "more", "grep", "find", "awk", "sed", "sort", "uniq", "wc", "cut", "strings", "od", "xxd", "hexdump"]);
|
|
722
733
|
WRITE_KEYWORDS = ["write", "\u5199\u5165", "save", "\u4FDD\u5B58", "modify", "\u4FEE\u6539", "update", "\u66F4\u65B0", "delete", "\u5220\u9664", "remove", "\u79FB\u9664", "create", "\u521B\u5EFA", "append", "\u8FFD\u52A0", "truncate", "\u622A\u65AD", "overwrite", "\u8986\u76D6", "replace", "\u66FF\u6362"];
|
|
734
|
+
WRITE_COMMAND_RES = [
|
|
735
|
+
/\brm\b/,
|
|
736
|
+
/\bunlink\b/,
|
|
737
|
+
/\brmdir\b/,
|
|
738
|
+
/\bshred\b/,
|
|
739
|
+
/\bcp\b/,
|
|
740
|
+
/\bmv\b/,
|
|
741
|
+
/\binstall\b/,
|
|
742
|
+
/\btee\b/,
|
|
743
|
+
/\bdd\b/,
|
|
744
|
+
/\bmkfs\b/,
|
|
745
|
+
/\b(fdisk|parted|cfdisk|sfdisk)\b/,
|
|
746
|
+
/\bchmod\b/,
|
|
747
|
+
/\bchown\b/,
|
|
748
|
+
/\btruncate\b/
|
|
749
|
+
];
|
|
750
|
+
READ_ONLY_COMMANDS = /* @__PURE__ */ new Set([
|
|
751
|
+
"cat",
|
|
752
|
+
"head",
|
|
753
|
+
"tail",
|
|
754
|
+
"less",
|
|
755
|
+
"more",
|
|
756
|
+
"grep",
|
|
757
|
+
"find",
|
|
758
|
+
"awk",
|
|
759
|
+
"sed",
|
|
760
|
+
"sort",
|
|
761
|
+
"uniq",
|
|
762
|
+
"wc",
|
|
763
|
+
"cut",
|
|
764
|
+
"strings",
|
|
765
|
+
"od",
|
|
766
|
+
"xxd",
|
|
767
|
+
"hexdump",
|
|
768
|
+
"tr",
|
|
769
|
+
"file",
|
|
770
|
+
"stat",
|
|
771
|
+
"du",
|
|
772
|
+
"df",
|
|
773
|
+
"ls",
|
|
774
|
+
"dir",
|
|
775
|
+
"tree",
|
|
776
|
+
"nl",
|
|
777
|
+
"tac",
|
|
778
|
+
"rev",
|
|
779
|
+
"lsblk",
|
|
780
|
+
"blockdev",
|
|
781
|
+
"smartctl",
|
|
782
|
+
"udevadm",
|
|
783
|
+
"dmidecode",
|
|
784
|
+
"lscpu",
|
|
785
|
+
"lspci",
|
|
786
|
+
"lsusb",
|
|
787
|
+
"lsmem",
|
|
788
|
+
"lsns",
|
|
789
|
+
"lsof",
|
|
790
|
+
"hwinfo",
|
|
791
|
+
"inxi",
|
|
792
|
+
"fdisk",
|
|
793
|
+
"parted",
|
|
794
|
+
"dmesg",
|
|
795
|
+
"journalctl",
|
|
796
|
+
"systemctl",
|
|
797
|
+
"hostnamectl",
|
|
798
|
+
"localectl",
|
|
799
|
+
"timedatectl",
|
|
800
|
+
"ps",
|
|
801
|
+
"top",
|
|
802
|
+
"free",
|
|
803
|
+
"vmstat",
|
|
804
|
+
"iostat",
|
|
805
|
+
"mpstat",
|
|
806
|
+
"pidof",
|
|
807
|
+
"pgrep",
|
|
808
|
+
"ip",
|
|
809
|
+
"ifconfig",
|
|
810
|
+
"route",
|
|
811
|
+
"ss",
|
|
812
|
+
"netstat",
|
|
813
|
+
"arp",
|
|
814
|
+
"ethtool",
|
|
815
|
+
"nmcli",
|
|
816
|
+
"uname",
|
|
817
|
+
"arch",
|
|
818
|
+
"nproc",
|
|
819
|
+
"getconf",
|
|
820
|
+
"getent",
|
|
821
|
+
"id",
|
|
822
|
+
"whoami",
|
|
823
|
+
"who",
|
|
824
|
+
"w",
|
|
825
|
+
"last",
|
|
826
|
+
"uptime",
|
|
827
|
+
"lsmod",
|
|
828
|
+
"modinfo",
|
|
829
|
+
"sysctl"
|
|
830
|
+
]);
|
|
831
|
+
DEVNULL_REDIRECT_RE = /(?:2|&|1)?\s*>\s*\/dev\/null\b/;
|
|
723
832
|
READ_KEYWORDS = ["read", "\u8BFB\u53D6", "cat", "head", "tail", "less", "more", "view", "\u67E5\u770B", "open", "\u6253\u5F00", "load", "\u52A0\u8F7D", "grep", "search", "\u641C\u7D22", "find", "\u67E5\u627E"];
|
|
724
833
|
CREATE_KEYWORDS = ["\u521B\u5EFA", "\u65B0\u5EFA", "create", "new file", "touch"];
|
|
725
834
|
PASSWORD_MODIFY_PATTERNS = [
|
|
@@ -741,7 +850,7 @@ var init_logic_rules = __esm({
|
|
|
741
850
|
INTENT_DEVIATION_PATTERNS = [
|
|
742
851
|
{
|
|
743
852
|
intentKeywords: ["\u8BFB\u53D6", "\u67E5\u770B", "\u5206\u6790", "read", "analyze", "view", "list", "\u5217\u51FA"],
|
|
744
|
-
dangerousActions: ["\u5220\u9664", "remove", "delete", "rm
|
|
853
|
+
dangerousActions: ["\u5220\u9664", "remove", "delete", "rm", "\u683C\u5F0F\u5316", "format"],
|
|
745
854
|
reason: "\u539F\u59CB\u610F\u56FE\u4E3A\u8BFB\u53D6/\u5206\u6790\uFF0C\u4F46\u6267\u884C\u4E86\u5220\u9664\u64CD\u4F5C"
|
|
746
855
|
},
|
|
747
856
|
{
|
|
@@ -1961,12 +2070,14 @@ function severityRank(s) {
|
|
|
1961
2070
|
}
|
|
1962
2071
|
function checkSensitivePath(command, cwd, agentExt) {
|
|
1963
2072
|
const expandedCwd = cwd.replace(/^~/, process.env.HOME || "/home/user");
|
|
1964
|
-
const
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
|
|
2073
|
+
const isWriteOpFlag = isWriteOperation("", command);
|
|
2074
|
+
const pathMatches = (text, path3) => {
|
|
2075
|
+
const escaped = path3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2076
|
+
const re = path3.startsWith(".") || path3.startsWith("/") ? new RegExp(`(?:^|[\\s/\\\\'"])${escaped}\\b`, "i") : new RegExp(`\\b${escaped}\\b`, "i");
|
|
2077
|
+
return re.test(text);
|
|
2078
|
+
};
|
|
1968
2079
|
for (const sp of ROOT_SENSITIVE_PATHS) {
|
|
1969
|
-
if (command
|
|
2080
|
+
if (pathMatches(command, sp.path.toLowerCase())) {
|
|
1970
2081
|
if (sp.path === "/dev/random") {
|
|
1971
2082
|
if (isWriteOpFlag) {
|
|
1972
2083
|
continue;
|
|
@@ -2020,7 +2131,7 @@ function checkSensitivePath(command, cwd, agentExt) {
|
|
|
2020
2131
|
for (const sp of agentExt.extra_sensitive_paths) {
|
|
2021
2132
|
const spPath = sp.path.toLowerCase();
|
|
2022
2133
|
const expanded = `${expandedCwd}/${spPath}`;
|
|
2023
|
-
if (command
|
|
2134
|
+
if (pathMatches(command, spPath) || pathMatches(command, expanded.toLowerCase())) {
|
|
2024
2135
|
const denyMode = sp.deny_mode || (sp.credential ? "deny_both" : sp.read_only ? "deny_read" : "deny_write");
|
|
2025
2136
|
if (denyMode === "deny_read") {
|
|
2026
2137
|
if (isWriteOpFlag) continue;
|
|
@@ -3278,7 +3389,11 @@ var AnalyzeResponseSchema = z.object({
|
|
|
3278
3389
|
});
|
|
3279
3390
|
var HealthResponseSchema = z.object({
|
|
3280
3391
|
status: z.string().default("healthy"),
|
|
3281
|
-
version: z.string().default(version)
|
|
3392
|
+
version: z.string().default(version),
|
|
3393
|
+
// 归属实例标识:值来自 env AGENT_MOSS_INSTANCE(spawn/systemd 注入),默认空串。
|
|
3394
|
+
// 多个 agentmoss 同机并存时,调用方按 instance 过滤避免连到别人的进程。
|
|
3395
|
+
// 空=未配置(独立部署或旧版),调用方可选择兼容或严格过滤。
|
|
3396
|
+
instance: z.string().default("")
|
|
3282
3397
|
});
|
|
3283
3398
|
|
|
3284
3399
|
// src/engine/coordinator.ts
|
|
@@ -4652,7 +4767,9 @@ function reportEnforcementEvent(opts) {
|
|
|
4652
4767
|
|
|
4653
4768
|
// src/routes.ts
|
|
4654
4769
|
async function healthRoute(c) {
|
|
4655
|
-
return c.json(HealthResponseSchema.parse({
|
|
4770
|
+
return c.json(HealthResponseSchema.parse({
|
|
4771
|
+
instance: process.env.AGENT_MOSS_INSTANCE || ""
|
|
4772
|
+
}));
|
|
4656
4773
|
}
|
|
4657
4774
|
async function analyzeRoute(c) {
|
|
4658
4775
|
const t0 = performance.now();
|