@panguard-ai/panguard-guard 0.1.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/agent/analyze-agent.d.ts +62 -0
- package/dist/agent/analyze-agent.d.ts.map +1 -0
- package/dist/agent/analyze-agent.js +327 -0
- package/dist/agent/analyze-agent.js.map +1 -0
- package/dist/agent/detect-agent.d.ts +59 -0
- package/dist/agent/detect-agent.d.ts.map +1 -0
- package/dist/agent/detect-agent.js +214 -0
- package/dist/agent/detect-agent.js.map +1 -0
- package/dist/agent/index.d.ts +15 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +14 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/report-agent.d.ts +122 -0
- package/dist/agent/report-agent.d.ts.map +1 -0
- package/dist/agent/report-agent.js +468 -0
- package/dist/agent/report-agent.js.map +1 -0
- package/dist/agent/respond-agent.d.ts +113 -0
- package/dist/agent/respond-agent.d.ts.map +1 -0
- package/dist/agent/respond-agent.js +749 -0
- package/dist/agent/respond-agent.js.map +1 -0
- package/dist/agent-client/index.d.ts +81 -0
- package/dist/agent-client/index.d.ts.map +1 -0
- package/dist/agent-client/index.js +170 -0
- package/dist/agent-client/index.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +295 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +108 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon/index.d.ts +66 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +284 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/dashboard/index.d.ts +78 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +455 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/guard-engine.d.ts +108 -0
- package/dist/guard-engine.d.ts.map +1 -0
- package/dist/guard-engine.js +740 -0
- package/dist/guard-engine.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/install/index.d.ts +23 -0
- package/dist/install/index.d.ts.map +1 -0
- package/dist/install/index.js +216 -0
- package/dist/install/index.js.map +1 -0
- package/dist/investigation/index.d.ts +80 -0
- package/dist/investigation/index.d.ts.map +1 -0
- package/dist/investigation/index.js +570 -0
- package/dist/investigation/index.js.map +1 -0
- package/dist/license/index.d.ts +46 -0
- package/dist/license/index.d.ts.map +1 -0
- package/dist/license/index.js +145 -0
- package/dist/license/index.js.map +1 -0
- package/dist/memory/baseline.d.ts +34 -0
- package/dist/memory/baseline.d.ts.map +1 -0
- package/dist/memory/baseline.js +224 -0
- package/dist/memory/baseline.js.map +1 -0
- package/dist/memory/index.d.ts +32 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +58 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/learning.d.ts +35 -0
- package/dist/memory/learning.d.ts.map +1 -0
- package/dist/memory/learning.js +60 -0
- package/dist/memory/learning.js.map +1 -0
- package/dist/monitors/falco-monitor.d.ts +62 -0
- package/dist/monitors/falco-monitor.d.ts.map +1 -0
- package/dist/monitors/falco-monitor.js +226 -0
- package/dist/monitors/falco-monitor.js.map +1 -0
- package/dist/monitors/suricata-monitor.d.ts +80 -0
- package/dist/monitors/suricata-monitor.d.ts.map +1 -0
- package/dist/monitors/suricata-monitor.js +227 -0
- package/dist/monitors/suricata-monitor.js.map +1 -0
- package/dist/notify/email.d.ts +23 -0
- package/dist/notify/email.d.ts.map +1 -0
- package/dist/notify/email.js +124 -0
- package/dist/notify/email.js.map +1 -0
- package/dist/notify/index.d.ts +31 -0
- package/dist/notify/index.d.ts.map +1 -0
- package/dist/notify/index.js +70 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/line-notify.d.ts.map +1 -0
- package/dist/notify/slack.d.ts +21 -0
- package/dist/notify/slack.d.ts.map +1 -0
- package/dist/notify/slack.js +92 -0
- package/dist/notify/slack.js.map +1 -0
- package/dist/notify/telegram.d.ts +21 -0
- package/dist/notify/telegram.d.ts.map +1 -0
- package/dist/notify/telegram.js +89 -0
- package/dist/notify/telegram.js.map +1 -0
- package/dist/response/file-quarantine.d.ts +63 -0
- package/dist/response/file-quarantine.d.ts.map +1 -0
- package/dist/response/file-quarantine.js +137 -0
- package/dist/response/file-quarantine.js.map +1 -0
- package/dist/response/index.d.ts +4 -0
- package/dist/response/index.d.ts.map +1 -0
- package/dist/response/index.js +4 -0
- package/dist/response/index.js.map +1 -0
- package/dist/response/ip-blocker.d.ts +69 -0
- package/dist/response/ip-blocker.d.ts.map +1 -0
- package/dist/response/ip-blocker.js +191 -0
- package/dist/response/ip-blocker.js.map +1 -0
- package/dist/response/process-killer.d.ts +49 -0
- package/dist/response/process-killer.d.ts.map +1 -0
- package/dist/response/process-killer.js +230 -0
- package/dist/response/process-killer.js.map +1 -0
- package/dist/rules/builtin-rules.d.ts +12 -0
- package/dist/rules/builtin-rules.d.ts.map +1 -0
- package/dist/rules/builtin-rules.js +471 -0
- package/dist/rules/builtin-rules.js.map +1 -0
- package/dist/threat-cloud/client-id.d.ts +13 -0
- package/dist/threat-cloud/client-id.d.ts.map +1 -0
- package/dist/threat-cloud/client-id.js +38 -0
- package/dist/threat-cloud/client-id.js.map +1 -0
- package/dist/threat-cloud/index.d.ts +103 -0
- package/dist/threat-cloud/index.d.ts.map +1 -0
- package/dist/threat-cloud/index.js +386 -0
- package/dist/threat-cloud/index.js.map +1 -0
- package/dist/types.d.ts +336 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +42 -0
- package/dist/types.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Agent - Event logging with rotation, streaming reads, and retention policy
|
|
3
|
+
* 報告代理 - 事件記錄,支援 log rotation、串流讀取和資料保留策略
|
|
4
|
+
*
|
|
5
|
+
* Fourth stage of the multi-agent pipeline. Logs all events to JSONL with
|
|
6
|
+
* automatic rotation, updates the baseline during learning mode, and
|
|
7
|
+
* generates anonymized threat data for collective intelligence.
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/panguard-guard/agent/report-agent
|
|
10
|
+
*/
|
|
11
|
+
import { appendFileSync, mkdirSync, readFileSync, statSync, renameSync, readdirSync, unlinkSync, createReadStream, } from 'node:fs';
|
|
12
|
+
import { dirname, join, basename } from 'node:path';
|
|
13
|
+
import { createInterface } from 'node:readline';
|
|
14
|
+
import { createLogger } from '@panguard-ai/core';
|
|
15
|
+
import { updateBaseline } from '../memory/baseline.js';
|
|
16
|
+
const logger = createLogger('panguard-guard:report-agent');
|
|
17
|
+
const DEFAULT_ROTATION = {
|
|
18
|
+
maxFileSizeBytes: 50 * 1024 * 1024, // 50MB
|
|
19
|
+
maxRotatedFiles: 10,
|
|
20
|
+
retentionDays: 90,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Report Agent logs events with rotation, updates baselines, and generates anonymized data.
|
|
24
|
+
*/
|
|
25
|
+
export class ReportAgent {
|
|
26
|
+
logPath;
|
|
27
|
+
mode;
|
|
28
|
+
reportCount = 0;
|
|
29
|
+
rotation;
|
|
30
|
+
constructor(logPath, mode, rotation) {
|
|
31
|
+
this.logPath = logPath;
|
|
32
|
+
this.mode = mode;
|
|
33
|
+
this.rotation = { ...DEFAULT_ROTATION, ...rotation };
|
|
34
|
+
// Ensure log directory exists
|
|
35
|
+
try {
|
|
36
|
+
mkdirSync(dirname(logPath), { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Directory may already exist
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Update operating mode */
|
|
43
|
+
setMode(mode) {
|
|
44
|
+
this.mode = mode;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Process a complete pipeline result: log, update baseline, generate anonymized data.
|
|
48
|
+
* Automatically rotates log file when size limit is reached.
|
|
49
|
+
*/
|
|
50
|
+
report(event, verdict, response, baseline) {
|
|
51
|
+
this.reportCount++;
|
|
52
|
+
// Step 1: Check if rotation needed before writing
|
|
53
|
+
this.rotateIfNeeded();
|
|
54
|
+
// Step 2: Log to JSONL
|
|
55
|
+
const record = {
|
|
56
|
+
event,
|
|
57
|
+
verdict,
|
|
58
|
+
response,
|
|
59
|
+
timestamp: new Date().toISOString(),
|
|
60
|
+
};
|
|
61
|
+
this.appendLog(record);
|
|
62
|
+
// Step 3: Update baseline (learning mode adds normal patterns)
|
|
63
|
+
let updatedBaseline = baseline;
|
|
64
|
+
if (this.mode === 'learning') {
|
|
65
|
+
updatedBaseline = updateBaseline(baseline, event);
|
|
66
|
+
}
|
|
67
|
+
// Step 4: Generate anonymized data for malicious/suspicious verdicts
|
|
68
|
+
let anonymizedData;
|
|
69
|
+
if (verdict.conclusion !== 'benign') {
|
|
70
|
+
anonymizedData = this.generateAnonymizedData(event, verdict);
|
|
71
|
+
}
|
|
72
|
+
logger.info(`Report #${this.reportCount}: ${verdict.conclusion} ` +
|
|
73
|
+
`(action: ${response.action}, success: ${response.success})`);
|
|
74
|
+
return { updatedBaseline, anonymizedData };
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Log Rotation
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Rotate log file if it exceeds the size limit.
|
|
81
|
+
* Naming: events.jsonl -> events.jsonl.1 -> events.jsonl.2 -> ...
|
|
82
|
+
* Oldest files beyond maxRotatedFiles are deleted.
|
|
83
|
+
*/
|
|
84
|
+
rotateIfNeeded() {
|
|
85
|
+
try {
|
|
86
|
+
const stats = statSync(this.logPath);
|
|
87
|
+
if (stats.size < this.rotation.maxFileSizeBytes)
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return; // File doesn't exist yet, no rotation needed
|
|
92
|
+
}
|
|
93
|
+
logger.info(`Log rotation triggered (file exceeds ${this.rotation.maxFileSizeBytes} bytes)`);
|
|
94
|
+
const dir = dirname(this.logPath);
|
|
95
|
+
const base = basename(this.logPath);
|
|
96
|
+
// Shift existing rotated files: .9 -> .10, .8 -> .9, etc.
|
|
97
|
+
for (let i = this.rotation.maxRotatedFiles; i >= 1; i--) {
|
|
98
|
+
const from = join(dir, `${base}.${i}`);
|
|
99
|
+
const to = join(dir, `${base}.${i + 1}`);
|
|
100
|
+
try {
|
|
101
|
+
renameSync(from, to);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// File may not exist
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Rename current log to .1
|
|
108
|
+
try {
|
|
109
|
+
renameSync(this.logPath, join(dir, `${base}.1`));
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
113
|
+
logger.error(`Log rotation rename failed: ${msg}`);
|
|
114
|
+
}
|
|
115
|
+
// Delete files beyond retention limit
|
|
116
|
+
this.enforceRetention();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Delete rotated log files beyond maxRotatedFiles and older than retentionDays
|
|
120
|
+
*/
|
|
121
|
+
enforceRetention() {
|
|
122
|
+
const dir = dirname(this.logPath);
|
|
123
|
+
const base = basename(this.logPath);
|
|
124
|
+
const cutoff = Date.now() - this.rotation.retentionDays * 24 * 60 * 60 * 1000;
|
|
125
|
+
try {
|
|
126
|
+
const files = readdirSync(dir).filter((f) => f.startsWith(base + '.'));
|
|
127
|
+
// Delete files beyond max count
|
|
128
|
+
const numbered = files
|
|
129
|
+
.map((f) => {
|
|
130
|
+
const num = parseInt(f.slice(base.length + 1), 10);
|
|
131
|
+
return { file: f, num };
|
|
132
|
+
})
|
|
133
|
+
.filter((x) => !isNaN(x.num))
|
|
134
|
+
.sort((a, b) => a.num - b.num);
|
|
135
|
+
for (const entry of numbered) {
|
|
136
|
+
if (entry.num > this.rotation.maxRotatedFiles) {
|
|
137
|
+
try {
|
|
138
|
+
unlinkSync(join(dir, entry.file));
|
|
139
|
+
logger.info(`Retention: deleted ${entry.file} (exceeds max rotated files)`);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Non-critical
|
|
143
|
+
}
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Also delete if older than retention period
|
|
147
|
+
try {
|
|
148
|
+
const stat = statSync(join(dir, entry.file));
|
|
149
|
+
if (stat.mtimeMs < cutoff) {
|
|
150
|
+
unlinkSync(join(dir, entry.file));
|
|
151
|
+
logger.info(`Retention: deleted ${entry.file} (older than ${this.rotation.retentionDays} days)`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Non-critical
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Directory read failure is non-critical
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Log Writing
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
appendLog(record) {
|
|
167
|
+
try {
|
|
168
|
+
const line = JSON.stringify(record) + '\n';
|
|
169
|
+
appendFileSync(this.logPath, line, 'utf-8');
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
173
|
+
logger.error(`Failed to write log: ${msg}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// Streaming Log Reader (memory-efficient)
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
/**
|
|
180
|
+
* Read log records from JSONL using streaming (line-by-line).
|
|
181
|
+
* Only loads records after the cutoff date into memory.
|
|
182
|
+
* This replaces the previous readFileSync approach that loaded entire files.
|
|
183
|
+
*/
|
|
184
|
+
async readLogRecordsStreaming(after) {
|
|
185
|
+
const records = [];
|
|
186
|
+
const allFiles = this.getLogFiles();
|
|
187
|
+
for (const filePath of allFiles) {
|
|
188
|
+
try {
|
|
189
|
+
const fileRecords = await this.streamFile(filePath, after);
|
|
190
|
+
records.push(...fileRecords);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// File may not exist or be corrupted
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return records;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get all log files (current + rotated) sorted newest first
|
|
200
|
+
*/
|
|
201
|
+
getLogFiles() {
|
|
202
|
+
const files = [this.logPath];
|
|
203
|
+
const dir = dirname(this.logPath);
|
|
204
|
+
const base = basename(this.logPath);
|
|
205
|
+
try {
|
|
206
|
+
const rotated = readdirSync(dir)
|
|
207
|
+
.filter((f) => f.startsWith(base + '.'))
|
|
208
|
+
.map((f) => {
|
|
209
|
+
const num = parseInt(f.slice(base.length + 1), 10);
|
|
210
|
+
return { file: join(dir, f), num };
|
|
211
|
+
})
|
|
212
|
+
.filter((x) => !isNaN(x.num))
|
|
213
|
+
.sort((a, b) => a.num - b.num)
|
|
214
|
+
.map((x) => x.file);
|
|
215
|
+
files.push(...rotated);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// No rotated files
|
|
219
|
+
}
|
|
220
|
+
return files;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Stream a single JSONL file, returning records after the cutoff
|
|
224
|
+
*/
|
|
225
|
+
streamFile(filePath, after) {
|
|
226
|
+
return new Promise((resolve) => {
|
|
227
|
+
const records = [];
|
|
228
|
+
try {
|
|
229
|
+
const stream = createReadStream(filePath, { encoding: 'utf-8' });
|
|
230
|
+
const rl = createInterface({ input: stream, crlfDelay: Infinity });
|
|
231
|
+
rl.on('line', (line) => {
|
|
232
|
+
if (!line.trim())
|
|
233
|
+
return;
|
|
234
|
+
try {
|
|
235
|
+
const record = JSON.parse(line);
|
|
236
|
+
if (new Date(record.timestamp) >= after) {
|
|
237
|
+
records.push(record);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
// Skip malformed lines
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
rl.on('close', () => resolve(records));
|
|
245
|
+
rl.on('error', () => resolve(records));
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
resolve(records);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
// Summary Generation (now uses streaming)
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
/**
|
|
256
|
+
* Generate a summary for the given time period.
|
|
257
|
+
* Uses streaming reader for memory efficiency.
|
|
258
|
+
*/
|
|
259
|
+
async generateSummary(hoursBack) {
|
|
260
|
+
const now = new Date();
|
|
261
|
+
const cutoff = new Date(now.getTime() - hoursBack * 60 * 60 * 1000);
|
|
262
|
+
const records = await this.readLogRecordsStreaming(cutoff);
|
|
263
|
+
const ipCounts = new Map();
|
|
264
|
+
const actionCounts = new Map();
|
|
265
|
+
const verdictBreakdown = { benign: 0, suspicious: 0, malicious: 0 };
|
|
266
|
+
let threatsBlocked = 0;
|
|
267
|
+
for (const r of records) {
|
|
268
|
+
const conclusion = r.verdict.conclusion;
|
|
269
|
+
if (conclusion === 'benign' || conclusion === 'suspicious' || conclusion === 'malicious') {
|
|
270
|
+
verdictBreakdown[conclusion]++;
|
|
271
|
+
}
|
|
272
|
+
if (r.response.action !== 'log_only' &&
|
|
273
|
+
r.response.action !== 'notify' &&
|
|
274
|
+
r.response.success) {
|
|
275
|
+
threatsBlocked++;
|
|
276
|
+
}
|
|
277
|
+
const ip = r.event.metadata?.['sourceIP'] ??
|
|
278
|
+
r.event.metadata?.['remoteAddress'];
|
|
279
|
+
if (ip && conclusion !== 'benign') {
|
|
280
|
+
ipCounts.set(ip, (ipCounts.get(ip) ?? 0) + 1);
|
|
281
|
+
}
|
|
282
|
+
const act = r.response.action;
|
|
283
|
+
actionCounts.set(act, (actionCounts.get(act) ?? 0) + 1);
|
|
284
|
+
}
|
|
285
|
+
const topAttackSources = [...ipCounts.entries()]
|
|
286
|
+
.sort((a, b) => b[1] - a[1])
|
|
287
|
+
.slice(0, 10)
|
|
288
|
+
.map(([ip, count]) => ({ ip, count }));
|
|
289
|
+
const actionsTaken = [...actionCounts.entries()].map(([action, count]) => ({ action, count }));
|
|
290
|
+
return {
|
|
291
|
+
period: { start: cutoff.toISOString(), end: now.toISOString() },
|
|
292
|
+
totalEvents: records.length,
|
|
293
|
+
threatsBlocked,
|
|
294
|
+
suspiciousEvents: verdictBreakdown.suspicious,
|
|
295
|
+
benignEvents: verdictBreakdown.benign,
|
|
296
|
+
topAttackSources,
|
|
297
|
+
actionsTaken,
|
|
298
|
+
verdictBreakdown,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/** Generate daily summary (last 24 hours) */
|
|
302
|
+
async generateDailySummary() {
|
|
303
|
+
return this.generateSummary(24);
|
|
304
|
+
}
|
|
305
|
+
/** Generate weekly summary (last 7 days) */
|
|
306
|
+
async generateWeeklySummary() {
|
|
307
|
+
return this.generateSummary(7 * 24);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Synchronous summary for backwards compatibility (reads current file only).
|
|
311
|
+
* Prefer async generateSummary() for production use.
|
|
312
|
+
*/
|
|
313
|
+
generateSummarySync(hoursBack) {
|
|
314
|
+
const now = new Date();
|
|
315
|
+
const cutoff = new Date(now.getTime() - hoursBack * 60 * 60 * 1000);
|
|
316
|
+
const records = this.readLogRecordsSync(cutoff);
|
|
317
|
+
const ipCounts = new Map();
|
|
318
|
+
const actionCounts = new Map();
|
|
319
|
+
const verdictBreakdown = { benign: 0, suspicious: 0, malicious: 0 };
|
|
320
|
+
let threatsBlocked = 0;
|
|
321
|
+
for (const r of records) {
|
|
322
|
+
const conclusion = r.verdict.conclusion;
|
|
323
|
+
if (conclusion === 'benign' || conclusion === 'suspicious' || conclusion === 'malicious') {
|
|
324
|
+
verdictBreakdown[conclusion]++;
|
|
325
|
+
}
|
|
326
|
+
if (r.response.action !== 'log_only' &&
|
|
327
|
+
r.response.action !== 'notify' &&
|
|
328
|
+
r.response.success) {
|
|
329
|
+
threatsBlocked++;
|
|
330
|
+
}
|
|
331
|
+
const ip = r.event.metadata?.['sourceIP'] ??
|
|
332
|
+
r.event.metadata?.['remoteAddress'];
|
|
333
|
+
if (ip && conclusion !== 'benign') {
|
|
334
|
+
ipCounts.set(ip, (ipCounts.get(ip) ?? 0) + 1);
|
|
335
|
+
}
|
|
336
|
+
actionCounts.set(r.response.action, (actionCounts.get(r.response.action) ?? 0) + 1);
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
period: { start: cutoff.toISOString(), end: now.toISOString() },
|
|
340
|
+
totalEvents: records.length,
|
|
341
|
+
threatsBlocked,
|
|
342
|
+
suspiciousEvents: verdictBreakdown.suspicious,
|
|
343
|
+
benignEvents: verdictBreakdown.benign,
|
|
344
|
+
topAttackSources: [...ipCounts.entries()]
|
|
345
|
+
.sort((a, b) => b[1] - a[1])
|
|
346
|
+
.slice(0, 10)
|
|
347
|
+
.map(([ip, count]) => ({ ip, count })),
|
|
348
|
+
actionsTaken: [...actionCounts.entries()].map(([action, count]) => ({ action, count })),
|
|
349
|
+
verdictBreakdown,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/** Synchronous read of current log file only */
|
|
353
|
+
readLogRecordsSync(after) {
|
|
354
|
+
const records = [];
|
|
355
|
+
try {
|
|
356
|
+
const content = readFileSync(this.logPath, 'utf-8');
|
|
357
|
+
const lines = content.trim().split('\n').filter(Boolean);
|
|
358
|
+
for (const line of lines) {
|
|
359
|
+
try {
|
|
360
|
+
const record = JSON.parse(line);
|
|
361
|
+
if (new Date(record.timestamp) >= after) {
|
|
362
|
+
records.push(record);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
// Skip malformed lines
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
// Log file may not exist yet
|
|
372
|
+
}
|
|
373
|
+
return records;
|
|
374
|
+
}
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
// Anonymized Data Generation
|
|
377
|
+
// ---------------------------------------------------------------------------
|
|
378
|
+
generateAnonymizedData(event, verdict) {
|
|
379
|
+
const rawIP = event.metadata?.['sourceIP'] ??
|
|
380
|
+
event.metadata?.['remoteAddress'] ??
|
|
381
|
+
'unknown';
|
|
382
|
+
const attackSourceIP = anonymizeIP(rawIP);
|
|
383
|
+
const sigmaRuleMatched = verdict.evidence
|
|
384
|
+
.filter((e) => e.source === 'rule_match')
|
|
385
|
+
.map((e) => e.data?.['ruleId'])
|
|
386
|
+
.filter(Boolean)
|
|
387
|
+
.join(',') || 'none';
|
|
388
|
+
return {
|
|
389
|
+
attackSourceIP,
|
|
390
|
+
attackType: event.category,
|
|
391
|
+
mitreTechnique: verdict.mitreTechnique ?? 'unknown',
|
|
392
|
+
sigmaRuleMatched,
|
|
393
|
+
timestamp: new Date().toISOString(),
|
|
394
|
+
region: getCountryCode(),
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
/** Get total report count */
|
|
398
|
+
getReportCount() {
|
|
399
|
+
return this.reportCount;
|
|
400
|
+
}
|
|
401
|
+
/** Get current log file size in bytes */
|
|
402
|
+
getLogSizeBytes() {
|
|
403
|
+
try {
|
|
404
|
+
return statSync(this.logPath).size;
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
return 0;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/** Get number of rotated log files */
|
|
411
|
+
getRotatedFileCount() {
|
|
412
|
+
const dir = dirname(this.logPath);
|
|
413
|
+
const base = basename(this.logPath);
|
|
414
|
+
try {
|
|
415
|
+
return readdirSync(dir).filter((f) => f.startsWith(base + '.') && /\.\d+$/.test(f)).length;
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
return 0;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
423
|
+
// Utility functions
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
function getCountryCode() {
|
|
426
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
427
|
+
const tzCountryMap = {
|
|
428
|
+
'Asia/Taipei': 'TW',
|
|
429
|
+
'Asia/Tokyo': 'JP',
|
|
430
|
+
'Asia/Seoul': 'KR',
|
|
431
|
+
'Asia/Shanghai': 'CN',
|
|
432
|
+
'Asia/Hong_Kong': 'HK',
|
|
433
|
+
'Asia/Singapore': 'SG',
|
|
434
|
+
'America/New_York': 'US',
|
|
435
|
+
'America/Chicago': 'US',
|
|
436
|
+
'America/Denver': 'US',
|
|
437
|
+
'America/Los_Angeles': 'US',
|
|
438
|
+
'Europe/London': 'GB',
|
|
439
|
+
'Europe/Berlin': 'DE',
|
|
440
|
+
'Europe/Paris': 'FR',
|
|
441
|
+
'Australia/Sydney': 'AU',
|
|
442
|
+
};
|
|
443
|
+
return tzCountryMap[tz] ?? 'UNKNOWN';
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Anonymize IP: zero last two octets for IPv4, last two segments for IPv6.
|
|
447
|
+
* Stronger anonymization than single-octet zeroing.
|
|
448
|
+
*/
|
|
449
|
+
function anonymizeIP(ip) {
|
|
450
|
+
if (ip === 'unknown')
|
|
451
|
+
return ip;
|
|
452
|
+
// IPv4: zero last two octets (x.x.0.0)
|
|
453
|
+
const v4parts = ip.split('.');
|
|
454
|
+
if (v4parts.length === 4) {
|
|
455
|
+
v4parts[2] = '0';
|
|
456
|
+
v4parts[3] = '0';
|
|
457
|
+
return v4parts.join('.');
|
|
458
|
+
}
|
|
459
|
+
// IPv6: zero last two segments
|
|
460
|
+
const v6parts = ip.split(':');
|
|
461
|
+
if (v6parts.length > 2) {
|
|
462
|
+
v6parts[v6parts.length - 1] = '0';
|
|
463
|
+
v6parts[v6parts.length - 2] = '0';
|
|
464
|
+
return v6parts.join(':');
|
|
465
|
+
}
|
|
466
|
+
return ip;
|
|
467
|
+
}
|
|
468
|
+
//# sourceMappingURL=report-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-agent.js","sourceRoot":"","sources":["../../src/agent/report-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Respond Agent - Execute response actions with persistence, rollback, and escalation
|
|
3
|
+
* 回應代理 - 執行回應動作,支援持久化、回滾和漸進升級
|
|
4
|
+
*
|
|
5
|
+
* Third stage of the multi-agent pipeline. Determines and executes
|
|
6
|
+
* the appropriate response action based on verdict confidence levels
|
|
7
|
+
* and the configured action policy thresholds.
|
|
8
|
+
*
|
|
9
|
+
* Uses execFile (never exec) for all system commands to prevent
|
|
10
|
+
* command injection vulnerabilities.
|
|
11
|
+
*
|
|
12
|
+
* @module @panguard-ai/panguard-guard/agent/respond-agent
|
|
13
|
+
*/
|
|
14
|
+
import type { ThreatVerdict, ActionPolicy, ResponseResult, ResponseAction, GuardMode } from '../types.js';
|
|
15
|
+
/** Action manifest record for persistence and rollback */
|
|
16
|
+
interface ActionManifestEntry {
|
|
17
|
+
id: string;
|
|
18
|
+
action: ResponseAction;
|
|
19
|
+
target: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
expiresAt?: string;
|
|
22
|
+
rolledBack: boolean;
|
|
23
|
+
verdict: {
|
|
24
|
+
conclusion: string;
|
|
25
|
+
confidence: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Escalation tracker: IP/target → violation count */
|
|
29
|
+
interface EscalationRecord {
|
|
30
|
+
target: string;
|
|
31
|
+
violationCount: number;
|
|
32
|
+
firstSeen: string;
|
|
33
|
+
lastSeen: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Respond Agent determines and executes appropriate response actions
|
|
37
|
+
* with persistence, auto-unblock timers, SIGKILL fallback, and escalation.
|
|
38
|
+
*/
|
|
39
|
+
export declare class RespondAgent {
|
|
40
|
+
private readonly actionPolicy;
|
|
41
|
+
private mode;
|
|
42
|
+
private actionCount;
|
|
43
|
+
private readonly additionalWhitelistedIPs;
|
|
44
|
+
/** Action manifest for persistence and rollback */
|
|
45
|
+
private readonly manifest;
|
|
46
|
+
private readonly manifestPath;
|
|
47
|
+
/** Escalation tracker: target → record */
|
|
48
|
+
private readonly escalationMap;
|
|
49
|
+
/** Active unblock timers */
|
|
50
|
+
private readonly unblockTimers;
|
|
51
|
+
constructor(actionPolicy: ActionPolicy, mode: GuardMode, whitelistedIPs?: string[], dataDir?: string);
|
|
52
|
+
/** Update operating mode */
|
|
53
|
+
setMode(mode: GuardMode): void;
|
|
54
|
+
/**
|
|
55
|
+
* Execute response based on verdict with escalation awareness
|
|
56
|
+
*/
|
|
57
|
+
respond(verdict: ThreatVerdict): Promise<ResponseResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Rollback a previous action by manifest entry ID
|
|
60
|
+
*/
|
|
61
|
+
rollback(entryId: string): Promise<ResponseResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Get all active (non-rolled-back) actions
|
|
64
|
+
*/
|
|
65
|
+
getActiveActions(): ActionManifestEntry[];
|
|
66
|
+
private executeAction;
|
|
67
|
+
/**
|
|
68
|
+
* Block an IP address with auto-unblock timer
|
|
69
|
+
*/
|
|
70
|
+
private blockIP;
|
|
71
|
+
/**
|
|
72
|
+
* Unblock a previously blocked IP
|
|
73
|
+
*/
|
|
74
|
+
private unblockIP;
|
|
75
|
+
/**
|
|
76
|
+
* Schedule auto-unblock after duration
|
|
77
|
+
*/
|
|
78
|
+
private scheduleUnblock;
|
|
79
|
+
/**
|
|
80
|
+
* Kill a process with SIGKILL fallback
|
|
81
|
+
*/
|
|
82
|
+
private killProcess;
|
|
83
|
+
/**
|
|
84
|
+
* Wait for a process to exit, return true if still alive after timeout
|
|
85
|
+
*/
|
|
86
|
+
private waitForProcessExit;
|
|
87
|
+
/**
|
|
88
|
+
* Disable a user account
|
|
89
|
+
*/
|
|
90
|
+
private disableAccount;
|
|
91
|
+
/**
|
|
92
|
+
* Isolate a file (move to quarantine) with metadata tracking
|
|
93
|
+
*/
|
|
94
|
+
private isolateFile;
|
|
95
|
+
private recordAction;
|
|
96
|
+
private persistManifestEntry;
|
|
97
|
+
private loadManifest;
|
|
98
|
+
private trackEscalation;
|
|
99
|
+
private extractTarget;
|
|
100
|
+
private extractIP;
|
|
101
|
+
private extractPID;
|
|
102
|
+
private extractUsername;
|
|
103
|
+
private extractFilePath;
|
|
104
|
+
private extractProcessName;
|
|
105
|
+
/** Get total action count */
|
|
106
|
+
getActionCount(): number;
|
|
107
|
+
/** Get escalation records */
|
|
108
|
+
getEscalationRecords(): Map<string, EscalationRecord>;
|
|
109
|
+
/** Cleanup: clear all timers (for graceful shutdown) */
|
|
110
|
+
destroy(): void;
|
|
111
|
+
}
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=respond-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond-agent.d.ts","sourceRoot":"","sources":["../../src/agent/respond-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,cAAc,EACd,SAAS,EACV,MAAM,aAAa,CAAC;AAIrB,0DAA0D;AAC1D,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,sDAAsD;AACtD,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA2CD;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,IAAI,CAAY;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAc;IAEvD,mDAAmD;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IAErE,4BAA4B;IAC5B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoD;gBAGhF,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,SAAS,EACf,cAAc,GAAE,MAAM,EAAO,EAC7B,OAAO,SAAwB;IAkBjC,4BAA4B;IAC5B,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAI9B;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAgE9D;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA2CxD;;OAEG;IACH,gBAAgB,IAAI,mBAAmB,EAAE;YAQ3B,aAAa;IAgC3B;;OAEG;YACW,OAAO;IA2FrB;;OAEG;YACW,SAAS;IA6CvB;;OAEG;IACH,OAAO,CAAC,eAAe;IAwBvB;;OAEG;YACW,WAAW;IA0EzB;;OAEG;YACW,kBAAkB;IAiBhC;;OAEG;YACW,cAAc;IAuE5B;;OAEG;YACW,WAAW;IAkEzB,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,kBAAkB;IAQ1B,6BAA6B;IAC7B,cAAc,IAAI,MAAM;IAIxB,6BAA6B;IAC7B,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAIrD,wDAAwD;IACxD,OAAO,IAAI,IAAI;CAMhB"}
|