@astrofoundry/pi-astro 0.19.3 → 0.19.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/package.json
CHANGED
package/skills/security/SKILL.md
CHANGED
|
@@ -15,7 +15,7 @@ The `security` tool is read-only. Every call is a fixed command on the guest; `[
|
|
|
15
15
|
| `attention` | JSON: `bouncer` (count, oldest pull age), `wazuh_agents` (active/total, list), `recent_high_alerts` (24 h, level ≥ 10), `health_issues` |
|
|
16
16
|
| `agents` | `agent_control -l` |
|
|
17
17
|
| `alerts <days> [ip]` | summary: `count`, `uniqueIps`, `repeatIps`, `daily`, `topIps` (10), `scenarios`, `latest` (20 compact alerts: `at`, `ip`, `scenario`, `events`, `decisions`, `country`, `as`); with `ip`, `latest` holds every alert of that address |
|
|
18
|
-
| `decisions` | `count` and
|
|
18
|
+
| `decisions` | `count` and one row per active decision (`value`, `scope`, `type`, `duration`, `scenario`, `origin`, `alertId`, `country`) |
|
|
19
19
|
| `bouncers` | bouncers JSON (`name`, `last_pull`, `revoked`) |
|
|
20
20
|
| `metrics` | `cscli metrics -o json` |
|
|
21
21
|
| `wazuh-alerts <days> <minLevel>` | summary: count, groups by rule and agent, latest 20 (log line truncated to 200 chars) |
|
|
@@ -92,7 +92,7 @@ interface CrowdsecAlert {
|
|
|
92
92
|
scenario?: string;
|
|
93
93
|
events_count?: number;
|
|
94
94
|
source?: { ip?: string; range?: string; as_number?: string; as_name?: string; cn?: string };
|
|
95
|
-
decisions?:
|
|
95
|
+
decisions?: CrowdsecDecision[];
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
interface CompactAlert {
|
|
@@ -188,17 +188,32 @@ interface CrowdsecDecision {
|
|
|
188
188
|
origin?: string;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
191
|
+
interface CompactDecision extends CrowdsecDecision {
|
|
192
|
+
alertId?: number;
|
|
193
|
+
country?: string;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* `cscli decisions list -o json` returns alerts, each with its active decisions
|
|
198
|
+
* (the table's ALERT ID, COUNTRY, and AS columns are alert fields). Flattens to one row per decision.
|
|
199
|
+
*/
|
|
200
|
+
export function compactDecisions(text: string): { count: number; decisions: CompactDecision[] } {
|
|
201
|
+
const decisions: CompactDecision[] = [];
|
|
202
|
+
for (const alert of parseJsonArray<CrowdsecAlert & { decisions?: CrowdsecDecision[] }>(text, "decisions")) {
|
|
203
|
+
for (const d of alert.decisions ?? []) {
|
|
204
|
+
decisions.push({
|
|
205
|
+
id: d.id,
|
|
206
|
+
value: d.value,
|
|
207
|
+
scope: d.scope,
|
|
208
|
+
type: d.type,
|
|
209
|
+
duration: d.duration,
|
|
210
|
+
scenario: d.scenario ?? alert.scenario,
|
|
211
|
+
origin: d.origin,
|
|
212
|
+
alertId: alert.id,
|
|
213
|
+
country: alert.source?.cn,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
202
217
|
return { count: decisions.length, decisions };
|
|
203
218
|
}
|
|
204
219
|
|
|
@@ -244,9 +244,18 @@ describe("security wrapper", () => {
|
|
|
244
244
|
expect(summary.latest[0]).toMatchObject({ id: 3, ip: "203.0.113.9", decisions: ["ban 4h"], country: "US" });
|
|
245
245
|
expect(summariseAlerts(text, 7, "45.79.207.181").latest.map((a) => a.id)).toEqual([2, 1]);
|
|
246
246
|
expect(summariseAlerts("null", 7)).toMatchObject({ count: 0, uniqueIps: 0 });
|
|
247
|
-
|
|
247
|
+
const decisionsText = JSON.stringify([
|
|
248
|
+
{
|
|
249
|
+
id: 364,
|
|
250
|
+
scenario: "37pla/frontdoor-sni-scanning",
|
|
251
|
+
source: { ip: "203.0.113.9", cn: "US" },
|
|
252
|
+
decisions: [{ id: 9, value: "203.0.113.9", scope: "Ip", type: "ban", duration: "3h59m", origin: "crowdsec", simulated: false }],
|
|
253
|
+
},
|
|
254
|
+
{ id: 365, scenario: "x", source: {}, decisions: [] },
|
|
255
|
+
]);
|
|
256
|
+
expect(compactDecisions(decisionsText)).toEqual({
|
|
248
257
|
count: 1,
|
|
249
|
-
decisions: [{ id: 9, value: "203.0.113.9", scope: "Ip", type: "ban", duration: "3h59m", scenario: "
|
|
258
|
+
decisions: [{ id: 9, value: "203.0.113.9", scope: "Ip", type: "ban", duration: "3h59m", scenario: "37pla/frontdoor-sni-scanning", origin: "crowdsec", alertId: 364, country: "US" }],
|
|
250
259
|
});
|
|
251
260
|
expect(() => summariseAlerts("not json", 7)).toThrow(/no JSON/);
|
|
252
261
|
});
|