@kenhkl/agent-moss 0.10.3 → 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/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.includes(kw));
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
- let isWrite = isBashLike ? WRITE_KEYWORDS.some((kw) => actionType.includes(kw) || actionDetail.includes(kw)) : WRITE_KEYWORDS.some((kw) => actionType.includes(kw));
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, READ_ONLY_REDIR_CMDS, WRITE_KEYWORDS, READ_KEYWORDS, CREATE_KEYWORDS, PASSWORD_MODIFY_PATTERNS, USER_DELETION_PATTERNS, INTENT_DEVIATION_PATTERNS, INLINE_SCRIPT_RE, DIR_TRAVERSAL_KW;
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 ", "\u683C\u5F0F\u5316", "format"],
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 _WRITE_CMD_RES = [/\brm\b/, /\bunlink\b/, /\brmdir\b/, /\bshred\b/, /\bcp\b/, /\bmv\b/, /\binstall\b/, /\btee\b/, /\bdd\b/, /\bmkfs\b/, /\b(fdisk|parted|cfdisk|sfdisk)\b/, /\bchmod\b/, /\bchown\b/, /\btruncate\b/];
1965
- const _DEVNULL_RE = /(?:2|&|1)?\s*>\s*\/dev\/null\b/;
1966
- const _READONLY_CMDS = /* @__PURE__ */ new Set(["cat", "head", "tail", "less", "more", "grep", "find", "awk", "sed", "sort", "uniq", "wc", "cut", "strings", "od", "xxd", "hexdump", "tr", "file", "stat", "du", "df", "ls", "dir", "tree", "nl", "tac", "rev", "lsblk", "blockdev", "smartctl", "udevadm", "dmidecode", "lscpu", "lspci", "lsusb", "lsmem", "lsns", "lsof", "hwinfo", "inxi", "fdisk", "parted", "dmesg", "journalctl", "systemctl", "hostnamectl", "localectl", "timedatectl", "ps", "top", "free", "vmstat", "iostat", "mpstat", "pidof", "pgrep", "ip", "ifconfig", "route", "ss", "netstat", "arp", "ethtool", "nmcli", "uname", "arch", "nproc", "getconf", "getent", "id", "whoami", "who", "w", "last", "uptime", "lsmod", "modinfo", "sysctl"]);
1967
- const isWriteOpFlag = _WRITE_CMD_RES.some((rx) => rx.test(command)) || /\bsed\s+-[a-zA-Z]*i/.test(command) || command.includes(">") && !command.replace(_DEVNULL_RE, "").includes(">") || command.includes(">") && command.replace(_DEVNULL_RE, "").includes(">") && !_READONLY_CMDS.has(command.trim().split(/\s+/)[0]?.toLowerCase() || "") || WRITE_KEYWORDS.some((kw) => "".includes(kw) || command.includes(kw));
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.includes(sp.path.toLowerCase())) {
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.includes(spPath) || command.includes(expanded.toLowerCase())) {
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;