@kenhkl/agent-moss 0.2.0
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.d.ts +1 -0
- package/dist/cli.js +624 -0
- package/dist/cli.js.map +1 -0
- package/package.json +34 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// node_modules/tsup/assets/esm_shims.js
|
|
13
|
+
import path from "path";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
var init_esm_shims = __esm({
|
|
16
|
+
"node_modules/tsup/assets/esm_shims.js"() {
|
|
17
|
+
"use strict";
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// src/engine/heuristic.ts
|
|
22
|
+
function runHeuristicCheck(input) {
|
|
23
|
+
const command = `${input.aNext.actionType}: ${input.aNext.actionDetail}`;
|
|
24
|
+
const matched = [];
|
|
25
|
+
let highestSeverity = "low";
|
|
26
|
+
for (const rule of DANGEROUS_PATTERNS) {
|
|
27
|
+
if (rule.pattern.test(command)) {
|
|
28
|
+
matched.push(rule.description);
|
|
29
|
+
if (severityRank(rule.severity) > severityRank(highestSeverity)) {
|
|
30
|
+
highestSeverity = rule.severity;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (matched.length > 0) {
|
|
35
|
+
return {
|
|
36
|
+
allowed: false,
|
|
37
|
+
reason: `\u68C0\u6D4B\u5230\u9AD8\u5371\u64CD\u4F5C: ${matched.join(", ")}`,
|
|
38
|
+
riskLevel: highestSeverity,
|
|
39
|
+
riskType: "dangerous_command",
|
|
40
|
+
confidence: 95,
|
|
41
|
+
source: "heuristic",
|
|
42
|
+
violatedLayers: ["1"]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function severityRank(s) {
|
|
48
|
+
const ranks = { low: 1, medium: 2, high: 3, critical: 4 };
|
|
49
|
+
return ranks[s] || 0;
|
|
50
|
+
}
|
|
51
|
+
var DANGEROUS_PATTERNS;
|
|
52
|
+
var init_heuristic = __esm({
|
|
53
|
+
"src/engine/heuristic.ts"() {
|
|
54
|
+
"use strict";
|
|
55
|
+
init_esm_shims();
|
|
56
|
+
DANGEROUS_PATTERNS = [
|
|
57
|
+
{ pattern: /rm\s+-rf\s+\/\s*$|rm\s+-rf\s+\/\*/, severity: "critical", description: "\u9012\u5F52\u5F3A\u5236\u5220\u9664\u6839\u76EE\u5F55" },
|
|
58
|
+
{ pattern: /rm\s+-rf\s+\/home\/\*|rm\s+-rf\s+\/root/, severity: "critical", description: "\u5220\u9664\u7528\u6237\u4E3B\u76EE\u5F55" },
|
|
59
|
+
{ pattern: /rm\s+-rf\s+\/etc|rm\s+-rf\s+\/var/, severity: "critical", description: "\u5220\u9664\u7CFB\u7EDF\u76EE\u5F55" },
|
|
60
|
+
{ pattern: /curl\s+.*\|\s*(bash|sh|zsh)/, severity: "critical", description: "curl pipe shell \u6267\u884C" },
|
|
61
|
+
{ pattern: /wget\s+.*\|\s*(bash|sh)/, severity: "critical", description: "wget pipe shell \u6267\u884C" },
|
|
62
|
+
{ pattern: />\s*\/dev\/sda|dd\s+if=.*of=\/dev\//, severity: "critical", description: "\u78C1\u76D8\u76F4\u63A5\u5199\u5165" },
|
|
63
|
+
{ pattern: /mkfs\./, severity: "critical", description: "\u683C\u5F0F\u5316\u6587\u4EF6\u7CFB\u7EDF" },
|
|
64
|
+
{ pattern: /chmod\s+777\s+\//, severity: "high", description: "\u4FEE\u6539\u6839\u76EE\u5F55\u6743\u9650\u4E3A777" },
|
|
65
|
+
{ pattern: /chown\s+-R\s+\w+:\w+\s+\//, severity: "high", description: "\u9012\u5F52\u4FEE\u6539\u6839\u76EE\u5F55\u6240\u6709\u8005" },
|
|
66
|
+
{ pattern: /eval\s+\$\(curl|eval\s+\$\(wget/, severity: "critical", description: "eval \u8FDC\u7A0B\u4EE3\u7801\u6267\u884C" },
|
|
67
|
+
{ pattern: /\/dev\/tcp\/|bash\s+-i\s+>&/, severity: "critical", description: "\u53CD\u5F39 Shell" },
|
|
68
|
+
{ pattern: /nc\s+-[el]\s+.*\d{1,5}/, severity: "high", description: "Netcat \u53CD\u5F39\u8FDE\u63A5" },
|
|
69
|
+
{ pattern: /:\(\)\s*\{.*:\|:&.*\};:/, severity: "critical", description: "Fork Bomb" },
|
|
70
|
+
{ pattern: /sudo\s+rm\s+-rf/, severity: "high", description: "sudo \u5F3A\u5236\u5220\u9664" },
|
|
71
|
+
{ pattern: /git\s+clone\s+.*\|.*bash/, severity: "high", description: "git clone pipe shell" },
|
|
72
|
+
{ pattern: /pip\s+install\s+.*\|\s*bash/, severity: "high", description: "pip install pipe shell" },
|
|
73
|
+
{ pattern: /npm\s+install\s+-g\s+.*\|\s*bash/, severity: "high", description: "npm install pipe shell" },
|
|
74
|
+
{ pattern: /export\s+.*(?:TOKEN|KEY|SECRET|PASSWORD)/i, severity: "medium", description: "\u5BFC\u51FA\u654F\u611F\u51ED\u8BC1" },
|
|
75
|
+
{ pattern: /base64\s+-d\s+.*\|\s*bash/, severity: "critical", description: "base64 \u89E3\u7801\u6267\u884C" }
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// src/engine/logic-rules.ts
|
|
81
|
+
function runLogicCheck(input) {
|
|
82
|
+
const { actionHistory, aNext, cwd } = input;
|
|
83
|
+
const command = aNext.actionDetail;
|
|
84
|
+
const resolvedCwd = cwd || "/";
|
|
85
|
+
if (aNext.actionType === "write" || aNext.actionType === "file_write" || aNext.actionType === "write_to_file") {
|
|
86
|
+
const hadRead = actionHistory.some(
|
|
87
|
+
(h) => (h.actionType === "read" || h.actionType === "file_read" || h.actionType === "read_file") && h.actionDetail.includes(cwd)
|
|
88
|
+
);
|
|
89
|
+
if (!hadRead && actionHistory.length === 0) {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (containsSensitivePath(command, resolvedCwd)) {
|
|
93
|
+
return {
|
|
94
|
+
allowed: false,
|
|
95
|
+
reason: "\u5C1D\u8BD5\u8BBF\u95EE\u7CFB\u7EDF\u654F\u611F\u8DEF\u5F84",
|
|
96
|
+
riskLevel: "high",
|
|
97
|
+
riskType: "sensitive_path_access",
|
|
98
|
+
confidence: 90,
|
|
99
|
+
source: "logic_rule",
|
|
100
|
+
violatedLayers: ["2"]
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (command.includes("sudo") || command.includes("su -") || command.includes("chmod u+s") || command.includes("setuid")) {
|
|
104
|
+
const adminContext = actionHistory.some(
|
|
105
|
+
(h) => h.actionDetail.includes("sudo") || h.actionDetail.includes("apt") || h.actionDetail.includes("systemctl")
|
|
106
|
+
);
|
|
107
|
+
if (!adminContext && actionHistory.length === 0) {
|
|
108
|
+
return {
|
|
109
|
+
allowed: false,
|
|
110
|
+
reason: "\u68C0\u6D4B\u5230\u63D0\u6743\u64CD\u4F5C\uFF0C\u672A\u53D1\u73B0\u5408\u6CD5\u7BA1\u7406\u4E0A\u4E0B\u6587",
|
|
111
|
+
riskLevel: "high",
|
|
112
|
+
riskType: "privilege_escalation",
|
|
113
|
+
confidence: 85,
|
|
114
|
+
source: "logic_rule",
|
|
115
|
+
violatedLayers: ["2"]
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (command.includes("ssh") || command.includes("scp") || command.includes("rsync")) {
|
|
120
|
+
const targetHost = extractRemoteHost(command);
|
|
121
|
+
if (targetHost && !isLocalHost(targetHost)) {
|
|
122
|
+
return {
|
|
123
|
+
allowed: false,
|
|
124
|
+
reason: `\u5C1D\u8BD5\u6A2A\u5411\u79FB\u52A8\u5230\u8FDC\u7A0B\u4E3B\u673A: ${targetHost}`,
|
|
125
|
+
riskLevel: "medium",
|
|
126
|
+
riskType: "lateral_movement",
|
|
127
|
+
confidence: 80,
|
|
128
|
+
source: "logic_rule",
|
|
129
|
+
violatedLayers: ["2"]
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
function containsSensitivePath(command, cwd) {
|
|
136
|
+
const expandedCwd = cwd.replace(/^~/, process.env.HOME || "/home/user");
|
|
137
|
+
for (const p of ROOT_SENSITIVE_PATHS) {
|
|
138
|
+
if (command.includes(p)) return true;
|
|
139
|
+
}
|
|
140
|
+
for (const p of HOME_SENSITIVE_PATHS) {
|
|
141
|
+
if (command.includes(p) || command.includes(`${expandedCwd}/${p}`)) return true;
|
|
142
|
+
}
|
|
143
|
+
if ((command.includes("rm ") || command.includes("unlink")) && (command.includes("/etc/") || command.includes("/root/") || command.includes("/var/log/"))) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
function extractRemoteHost(command) {
|
|
149
|
+
const m = command.match(/(?:ssh|scp|rsync)\s+(?:-[\w]+\s+)*(\S+@\S+|\b(?!-)[\w.-]+\b)/);
|
|
150
|
+
return m ? m[1] : null;
|
|
151
|
+
}
|
|
152
|
+
function isLocalHost(host) {
|
|
153
|
+
const localNames = ["localhost", "127.0.0.1", "::1", process.env.HOSTNAME || "", "0.0.0.0"];
|
|
154
|
+
return localNames.includes(host.replace(/.*@/, ""));
|
|
155
|
+
}
|
|
156
|
+
var ROOT_SENSITIVE_PATHS, HOME_SENSITIVE_PATHS;
|
|
157
|
+
var init_logic_rules = __esm({
|
|
158
|
+
"src/engine/logic-rules.ts"() {
|
|
159
|
+
"use strict";
|
|
160
|
+
init_esm_shims();
|
|
161
|
+
ROOT_SENSITIVE_PATHS = [
|
|
162
|
+
"/etc/shadow",
|
|
163
|
+
"/etc/passwd",
|
|
164
|
+
"/etc/sudoers",
|
|
165
|
+
"/root/.ssh",
|
|
166
|
+
"/root/.bashrc",
|
|
167
|
+
"/boot",
|
|
168
|
+
"/sys",
|
|
169
|
+
"/proc"
|
|
170
|
+
];
|
|
171
|
+
HOME_SENSITIVE_PATHS = [
|
|
172
|
+
".ssh/id_rsa",
|
|
173
|
+
".ssh/authorized_keys",
|
|
174
|
+
".aws/credentials",
|
|
175
|
+
".gitconfig",
|
|
176
|
+
".gnupg"
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// src/config.ts
|
|
182
|
+
function getLLMConfig() {
|
|
183
|
+
return llmConfig;
|
|
184
|
+
}
|
|
185
|
+
function isLLMAvailable() {
|
|
186
|
+
return llmConfig.apiKey.length > 0;
|
|
187
|
+
}
|
|
188
|
+
var llmConfig;
|
|
189
|
+
var init_config = __esm({
|
|
190
|
+
"src/config.ts"() {
|
|
191
|
+
"use strict";
|
|
192
|
+
init_esm_shims();
|
|
193
|
+
llmConfig = {
|
|
194
|
+
provider: "openai",
|
|
195
|
+
baseUrl: process.env.AGENT_MOSS_LLM_BASE_URL || "https://api.openai.com/v1",
|
|
196
|
+
apiKey: process.env.AGENT_MOSS_LLM_API_KEY || "",
|
|
197
|
+
model: process.env.AGENT_MOSS_LLM_MODEL || "gpt-4o",
|
|
198
|
+
temperature: parseFloat(process.env.AGENT_MOSS_LLM_TEMPERATURE || "0.1"),
|
|
199
|
+
maxTokens: parseInt(process.env.AGENT_MOSS_LLM_MAX_TOKENS || "4096", 10)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// src/engine/skill-loader.ts
|
|
205
|
+
import { readFileSync, readdirSync, existsSync } from "fs";
|
|
206
|
+
import { resolve, dirname } from "path";
|
|
207
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
208
|
+
function loadSkills() {
|
|
209
|
+
if (cachedSkills) return cachedSkills;
|
|
210
|
+
if (!existsSync(SKILLS_DIR)) {
|
|
211
|
+
console.warn("[AgentMoss] Skills directory not found:", SKILLS_DIR);
|
|
212
|
+
cachedSkills = [];
|
|
213
|
+
return cachedSkills;
|
|
214
|
+
}
|
|
215
|
+
const files = readdirSync(SKILLS_DIR).filter((f) => f.endsWith(".md"));
|
|
216
|
+
cachedSkills = files.map((f) => {
|
|
217
|
+
const content = readFileSync(resolve(SKILLS_DIR, f), "utf-8");
|
|
218
|
+
return `### ${f.replace(".md", "")}
|
|
219
|
+
${content}`;
|
|
220
|
+
});
|
|
221
|
+
console.log(`[AgentMoss] Loaded ${cachedSkills.length} skills`);
|
|
222
|
+
return cachedSkills;
|
|
223
|
+
}
|
|
224
|
+
var __filename2, __dirname2, SKILLS_DIR, cachedSkills;
|
|
225
|
+
var init_skill_loader = __esm({
|
|
226
|
+
"src/engine/skill-loader.ts"() {
|
|
227
|
+
"use strict";
|
|
228
|
+
init_esm_shims();
|
|
229
|
+
__filename2 = fileURLToPath2(import.meta.url);
|
|
230
|
+
__dirname2 = dirname(__filename2);
|
|
231
|
+
SKILLS_DIR = resolve(__dirname2, "../../agent_moss/skills");
|
|
232
|
+
cachedSkills = null;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// src/engine/template-loader.ts
|
|
237
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
238
|
+
import { resolve as resolve2, dirname as dirname2 } from "path";
|
|
239
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
240
|
+
function loadTemplates() {
|
|
241
|
+
if (cachedTemplates) return cachedTemplates;
|
|
242
|
+
cachedTemplates = {};
|
|
243
|
+
if (!existsSync2(TEMPLATES_DIR)) {
|
|
244
|
+
console.warn("[AgentMoss] Templates directory not found:", TEMPLATES_DIR);
|
|
245
|
+
return cachedTemplates;
|
|
246
|
+
}
|
|
247
|
+
for (const file of TEMPLATE_FILES) {
|
|
248
|
+
const filePath = resolve2(TEMPLATES_DIR, file);
|
|
249
|
+
if (existsSync2(filePath)) {
|
|
250
|
+
const key = file.replace(".txt", "").replace("_template", "");
|
|
251
|
+
cachedTemplates[key] = readFileSync2(filePath, "utf-8");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
console.log(`[AgentMoss] Loaded ${Object.keys(cachedTemplates).length} templates`);
|
|
255
|
+
return cachedTemplates;
|
|
256
|
+
}
|
|
257
|
+
var __filename3, __dirname3, TEMPLATES_DIR, TEMPLATE_FILES, cachedTemplates;
|
|
258
|
+
var init_template_loader = __esm({
|
|
259
|
+
"src/engine/template-loader.ts"() {
|
|
260
|
+
"use strict";
|
|
261
|
+
init_esm_shims();
|
|
262
|
+
__filename3 = fileURLToPath3(import.meta.url);
|
|
263
|
+
__dirname3 = dirname2(__filename3);
|
|
264
|
+
TEMPLATES_DIR = resolve2(__dirname3, "../../agent_moss/templates");
|
|
265
|
+
TEMPLATE_FILES = ["prompt1_template.txt", "prompt2_template.txt", "security_judge_template.txt"];
|
|
266
|
+
cachedTemplates = null;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// src/engine/llm-analyzer.ts
|
|
271
|
+
import OpenAI from "openai";
|
|
272
|
+
async function runLLMAnalysis(input, previous) {
|
|
273
|
+
if (!isLLMAvailable()) {
|
|
274
|
+
console.log("[AgentMoss] LLM not configured, skipping deep analysis");
|
|
275
|
+
return {
|
|
276
|
+
allowed: true,
|
|
277
|
+
reason: "LLM \u672A\u914D\u7F6E\uFF0C\u8DF3\u8FC7\u6DF1\u5C42\u5206\u6790",
|
|
278
|
+
riskLevel: "low",
|
|
279
|
+
riskType: "",
|
|
280
|
+
confidence: 50,
|
|
281
|
+
source: "llm",
|
|
282
|
+
violatedLayers: []
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const config = getLLMConfig();
|
|
286
|
+
const cacheKey = `${input.aNext.actionType}:${input.aNext.actionDetail}`;
|
|
287
|
+
const cached = llmCache.get(cacheKey);
|
|
288
|
+
if (cached) {
|
|
289
|
+
console.log("[AgentMoss] LLM cache hit");
|
|
290
|
+
return cached;
|
|
291
|
+
}
|
|
292
|
+
const skills = loadSkills();
|
|
293
|
+
const templates = loadTemplates();
|
|
294
|
+
const prompt = buildPrompt(input, previous, skills, templates);
|
|
295
|
+
const result = await analyzeWithLLM(prompt, config);
|
|
296
|
+
if (llmCache.size >= LLM_CACHE_MAX) {
|
|
297
|
+
const firstKey = llmCache.keys().next().value;
|
|
298
|
+
if (firstKey) llmCache.delete(firstKey);
|
|
299
|
+
}
|
|
300
|
+
llmCache.set(cacheKey, result);
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
function buildPrompt(input, previous, skills, templates) {
|
|
304
|
+
const skillContext = skills.length > 0 ? skills.join("\n---\n") : "(\u65E0\u53EF\u7528 Skill)";
|
|
305
|
+
const historyStr = input.actionHistory.map((h, i) => `${i + 1}. [${h.actionType}] ${h.actionDetail}`).join("\n") || "(\u65E0\u5386\u53F2\u64CD\u4F5C)";
|
|
306
|
+
const templateName = previous.heuristic || previous.logic ? "prompt2" : "prompt1";
|
|
307
|
+
const baseTemplate = templates[templateName] || templates["prompt1"] || "";
|
|
308
|
+
return `${baseTemplate}
|
|
309
|
+
|
|
310
|
+
## \u5F53\u524D\u64CD\u4F5C\u4E0A\u4E0B\u6587
|
|
311
|
+
- \u4F1A\u8BDD ID: ${input.sessionId}
|
|
312
|
+
- \u7528\u6237\u4EFB\u52A1: ${input.promptSession || "\u672A\u6307\u5B9A"}
|
|
313
|
+
- \u64CD\u4F5C\u7CFB\u7EDF: ${input.osType}
|
|
314
|
+
- \u5DE5\u4F5C\u76EE\u5F55: ${input.cwd || "/"}
|
|
315
|
+
- \u64CD\u4F5C\u539F\u56E0: ${input.reason || "\u672A\u8BF4\u660E"}
|
|
316
|
+
- \u5386\u53F2\u64CD\u4F5C\u5E8F\u5217:
|
|
317
|
+
${historyStr}
|
|
318
|
+
|
|
319
|
+
- \u5373\u5C06\u6267\u884C\u7684\u64CD\u4F5C:
|
|
320
|
+
\u7C7B\u578B: ${input.aNext.actionType}
|
|
321
|
+
\u8BE6\u60C5: ${input.aNext.actionDetail}
|
|
322
|
+
|
|
323
|
+
## \u53EF\u7528\u5B89\u5168 Skill
|
|
324
|
+
${skillContext}
|
|
325
|
+
|
|
326
|
+
\u8BF7\u6839\u636E\u4EE5\u4E0A\u4FE1\u606F\uFF0C\u5BF9\u5373\u5C06\u6267\u884C\u7684\u64CD\u4F5C\u8FDB\u884C\u5B89\u5168\u5224\u65AD\u3002\u4F60\u5FC5\u987B\u8F93\u51FA\u4E25\u683C\u7684 JSON \u683C\u5F0F\uFF0C
|
|
327
|
+
\u4E0D\u8981\u5305\u542B\u4EFB\u4F55\u5176\u4ED6\u6587\u5B57\u3001\u6CE8\u91CA\u6216 markdown \u6807\u8BB0\u3002
|
|
328
|
+
|
|
329
|
+
\u8F93\u51FA\u683C\u5F0F:
|
|
330
|
+
{"allowed": true/false, "reason": "\u5224\u65AD\u7406\u7531", "riskLevel": "low|medium|high|critical", "riskType": "\u98CE\u9669\u7C7B\u578B", "confidence": 0-100}`;
|
|
331
|
+
}
|
|
332
|
+
async function analyzeWithLLM(prompt, config) {
|
|
333
|
+
console.log(`[AgentMoss] LLM analyzing with model: ${config.model}, url: ${config.baseUrl}`);
|
|
334
|
+
const client = new OpenAI({
|
|
335
|
+
baseURL: config.baseUrl,
|
|
336
|
+
apiKey: config.apiKey,
|
|
337
|
+
timeout: 3e4
|
|
338
|
+
});
|
|
339
|
+
try {
|
|
340
|
+
const response = await client.chat.completions.create({
|
|
341
|
+
model: config.model,
|
|
342
|
+
temperature: config.temperature || 0.1,
|
|
343
|
+
max_tokens: config.maxTokens || 1024,
|
|
344
|
+
messages: [
|
|
345
|
+
{ role: "system", content: "\u4F60\u662F\u4E00\u4E2A AI Agent \u5B89\u5168\u5BA1\u8BA1\u4E13\u5BB6\u3002\u4F60\u7684\u4EFB\u52A1\u662F\u5206\u6790\u5373\u5C06\u6267\u884C\u7684\u547D\u4EE4\u662F\u5426\u5B89\u5168\u3002\u4F60\u5FC5\u987B\u53EA\u8F93\u51FA\u7EAF JSON\uFF0C\u4E0D\u8981\u5305\u542B\u4EFB\u4F55 markdown \u6807\u8BB0\u3001\u4EE3\u7801\u5757\u6216\u5176\u4ED6\u6587\u5B57\u3002" },
|
|
346
|
+
{ role: "user", content: prompt }
|
|
347
|
+
]
|
|
348
|
+
});
|
|
349
|
+
const content = response.choices[0]?.message?.content || "{}";
|
|
350
|
+
console.log(`[AgentMoss] LLM raw response: ${content.substring(0, 300)}`);
|
|
351
|
+
let jsonStr = content.trim();
|
|
352
|
+
if (jsonStr.startsWith("```")) {
|
|
353
|
+
jsonStr = jsonStr.replace(/^```[\w]*\n?/, "").replace(/\n?```$/, "");
|
|
354
|
+
}
|
|
355
|
+
const parsed = JSON.parse(jsonStr);
|
|
356
|
+
return {
|
|
357
|
+
allowed: parsed.allowed !== false,
|
|
358
|
+
// default to Allow if missing
|
|
359
|
+
reason: parsed.reason || "LLM \u5206\u6790\u5B8C\u6210",
|
|
360
|
+
riskLevel: ["low", "medium", "high", "critical"].includes(parsed.riskLevel) ? parsed.riskLevel : "low",
|
|
361
|
+
riskType: parsed.riskType || "",
|
|
362
|
+
confidence: typeof parsed.confidence === "number" ? Math.min(100, Math.max(0, parsed.confidence)) : 70,
|
|
363
|
+
source: "llm",
|
|
364
|
+
violatedLayers: ["3"]
|
|
365
|
+
};
|
|
366
|
+
} catch (err) {
|
|
367
|
+
console.error("[AgentMoss] LLM call failed:", err.message);
|
|
368
|
+
return {
|
|
369
|
+
allowed: true,
|
|
370
|
+
reason: `LLM \u8C03\u7528\u5931\u8D25: ${err.message}`,
|
|
371
|
+
riskLevel: "low",
|
|
372
|
+
riskType: "",
|
|
373
|
+
confidence: 30,
|
|
374
|
+
source: "llm",
|
|
375
|
+
violatedLayers: []
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
var llmCache, LLM_CACHE_MAX;
|
|
380
|
+
var init_llm_analyzer = __esm({
|
|
381
|
+
"src/engine/llm-analyzer.ts"() {
|
|
382
|
+
"use strict";
|
|
383
|
+
init_esm_shims();
|
|
384
|
+
init_config();
|
|
385
|
+
init_skill_loader();
|
|
386
|
+
init_template_loader();
|
|
387
|
+
llmCache = /* @__PURE__ */ new Map();
|
|
388
|
+
LLM_CACHE_MAX = 200;
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// src/engine/coordinator.ts
|
|
393
|
+
var coordinator_exports = {};
|
|
394
|
+
__export(coordinator_exports, {
|
|
395
|
+
runAnalysis: () => runAnalysis
|
|
396
|
+
});
|
|
397
|
+
async function runAnalysis(input) {
|
|
398
|
+
const heuristicResult = runHeuristicCheck(input);
|
|
399
|
+
if (heuristicResult && !heuristicResult.allowed) {
|
|
400
|
+
return heuristicResult;
|
|
401
|
+
}
|
|
402
|
+
const logicResult = runLogicCheck(input);
|
|
403
|
+
if (logicResult && !logicResult.allowed) {
|
|
404
|
+
return logicResult;
|
|
405
|
+
}
|
|
406
|
+
const llmResult = await runLLMAnalysis(input, {
|
|
407
|
+
heuristic: heuristicResult,
|
|
408
|
+
logic: logicResult
|
|
409
|
+
});
|
|
410
|
+
return llmResult;
|
|
411
|
+
}
|
|
412
|
+
var init_coordinator = __esm({
|
|
413
|
+
"src/engine/coordinator.ts"() {
|
|
414
|
+
"use strict";
|
|
415
|
+
init_esm_shims();
|
|
416
|
+
init_heuristic();
|
|
417
|
+
init_logic_rules();
|
|
418
|
+
init_llm_analyzer();
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
// src/cli.ts
|
|
423
|
+
init_esm_shims();
|
|
424
|
+
|
|
425
|
+
// src/server.ts
|
|
426
|
+
init_esm_shims();
|
|
427
|
+
import { Hono } from "hono";
|
|
428
|
+
import { cors } from "hono/cors";
|
|
429
|
+
import { logger } from "hono/logger";
|
|
430
|
+
|
|
431
|
+
// src/routes.ts
|
|
432
|
+
init_esm_shims();
|
|
433
|
+
|
|
434
|
+
// src/models.ts
|
|
435
|
+
init_esm_shims();
|
|
436
|
+
import { z } from "zod";
|
|
437
|
+
var ActionItemSchema = z.object({
|
|
438
|
+
action_type: z.string().describe("Action type, e.g. bash, file_read, file_write"),
|
|
439
|
+
action_detail: z.string().describe("Action detail / command content")
|
|
440
|
+
});
|
|
441
|
+
var AnalyzeRequestSchema = z.object({
|
|
442
|
+
session_id: z.string().describe("Session / agent unique identifier"),
|
|
443
|
+
prompt_session: z.string().default("").describe("User original prompt"),
|
|
444
|
+
action_history: z.array(ActionItemSchema).default([]).describe("Historical action sequence"),
|
|
445
|
+
a_next: ActionItemSchema.describe("Next action to be executed"),
|
|
446
|
+
reason: z.string().default("").describe("Reason for executing this action"),
|
|
447
|
+
os_type: z.string().default("").describe("OS type: 'linux', 'windows', or empty for auto-detect"),
|
|
448
|
+
cwd: z.string().default("").describe("Current working directory"),
|
|
449
|
+
metadata: z.record(z.unknown()).optional().describe("Extended metadata")
|
|
450
|
+
});
|
|
451
|
+
var AnalyzeResponseSchema = z.object({
|
|
452
|
+
decision: z.enum(["Allow", "Deny"]).describe("Allow or Deny"),
|
|
453
|
+
reason: z.string().describe("Decision reason"),
|
|
454
|
+
risk_level: z.enum(["low", "medium", "high", "critical"]).default("low"),
|
|
455
|
+
risk_type: z.string().default(""),
|
|
456
|
+
violated_layers: z.array(z.string()).default([]),
|
|
457
|
+
policy: z.string().default(""),
|
|
458
|
+
violated_policy: z.string().default(""),
|
|
459
|
+
confidence: z.number().int().min(0).max(100).default(100),
|
|
460
|
+
analysis_duration_ms: z.number().default(0)
|
|
461
|
+
});
|
|
462
|
+
var HealthResponseSchema = z.object({
|
|
463
|
+
status: z.string().default("healthy"),
|
|
464
|
+
version: z.string().default("0.2.0")
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
// src/routes.ts
|
|
468
|
+
init_coordinator();
|
|
469
|
+
async function healthRoute(c) {
|
|
470
|
+
return c.json(HealthResponseSchema.parse({}));
|
|
471
|
+
}
|
|
472
|
+
async function analyzeRoute(c) {
|
|
473
|
+
const t0 = performance.now();
|
|
474
|
+
try {
|
|
475
|
+
const body = await c.req.json();
|
|
476
|
+
const req = AnalyzeRequestSchema.parse(body);
|
|
477
|
+
let osType = req.os_type;
|
|
478
|
+
if (!osType) {
|
|
479
|
+
osType = process.platform === "win32" ? "windows" : "linux";
|
|
480
|
+
}
|
|
481
|
+
const result = await runAnalysis({
|
|
482
|
+
sessionId: req.session_id,
|
|
483
|
+
promptSession: req.prompt_session,
|
|
484
|
+
actionHistory: req.action_history.map((h) => ({
|
|
485
|
+
actionType: h.action_type,
|
|
486
|
+
actionDetail: h.action_detail
|
|
487
|
+
})),
|
|
488
|
+
aNext: {
|
|
489
|
+
actionType: req.a_next.action_type,
|
|
490
|
+
actionDetail: req.a_next.action_detail
|
|
491
|
+
},
|
|
492
|
+
reason: req.reason,
|
|
493
|
+
osType,
|
|
494
|
+
cwd: req.cwd
|
|
495
|
+
});
|
|
496
|
+
const durationMs = performance.now() - t0;
|
|
497
|
+
return c.json(
|
|
498
|
+
AnalyzeResponseSchema.parse({
|
|
499
|
+
decision: result.allowed ? "Allow" : "Deny",
|
|
500
|
+
reason: result.reason,
|
|
501
|
+
risk_level: result.riskLevel,
|
|
502
|
+
risk_type: result.riskType,
|
|
503
|
+
violated_layers: result.violatedLayers,
|
|
504
|
+
policy: "",
|
|
505
|
+
violated_policy: "",
|
|
506
|
+
confidence: result.confidence,
|
|
507
|
+
analysis_duration_ms: Math.round(durationMs * 10) / 10
|
|
508
|
+
})
|
|
509
|
+
);
|
|
510
|
+
} catch (err) {
|
|
511
|
+
console.error("[AgentMoss] Analysis error:", err);
|
|
512
|
+
if (err instanceof SyntaxError) {
|
|
513
|
+
return c.json({ error: "Invalid JSON", detail: err.message }, 400);
|
|
514
|
+
}
|
|
515
|
+
if (err?.issues) {
|
|
516
|
+
return c.json({ error: "Validation error", detail: err.issues }, 400);
|
|
517
|
+
}
|
|
518
|
+
return c.json({ error: "Internal error", detail: String(err) }, 500);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// src/server.ts
|
|
523
|
+
function createApp() {
|
|
524
|
+
const app = new Hono();
|
|
525
|
+
app.use("*", cors({ origin: "*", allowMethods: ["GET", "POST", "OPTIONS"], allowHeaders: ["*"] }));
|
|
526
|
+
app.use("*", logger());
|
|
527
|
+
app.get("/api/v1/health", healthRoute);
|
|
528
|
+
app.post("/api/v1/analyze", analyzeRoute);
|
|
529
|
+
return app;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// src/cli.ts
|
|
533
|
+
function printHelp() {
|
|
534
|
+
console.log(`AgentMoss security analysis engine (TypeScript v0.2.0)
|
|
535
|
+
|
|
536
|
+
Commands:
|
|
537
|
+
init Generate input.json template
|
|
538
|
+
analyze <input> Run security analysis on input JSON
|
|
539
|
+
server Start HTTP API server
|
|
540
|
+
|
|
541
|
+
Server options:
|
|
542
|
+
--host <host> Listen host (default: 127.0.0.1)
|
|
543
|
+
--port <port> Listen port (default: 9090)
|
|
544
|
+
`);
|
|
545
|
+
}
|
|
546
|
+
async function main() {
|
|
547
|
+
const args = process.argv.slice(2);
|
|
548
|
+
const command = args[0];
|
|
549
|
+
if (!command || command === "--help" || command === "-h") {
|
|
550
|
+
printHelp();
|
|
551
|
+
process.exit(command ? 0 : 1);
|
|
552
|
+
}
|
|
553
|
+
switch (command) {
|
|
554
|
+
case "init": {
|
|
555
|
+
const output = args[2] || "input.json";
|
|
556
|
+
const fs = await import("fs");
|
|
557
|
+
const template = {
|
|
558
|
+
session_id: "my-session-001",
|
|
559
|
+
prompt_session: "Read /var/log/app.log and analyze errors",
|
|
560
|
+
action_history: [],
|
|
561
|
+
a_next: { action_type: "bash", action_detail: "cat /var/log/app.log" },
|
|
562
|
+
reason: "Need to read log file for error analysis",
|
|
563
|
+
os_type: "",
|
|
564
|
+
cwd: "/home/user/project"
|
|
565
|
+
};
|
|
566
|
+
fs.writeFileSync(output, JSON.stringify(template, null, 2), "utf-8");
|
|
567
|
+
console.log(`Template written to ${output}`);
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
case "analyze": {
|
|
571
|
+
if (!args[1]) {
|
|
572
|
+
console.error("Usage: agent-moss analyze <input.json>");
|
|
573
|
+
process.exit(1);
|
|
574
|
+
}
|
|
575
|
+
const fs = await import("fs");
|
|
576
|
+
const path2 = await import("path");
|
|
577
|
+
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_coordinator(), coordinator_exports));
|
|
578
|
+
const filePath = path2.resolve(args[1]);
|
|
579
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
580
|
+
const result = await runAnalysis2({
|
|
581
|
+
sessionId: data.session_id || "unknown",
|
|
582
|
+
promptSession: data.prompt_session || "",
|
|
583
|
+
actionHistory: (data.action_history || []).map((h) => ({
|
|
584
|
+
actionType: h.action_type || h.name || "",
|
|
585
|
+
actionDetail: h.action_detail || ""
|
|
586
|
+
})),
|
|
587
|
+
aNext: {
|
|
588
|
+
actionType: data.a_next?.action_type || "",
|
|
589
|
+
actionDetail: data.a_next?.action_detail || ""
|
|
590
|
+
},
|
|
591
|
+
reason: data.reason || "",
|
|
592
|
+
osType: data.os_type || (process.platform === "win32" ? "windows" : "linux"),
|
|
593
|
+
cwd: data.cwd || process.cwd()
|
|
594
|
+
});
|
|
595
|
+
console.log(JSON.stringify(result, null, 2));
|
|
596
|
+
process.exit(result.allowed ? 0 : 1);
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
case "server": {
|
|
600
|
+
let host = "127.0.0.1";
|
|
601
|
+
let port = 9090;
|
|
602
|
+
for (let i = 1; i < args.length; i++) {
|
|
603
|
+
if (args[i] === "--host" && args[i + 1]) host = args[++i];
|
|
604
|
+
else if (args[i] === "--port" && args[i + 1]) port = parseInt(args[++i], 10);
|
|
605
|
+
}
|
|
606
|
+
const { serve } = await import("@hono/node-server");
|
|
607
|
+
const app = createApp();
|
|
608
|
+
console.log(`AgentMoss HTTP server on ${host}:${port}`);
|
|
609
|
+
serve({ fetch: app.fetch, hostname: host, port }, (info) => {
|
|
610
|
+
console.log(`Listening on http://${host}:${port}`);
|
|
611
|
+
});
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
default:
|
|
615
|
+
console.error(`Unknown command: ${command}`);
|
|
616
|
+
printHelp();
|
|
617
|
+
process.exit(1);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
main().catch((err) => {
|
|
621
|
+
console.error("Fatal error:", err);
|
|
622
|
+
process.exit(1);
|
|
623
|
+
});
|
|
624
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/engine/heuristic.ts","../src/engine/logic-rules.ts","../src/config.ts","../src/engine/skill-loader.ts","../src/engine/template-loader.ts","../src/engine/llm-analyzer.ts","../src/engine/coordinator.ts","../src/cli.ts","../src/server.ts","../src/routes.ts","../src/models.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { SecurityJudgment, HeuristicResult } from './types';\nimport type { AnalysisInput } from './coordinator';\n\n/**\n * Layer 1: Heuristic static detection.\n * Uses regex patterns to detect dangerous commands and user-defined rules.\n * Runs in < 1ms, no LLM cost.\n */\n\n// High-risk command patterns (synced with Python version)\nconst DANGEROUS_PATTERNS: { pattern: RegExp; severity: string; description: string }[] = [\n { pattern: /rm\\s+-rf\\s+\\/\\s*$|rm\\s+-rf\\s+\\/\\*/, severity: 'critical', description: '递归强制删除根目录' },\n { pattern: /rm\\s+-rf\\s+\\/home\\/\\*|rm\\s+-rf\\s+\\/root/, severity: 'critical', description: '删除用户主目录' },\n { pattern: /rm\\s+-rf\\s+\\/etc|rm\\s+-rf\\s+\\/var/, severity: 'critical', description: '删除系统目录' },\n { pattern: /curl\\s+.*\\|\\s*(bash|sh|zsh)/, severity: 'critical', description: 'curl pipe shell 执行' },\n { pattern: /wget\\s+.*\\|\\s*(bash|sh)/, severity: 'critical', description: 'wget pipe shell 执行' },\n { pattern: />\\s*\\/dev\\/sda|dd\\s+if=.*of=\\/dev\\//, severity: 'critical', description: '磁盘直接写入' },\n { pattern: /mkfs\\./, severity: 'critical', description: '格式化文件系统' },\n { pattern: /chmod\\s+777\\s+\\//, severity: 'high', description: '修改根目录权限为777' },\n { pattern: /chown\\s+-R\\s+\\w+:\\w+\\s+\\//, severity: 'high', description: '递归修改根目录所有者' },\n { pattern: /eval\\s+\\$\\(curl|eval\\s+\\$\\(wget/, severity: 'critical', description: 'eval 远程代码执行' },\n { pattern: /\\/dev\\/tcp\\/|bash\\s+-i\\s+>&/, severity: 'critical', description: '反弹 Shell' },\n { pattern: /nc\\s+-[el]\\s+.*\\d{1,5}/, severity: 'high', description: 'Netcat 反弹连接' },\n { pattern: /:\\(\\)\\s*\\{.*:\\|:&.*\\};:/, severity: 'critical', description: 'Fork Bomb' },\n { pattern: /sudo\\s+rm\\s+-rf/, severity: 'high', description: 'sudo 强制删除' },\n { pattern: /git\\s+clone\\s+.*\\|.*bash/, severity: 'high', description: 'git clone pipe shell' },\n { pattern: /pip\\s+install\\s+.*\\|\\s*bash/, severity: 'high', description: 'pip install pipe shell' },\n { pattern: /npm\\s+install\\s+-g\\s+.*\\|\\s*bash/, severity: 'high', description: 'npm install pipe shell' },\n { pattern: /export\\s+.*(?:TOKEN|KEY|SECRET|PASSWORD)/i, severity: 'medium', description: '导出敏感凭证' },\n { pattern: /base64\\s+-d\\s+.*\\|\\s*bash/, severity: 'critical', description: 'base64 解码执行' },\n];\n\nexport function runHeuristicCheck(input: AnalysisInput): SecurityJudgment | null {\n const command = `${input.aNext.actionType}: ${input.aNext.actionDetail}`;\n const matched: string[] = [];\n let highestSeverity = 'low';\n\n // Check dangerous patterns\n for (const rule of DANGEROUS_PATTERNS) {\n if (rule.pattern.test(command)) {\n matched.push(rule.description);\n if (severityRank(rule.severity) > severityRank(highestSeverity)) {\n highestSeverity = rule.severity;\n }\n }\n }\n\n if (matched.length > 0) {\n return {\n allowed: false,\n reason: `检测到高危操作: ${matched.join(', ')}`,\n riskLevel: highestSeverity as SecurityJudgment['riskLevel'],\n riskType: 'dangerous_command',\n confidence: 95,\n source: 'heuristic',\n violatedLayers: ['1'],\n };\n }\n\n return null; // No match, pass to next layer\n}\n\nfunction severityRank(s: string): number {\n const ranks: Record<string, number> = { low: 1, medium: 2, high: 3, critical: 4 };\n return ranks[s] || 0;\n}\n","import { SecurityJudgment } from './types';\nimport type { AnalysisInput } from './coordinator';\n\n/**\n * Layer 2: Logic rule detection.\n * Checks behavioral patterns: read-before-write, intent consistency,\n * sensitive path access, privilege escalation, and lateral movement.\n * Runs in < 1ms, no LLM cost.\n */\n\nconst ROOT_SENSITIVE_PATHS = [\n '/etc/shadow',\n '/etc/passwd',\n '/etc/sudoers',\n '/root/.ssh',\n '/root/.bashrc',\n '/boot',\n '/sys',\n '/proc',\n];\n\nconst HOME_SENSITIVE_PATHS = [\n '.ssh/id_rsa',\n '.ssh/authorized_keys',\n '.aws/credentials',\n '.gitconfig',\n '.gnupg',\n];\n\nexport function runLogicCheck(input: AnalysisInput): SecurityJudgment | null {\n const { actionHistory, aNext, cwd } = input;\n const command = aNext.actionDetail;\n const resolvedCwd = cwd || '/';\n\n // Rule 1: Read-before-write principle\n if (aNext.actionType === 'write' || aNext.actionType === 'file_write' || aNext.actionType === 'write_to_file') {\n const hadRead = actionHistory.some(\n h => (h.actionType === 'read' || h.actionType === 'file_read' || h.actionType === 'read_file') &&\n h.actionDetail.includes(cwd)\n );\n if (!hadRead && actionHistory.length === 0) {\n // Only flag if there's a history (skip first action)\n }\n }\n\n // Rule 2: Sensitive path access\n if (containsSensitivePath(command, resolvedCwd)) {\n return {\n allowed: false,\n reason: '尝试访问系统敏感路径',\n riskLevel: 'high',\n riskType: 'sensitive_path_access',\n confidence: 90,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n\n // Rule 3: Privilege escalation detection\n if (command.includes('sudo') || command.includes('su -') || command.includes('chmod u+s') || command.includes('setuid')) {\n // Check if previous actions suggest legitimate admin work\n const adminContext = actionHistory.some(h =>\n h.actionDetail.includes('sudo') || h.actionDetail.includes('apt') || h.actionDetail.includes('systemctl')\n );\n if (!adminContext && actionHistory.length === 0) {\n return {\n allowed: false,\n reason: '检测到提权操作,未发现合法管理上下文',\n riskLevel: 'high',\n riskType: 'privilege_escalation',\n confidence: 85,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n\n // Rule 4: Lateral movement detection\n if (command.includes('ssh') || command.includes('scp') || command.includes('rsync')) {\n const targetHost = extractRemoteHost(command);\n if (targetHost && !isLocalHost(targetHost)) {\n return {\n allowed: false,\n reason: `尝试横向移动到远程主机: ${targetHost}`,\n riskLevel: 'medium',\n riskType: 'lateral_movement',\n confidence: 80,\n source: 'logic_rule',\n violatedLayers: ['2'],\n };\n }\n }\n\n return null; // Pass to next layer\n}\n\nfunction containsSensitivePath(command: string, cwd: string): boolean {\n const expandedCwd = cwd.replace(/^~/, process.env.HOME || '/home/user');\n for (const p of ROOT_SENSITIVE_PATHS) {\n if (command.includes(p)) return true;\n }\n for (const p of HOME_SENSITIVE_PATHS) {\n if (command.includes(p) || command.includes(`${expandedCwd}/${p}`)) return true;\n }\n // Check file deletion of sensitive paths\n if ((command.includes('rm ') || command.includes('unlink')) &&\n (command.includes('/etc/') || command.includes('/root/') || command.includes('/var/log/'))) {\n return true;\n }\n return false;\n}\n\nfunction extractRemoteHost(command: string): string | null {\n // Match ssh/scp/rsync host pattern: user@host or hostname\n const m = command.match(/(?:ssh|scp|rsync)\\s+(?:-[\\w]+\\s+)*(\\S+@\\S+|\\b(?!-)[\\w.-]+\\b)/);\n return m ? m[1] : null;\n}\n\nfunction isLocalHost(host: string): boolean {\n const localNames = ['localhost', '127.0.0.1', '::1', process.env.HOSTNAME || '', '0.0.0.0'];\n return localNames.includes(host.replace(/.*@/, ''));\n}\n","import type { LLMConfig } from './engine/types';\n\n/** Global LLM configuration, initialized from env vars or defaults */\nlet llmConfig: LLMConfig = {\n provider: 'openai',\n baseUrl: process.env.AGENT_MOSS_LLM_BASE_URL || 'https://api.openai.com/v1',\n apiKey: process.env.AGENT_MOSS_LLM_API_KEY || '',\n model: process.env.AGENT_MOSS_LLM_MODEL || 'gpt-4o',\n temperature: parseFloat(process.env.AGENT_MOSS_LLM_TEMPERATURE || '0.1'),\n maxTokens: parseInt(process.env.AGENT_MOSS_LLM_MAX_TOKENS || '4096', 10),\n};\n\nexport function getLLMConfig(): Readonly<LLMConfig> {\n return llmConfig;\n}\n\nexport function updateLLMConfig(partial: Partial<LLMConfig>): void {\n llmConfig = { ...llmConfig, ...partial };\n}\n\n/** Check if LLM analysis is available (API key configured) */\nexport function isLLMAvailable(): boolean {\n return llmConfig.apiKey.length > 0;\n}\n","import { readFileSync, readdirSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Skill files are in ../../agent_moss/skills/ (shared with Python version)\nconst SKILLS_DIR = resolve(__dirname, '../../agent_moss/skills');\n\nlet cachedSkills: string[] | null = null;\n\nexport function loadSkills(): string[] {\n if (cachedSkills) return cachedSkills;\n\n if (!existsSync(SKILLS_DIR)) {\n console.warn('[AgentMoss] Skills directory not found:', SKILLS_DIR);\n cachedSkills = [];\n return cachedSkills;\n }\n\n const files = readdirSync(SKILLS_DIR).filter(f => f.endsWith('.md'));\n cachedSkills = files.map(f => {\n const content = readFileSync(resolve(SKILLS_DIR, f), 'utf-8');\n return `### ${f.replace('.md', '')}\\n${content}`;\n });\n\n console.log(`[AgentMoss] Loaded ${cachedSkills.length} skills`);\n return cachedSkills;\n}\n\n/** Reload skills (for hot-reload) */\nexport function reloadSkills(): void {\n cachedSkills = null;\n loadSkills();\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst TEMPLATES_DIR = resolve(__dirname, '../../agent_moss/templates');\n\nconst TEMPLATE_FILES = ['prompt1_template.txt', 'prompt2_template.txt', 'security_judge_template.txt'];\n\nlet cachedTemplates: Record<string, string> | null = null;\n\nexport function loadTemplates(): Record<string, string> {\n if (cachedTemplates) return cachedTemplates;\n\n cachedTemplates = {};\n\n if (!existsSync(TEMPLATES_DIR)) {\n console.warn('[AgentMoss] Templates directory not found:', TEMPLATES_DIR);\n return cachedTemplates;\n }\n\n for (const file of TEMPLATE_FILES) {\n const filePath = resolve(TEMPLATES_DIR, file);\n if (existsSync(filePath)) {\n const key = file.replace('.txt', '').replace('_template', '');\n cachedTemplates[key] = readFileSync(filePath, 'utf-8');\n }\n }\n\n console.log(`[AgentMoss] Loaded ${Object.keys(cachedTemplates).length} templates`);\n return cachedTemplates;\n}\n\nexport function reloadTemplates(): void {\n cachedTemplates = null;\n loadTemplates();\n}\n","import { SecurityJudgment } from './types';\nimport type { AnalysisInput } from './coordinator';\nimport { getLLMConfig, isLLMAvailable } from '../config';\nimport { loadSkills } from './skill-loader';\nimport { loadTemplates } from './template-loader';\nimport OpenAI from 'openai';\n\n// LRU cache to avoid duplicate LLM calls for identical commands\nconst llmCache = new Map<string, SecurityJudgment>();\nconst LLM_CACHE_MAX = 200;\n\ninterface PreviousResults {\n heuristic: SecurityJudgment | null;\n logic: SecurityJudgment | null;\n}\n\n/**\n * Layer 3: LLM + Skill semantic analysis.\n * Only called when layers 1 and 2 both pass.\n * Loads skills from the shared skills directory and uses LLM for deep analysis.\n */\nexport async function runLLMAnalysis(\n input: AnalysisInput,\n previous: PreviousResults\n): Promise<SecurityJudgment> {\n if (!isLLMAvailable()) {\n console.log('[AgentMoss] LLM not configured, skipping deep analysis');\n return {\n allowed: true,\n reason: 'LLM 未配置,跳过深层分析',\n riskLevel: 'low',\n riskType: '',\n confidence: 50,\n source: 'llm',\n violatedLayers: [],\n };\n }\n\n const config = getLLMConfig();\n\n // Check LRU cache\n const cacheKey = `${input.aNext.actionType}:${input.aNext.actionDetail}`;\n const cached = llmCache.get(cacheKey);\n if (cached) {\n console.log('[AgentMoss] LLM cache hit');\n return cached;\n }\n\n // Load skills and templates (cached)\n const skills = loadSkills();\n const templates = loadTemplates();\n\n // Build the analysis prompt\n const prompt = buildPrompt(input, previous, skills, templates);\n\n // Call LLM\n const result = await analyzeWithLLM(prompt, config);\n\n // Cache result\n if (llmCache.size >= LLM_CACHE_MAX) {\n const firstKey = llmCache.keys().next().value;\n if (firstKey) llmCache.delete(firstKey);\n }\n llmCache.set(cacheKey, result);\n\n return result;\n}\n\nfunction buildPrompt(\n input: AnalysisInput,\n previous: PreviousResults,\n skills: string[],\n templates: Record<string, string>\n): string {\n const skillContext = skills.length > 0 ? skills.join('\\n---\\n') : '(无可用 Skill)';\n const historyStr = input.actionHistory\n .map((h, i) => `${i + 1}. [${h.actionType}] ${h.actionDetail}`)\n .join('\\n') || '(无历史操作)';\n\n const templateName = previous.heuristic || previous.logic ? 'prompt2' : 'prompt1';\n const baseTemplate = templates[templateName] || templates['prompt1'] || '';\n\n return `${baseTemplate}\n\n## 当前操作上下文\n- 会话 ID: ${input.sessionId}\n- 用户任务: ${input.promptSession || '未指定'}\n- 操作系统: ${input.osType}\n- 工作目录: ${input.cwd || '/'}\n- 操作原因: ${input.reason || '未说明'}\n- 历史操作序列:\n${historyStr}\n\n- 即将执行的操作:\n 类型: ${input.aNext.actionType}\n 详情: ${input.aNext.actionDetail}\n\n## 可用安全 Skill\n${skillContext}\n\n请根据以上信息,对即将执行的操作进行安全判断。你必须输出严格的 JSON 格式,\n不要包含任何其他文字、注释或 markdown 标记。\n\n输出格式:\n{\"allowed\": true/false, \"reason\": \"判断理由\", \"riskLevel\": \"low|medium|high|critical\", \"riskType\": \"风险类型\", \"confidence\": 0-100}`;\n}\n\nasync function analyzeWithLLM(prompt: string, config: ReturnType<typeof getLLMConfig>): Promise<SecurityJudgment> {\n console.log(`[AgentMoss] LLM analyzing with model: ${config.model}, url: ${config.baseUrl}`);\n\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n timeout: 30000,\n });\n\n try {\n const response = await client.chat.completions.create({\n model: config.model,\n temperature: config.temperature || 0.1,\n max_tokens: config.maxTokens || 1024,\n messages: [\n { role: 'system', content: '你是一个 AI Agent 安全审计专家。你的任务是分析即将执行的命令是否安全。你必须只输出纯 JSON,不要包含任何 markdown 标记、代码块或其他文字。' },\n { role: 'user', content: prompt },\n ],\n });\n\n const content = response.choices[0]?.message?.content || '{}';\n console.log(`[AgentMoss] LLM raw response: ${content.substring(0, 300)}`);\n\n // Parse JSON — strip markdown code fences if present\n let jsonStr = content.trim();\n if (jsonStr.startsWith('```')) {\n jsonStr = jsonStr.replace(/^```[\\w]*\\n?/, '').replace(/\\n?```$/, '');\n }\n const parsed = JSON.parse(jsonStr);\n\n return {\n allowed: parsed.allowed !== false, // default to Allow if missing\n reason: parsed.reason || 'LLM 分析完成',\n riskLevel: ['low', 'medium', 'high', 'critical'].includes(parsed.riskLevel) ? parsed.riskLevel : 'low',\n riskType: parsed.riskType || '',\n confidence: typeof parsed.confidence === 'number' ? Math.min(100, Math.max(0, parsed.confidence)) : 70,\n source: 'llm',\n violatedLayers: ['3'],\n };\n } catch (err) {\n console.error('[AgentMoss] LLM call failed:', (err as Error).message);\n return {\n allowed: true,\n reason: `LLM 调用失败: ${(err as Error).message}`,\n riskLevel: 'low',\n riskType: '',\n confidence: 30,\n source: 'llm',\n violatedLayers: [],\n };\n }\n}\n","import { SecurityJudgment } from './types';\nimport { runHeuristicCheck } from './heuristic';\nimport { runLogicCheck } from './logic-rules';\nimport { runLLMAnalysis } from './llm-analyzer';\n\nexport interface AnalysisInput {\n sessionId: string;\n promptSession: string;\n actionHistory: { actionType: string; actionDetail: string }[];\n aNext: { actionType: string; actionDetail: string };\n reason: string;\n osType: string;\n cwd: string;\n}\n\n/**\n * Three-layer defense coordinator.\n * Runs layers sequentially: heuristic → logic → LLM.\n * If layer 1 or 2 returns Deny, skip subsequent layers.\n */\nexport async function runAnalysis(input: AnalysisInput): Promise<SecurityJudgment> {\n // Layer 1: Heuristic static detection (fast)\n const heuristicResult = runHeuristicCheck(input);\n if (heuristicResult && !heuristicResult.allowed) {\n return heuristicResult;\n }\n\n // Layer 2: Logic rule detection (fast)\n const logicResult = runLogicCheck(input);\n if (logicResult && !logicResult.allowed) {\n return logicResult;\n }\n\n // Layer 3: LLM + Skill semantic analysis (slow, only if both above passed)\n const llmResult = await runLLMAnalysis(input, {\n heuristic: heuristicResult,\n logic: logicResult,\n });\n\n return llmResult;\n}\n","#!/usr/bin/env node\n/**\n * AgentMoss CLI — TypeScript version.\n * Supports: init | analyze | server\n */\n\nimport { parseArgs } from 'util';\nimport { createApp } from './server';\n\nfunction printHelp(): void {\n console.log(`AgentMoss security analysis engine (TypeScript v0.2.0)\n\nCommands:\n init Generate input.json template\n analyze <input> Run security analysis on input JSON\n server Start HTTP API server\n\nServer options:\n --host <host> Listen host (default: 127.0.0.1)\n --port <port> Listen port (default: 9090)\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (!command || command === '--help' || command === '-h') {\n printHelp();\n process.exit(command ? 0 : 1);\n }\n\n switch (command) {\n case 'init': {\n const output = args[2] || 'input.json';\n const fs = await import('fs');\n const template = {\n session_id: 'my-session-001',\n prompt_session: 'Read /var/log/app.log and analyze errors',\n action_history: [],\n a_next: { action_type: 'bash', action_detail: 'cat /var/log/app.log' },\n reason: 'Need to read log file for error analysis',\n os_type: '',\n cwd: '/home/user/project',\n };\n fs.writeFileSync(output, JSON.stringify(template, null, 2), 'utf-8');\n console.log(`Template written to ${output}`);\n break;\n }\n\n case 'analyze': {\n if (!args[1]) {\n console.error('Usage: agent-moss analyze <input.json>');\n process.exit(1);\n }\n const fs = await import('fs');\n const path = await import('path');\n const { runAnalysis } = await import('./engine/coordinator');\n const filePath = path.resolve(args[1]);\n const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n const result = await runAnalysis({\n sessionId: data.session_id || 'unknown',\n promptSession: data.prompt_session || '',\n actionHistory: (data.action_history || []).map((h: any) => ({\n actionType: h.action_type || h.name || '',\n actionDetail: h.action_detail || '',\n })),\n aNext: {\n actionType: data.a_next?.action_type || '',\n actionDetail: data.a_next?.action_detail || '',\n },\n reason: data.reason || '',\n osType: data.os_type || (process.platform === 'win32' ? 'windows' : 'linux'),\n cwd: data.cwd || process.cwd(),\n });\n console.log(JSON.stringify(result, null, 2));\n process.exit(result.allowed ? 0 : 1);\n break;\n }\n\n case 'server': {\n let host = '127.0.0.1';\n let port = 9090;\n\n for (let i = 1; i < args.length; i++) {\n if (args[i] === '--host' && args[i + 1]) host = args[++i];\n else if (args[i] === '--port' && args[i + 1]) port = parseInt(args[++i], 10);\n }\n\n // Import @hono/node-server dynamically\n const { serve } = await import('@hono/node-server');\n const app = createApp();\n console.log(`AgentMoss HTTP server on ${host}:${port}`);\n serve({ fetch: app.fetch, hostname: host, port }, (info) => {\n console.log(`Listening on http://${host}:${port}`);\n });\n break;\n }\n\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n","import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { logger } from 'hono/logger';\nimport { analyzeRoute, healthRoute } from './routes';\n\nexport function createApp(): Hono {\n const app = new Hono();\n\n // Middleware\n app.use('*', cors({ origin: '*', allowMethods: ['GET', 'POST', 'OPTIONS'], allowHeaders: ['*'] }));\n app.use('*', logger());\n\n // Routes\n app.get('/api/v1/health', healthRoute);\n app.post('/api/v1/analyze', analyzeRoute);\n\n return app;\n}\n\nexport function startServer(host = '127.0.0.1', port = 9090): { serve: () => void } {\n const app = createApp();\n return {\n serve: () => {\n console.log(`AgentMoss HTTP server on ${host}:${port}`);\n // In utilityProcess mode, use Bun.serve or Node adapter\n // Use @hono/node-server for Node.js environments\n const { serve: honoServe } = require('@hono/node-server');\n honoServe({ fetch: app.fetch, hostname: host, port });\n },\n };\n}\n","import type { Context } from 'hono';\nimport { AnalyzeRequestSchema, AnalyzeResponseSchema, HealthResponseSchema } from './models';\nimport { runAnalysis } from './engine/coordinator';\n\nexport async function healthRoute(c: Context) {\n return c.json(HealthResponseSchema.parse({}));\n}\n\nexport async function analyzeRoute(c: Context) {\n const t0 = performance.now();\n\n try {\n const body = await c.req.json();\n const req = AnalyzeRequestSchema.parse(body);\n\n // OS auto-detect\n let osType = req.os_type;\n if (!osType) {\n osType = process.platform === 'win32' ? 'windows' : 'linux';\n }\n\n const result = await runAnalysis({\n sessionId: req.session_id,\n promptSession: req.prompt_session,\n actionHistory: req.action_history.map(h => ({\n actionType: h.action_type,\n actionDetail: h.action_detail,\n })),\n aNext: {\n actionType: req.a_next.action_type,\n actionDetail: req.a_next.action_detail,\n },\n reason: req.reason,\n osType,\n cwd: req.cwd,\n });\n\n const durationMs = performance.now() - t0;\n\n return c.json(\n AnalyzeResponseSchema.parse({\n decision: result.allowed ? 'Allow' : 'Deny',\n reason: result.reason,\n risk_level: result.riskLevel,\n risk_type: result.riskType,\n violated_layers: result.violatedLayers,\n policy: '',\n violated_policy: '',\n confidence: result.confidence,\n analysis_duration_ms: Math.round(durationMs * 10) / 10,\n })\n );\n } catch (err) {\n console.error('[AgentMoss] Analysis error:', err);\n if (err instanceof SyntaxError) {\n return c.json({ error: 'Invalid JSON', detail: err.message }, 400);\n }\n if ((err as any)?.issues) {\n return c.json({ error: 'Validation error', detail: (err as any).issues }, 400);\n }\n return c.json({ error: 'Internal error', detail: String(err) }, 500);\n }\n}\n","import { z } from 'zod';\n\n/** Single action in history or next action */\nexport const ActionItemSchema = z.object({\n action_type: z.string().describe('Action type, e.g. bash, file_read, file_write'),\n action_detail: z.string().describe('Action detail / command content'),\n});\n\nexport const AnalyzeRequestSchema = z.object({\n session_id: z.string().describe('Session / agent unique identifier'),\n prompt_session: z.string().default('').describe('User original prompt'),\n action_history: z.array(ActionItemSchema).default([]).describe('Historical action sequence'),\n a_next: ActionItemSchema.describe('Next action to be executed'),\n reason: z.string().default('').describe('Reason for executing this action'),\n os_type: z.string().default('').describe(\"OS type: 'linux', 'windows', or empty for auto-detect\"),\n cwd: z.string().default('').describe('Current working directory'),\n metadata: z.record(z.unknown()).optional().describe('Extended metadata'),\n});\n\nexport const AnalyzeResponseSchema = z.object({\n decision: z.enum(['Allow', 'Deny']).describe('Allow or Deny'),\n reason: z.string().describe('Decision reason'),\n risk_level: z.enum(['low', 'medium', 'high', 'critical']).default('low'),\n risk_type: z.string().default(''),\n violated_layers: z.array(z.string()).default([]),\n policy: z.string().default(''),\n violated_policy: z.string().default(''),\n confidence: z.number().int().min(0).max(100).default(100),\n analysis_duration_ms: z.number().default(0),\n});\n\nexport const HealthResponseSchema = z.object({\n status: z.string().default('healthy'),\n version: z.string().default('0.2.0'),\n});\n\nexport type ActionItem = z.infer<typeof ActionItemSchema>;\nexport type AnalyzeRequest = z.infer<typeof AnalyzeRequestSchema>;\nexport type AnalyzeResponse = z.infer<typeof AnalyzeResponseSchema>;\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>;\n"],"mappings":"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","names":["fileURLToPath","__filename","__dirname","readFileSync","existsSync","resolve","dirname","fileURLToPath","__filename","__dirname","path","runAnalysis"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kenhkl/agent-moss",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Multi-layer security analysis engine for AI agents (TypeScript)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/cli.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"agent-moss": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup",
|
|
15
|
+
"dev": "tsx src/cli.ts server --port 9090",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@hono/node-server": "^1.13.0",
|
|
20
|
+
"hono": "^4.6.0",
|
|
21
|
+
"openai": "^4.104.0",
|
|
22
|
+
"pino": "^9.5.0",
|
|
23
|
+
"pino-pretty": "^11.3.0",
|
|
24
|
+
"yaml": "^2.6.0",
|
|
25
|
+
"zod": "^3.23.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.17.0",
|
|
29
|
+
"tsup": "^8.3.0",
|
|
30
|
+
"tsx": "^4.19.0",
|
|
31
|
+
"typescript": "^5.6.0"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT"
|
|
34
|
+
}
|