@sentriflow/cli 0.1.6 → 0.1.8
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/index.js +484 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9975,6 +9975,7 @@ var JsonRuleCompiler = class {
|
|
|
9975
9975
|
id: jsonRule.id,
|
|
9976
9976
|
selector: jsonRule.selector,
|
|
9977
9977
|
vendor: jsonRule.vendor,
|
|
9978
|
+
category: jsonRule.category,
|
|
9978
9979
|
metadata: jsonRule.metadata,
|
|
9979
9980
|
check: (node, _ctx) => {
|
|
9980
9981
|
const passed = !this.evaluateCheck(jsonRule.check, node);
|
|
@@ -10333,6 +10334,350 @@ function validateRegex(pattern, flags, path, ctx) {
|
|
|
10333
10334
|
}
|
|
10334
10335
|
}
|
|
10335
10336
|
|
|
10337
|
+
// ../core/src/ip/extractor.ts
|
|
10338
|
+
function isValidIPv4(ip) {
|
|
10339
|
+
if (!ip || typeof ip !== "string") return false;
|
|
10340
|
+
const octets = ip.split(".");
|
|
10341
|
+
if (octets.length !== 4) return false;
|
|
10342
|
+
for (const octet of octets) {
|
|
10343
|
+
if (!/^\d+$/.test(octet)) return false;
|
|
10344
|
+
if (octet.length > 1 && octet.startsWith("0")) return false;
|
|
10345
|
+
const num = parseInt(octet, 10);
|
|
10346
|
+
if (isNaN(num) || num < 0 || num > 255) return false;
|
|
10347
|
+
}
|
|
10348
|
+
return true;
|
|
10349
|
+
}
|
|
10350
|
+
function isValidIPv6(ip) {
|
|
10351
|
+
if (!ip || typeof ip !== "string") return false;
|
|
10352
|
+
let addr = ip;
|
|
10353
|
+
const zoneIndex = ip.indexOf("%");
|
|
10354
|
+
if (zoneIndex !== -1) {
|
|
10355
|
+
addr = ip.substring(0, zoneIndex);
|
|
10356
|
+
}
|
|
10357
|
+
if (!addr.includes(":")) return false;
|
|
10358
|
+
if (addr.includes(":::")) return false;
|
|
10359
|
+
const doubleColonCount = (addr.match(/::/g) || []).length;
|
|
10360
|
+
if (doubleColonCount > 1) return false;
|
|
10361
|
+
const parts = addr.split(":");
|
|
10362
|
+
if (doubleColonCount === 1) {
|
|
10363
|
+
const nonEmptyParts = parts.filter((p) => p !== "");
|
|
10364
|
+
for (const part of nonEmptyParts) {
|
|
10365
|
+
if (!/^[0-9a-fA-F]{1,4}$/.test(part)) return false;
|
|
10366
|
+
}
|
|
10367
|
+
if (nonEmptyParts.length > 7) return false;
|
|
10368
|
+
} else {
|
|
10369
|
+
if (parts.length !== 8) return false;
|
|
10370
|
+
for (const part of parts) {
|
|
10371
|
+
if (!/^[0-9a-fA-F]{1,4}$/.test(part)) return false;
|
|
10372
|
+
}
|
|
10373
|
+
}
|
|
10374
|
+
return true;
|
|
10375
|
+
}
|
|
10376
|
+
function isValidSubnet(subnet) {
|
|
10377
|
+
if (!subnet || typeof subnet !== "string") return false;
|
|
10378
|
+
const slashIndex = subnet.lastIndexOf("/");
|
|
10379
|
+
if (slashIndex === -1) return false;
|
|
10380
|
+
const ip = subnet.substring(0, slashIndex);
|
|
10381
|
+
const prefixStr = subnet.substring(slashIndex + 1);
|
|
10382
|
+
if (!/^\d+$/.test(prefixStr)) return false;
|
|
10383
|
+
const prefix = parseInt(prefixStr, 10);
|
|
10384
|
+
if (isValidIPv4(ip)) {
|
|
10385
|
+
return prefix >= 0 && prefix <= 32;
|
|
10386
|
+
} else if (isValidIPv6(ip)) {
|
|
10387
|
+
return prefix >= 0 && prefix <= 128;
|
|
10388
|
+
}
|
|
10389
|
+
return false;
|
|
10390
|
+
}
|
|
10391
|
+
function normalizeIPv4(ip) {
|
|
10392
|
+
return ip.split(".").map((octet) => parseInt(octet, 10).toString()).join(".");
|
|
10393
|
+
}
|
|
10394
|
+
function normalizeIPv6(ip) {
|
|
10395
|
+
let addr = ip;
|
|
10396
|
+
const zoneIndex = ip.indexOf("%");
|
|
10397
|
+
if (zoneIndex !== -1) {
|
|
10398
|
+
addr = ip.substring(0, zoneIndex);
|
|
10399
|
+
}
|
|
10400
|
+
addr = addr.toLowerCase();
|
|
10401
|
+
if (addr.includes("::")) {
|
|
10402
|
+
const sides = addr.split("::");
|
|
10403
|
+
const left = sides[0] ? sides[0].split(":").filter((p) => p !== "") : [];
|
|
10404
|
+
const right = sides[1] ? sides[1].split(":").filter((p) => p !== "") : [];
|
|
10405
|
+
const zerosNeeded = 8 - left.length - right.length;
|
|
10406
|
+
const expanded = [];
|
|
10407
|
+
for (const part of left) {
|
|
10408
|
+
expanded.push(parseInt(part, 16).toString(16));
|
|
10409
|
+
}
|
|
10410
|
+
for (let i = 0; i < zerosNeeded; i++) {
|
|
10411
|
+
expanded.push("0");
|
|
10412
|
+
}
|
|
10413
|
+
for (const part of right) {
|
|
10414
|
+
expanded.push(parseInt(part, 16).toString(16));
|
|
10415
|
+
}
|
|
10416
|
+
return expanded.join(":");
|
|
10417
|
+
}
|
|
10418
|
+
const parts = addr.split(":");
|
|
10419
|
+
const result = [];
|
|
10420
|
+
for (const part of parts) {
|
|
10421
|
+
if (part !== "") {
|
|
10422
|
+
result.push(parseInt(part, 16).toString(16));
|
|
10423
|
+
}
|
|
10424
|
+
}
|
|
10425
|
+
return result.join(":");
|
|
10426
|
+
}
|
|
10427
|
+
function ipv4ToNumber(ip) {
|
|
10428
|
+
const octets = ip.split(".").map(Number);
|
|
10429
|
+
const o0 = octets[0] ?? 0;
|
|
10430
|
+
const o1 = octets[1] ?? 0;
|
|
10431
|
+
const o2 = octets[2] ?? 0;
|
|
10432
|
+
const o3 = octets[3] ?? 0;
|
|
10433
|
+
return (o0 << 24 >>> 0) + (o1 << 16) + (o2 << 8) + o3;
|
|
10434
|
+
}
|
|
10435
|
+
function compareIPv4(a, b) {
|
|
10436
|
+
const numA = ipv4ToNumber(a);
|
|
10437
|
+
const numB = ipv4ToNumber(b);
|
|
10438
|
+
return numA < numB ? -1 : numA > numB ? 1 : 0;
|
|
10439
|
+
}
|
|
10440
|
+
function expandIPv6(ip) {
|
|
10441
|
+
let addr = ip;
|
|
10442
|
+
const zoneIndex = ip.indexOf("%");
|
|
10443
|
+
if (zoneIndex !== -1) {
|
|
10444
|
+
addr = ip.substring(0, zoneIndex);
|
|
10445
|
+
}
|
|
10446
|
+
const parts = addr.split(":");
|
|
10447
|
+
const result = [];
|
|
10448
|
+
for (let i = 0; i < parts.length; i++) {
|
|
10449
|
+
if (parts[i] === "" && i > 0 && i < parts.length - 1) {
|
|
10450
|
+
const nonEmpty = parts.filter((p) => p !== "").length;
|
|
10451
|
+
const zeros = 8 - nonEmpty;
|
|
10452
|
+
for (let j = 0; j < zeros; j++) {
|
|
10453
|
+
result.push("0");
|
|
10454
|
+
}
|
|
10455
|
+
} else if (parts[i] !== "") {
|
|
10456
|
+
result.push(parts[i] ?? "0");
|
|
10457
|
+
} else if (i === 0 && parts[1] === "") {
|
|
10458
|
+
const nonEmpty = parts.filter((p) => p !== "").length;
|
|
10459
|
+
const zeros = 8 - nonEmpty;
|
|
10460
|
+
for (let j = 0; j < zeros; j++) {
|
|
10461
|
+
result.push("0");
|
|
10462
|
+
}
|
|
10463
|
+
} else if (i === parts.length - 1 && parts[i - 1] === "") {
|
|
10464
|
+
}
|
|
10465
|
+
}
|
|
10466
|
+
while (result.length < 8) {
|
|
10467
|
+
result.push("0");
|
|
10468
|
+
}
|
|
10469
|
+
return result.slice(0, 8);
|
|
10470
|
+
}
|
|
10471
|
+
function ipv6ToBigInt(ip) {
|
|
10472
|
+
const parts = expandIPv6(ip);
|
|
10473
|
+
let result = 0n;
|
|
10474
|
+
for (const part of parts) {
|
|
10475
|
+
result = (result << 16n) + BigInt(parseInt(part, 16) || 0);
|
|
10476
|
+
}
|
|
10477
|
+
return result;
|
|
10478
|
+
}
|
|
10479
|
+
function compareIPv6(a, b) {
|
|
10480
|
+
const bigA = ipv6ToBigInt(a);
|
|
10481
|
+
const bigB = ipv6ToBigInt(b);
|
|
10482
|
+
return bigA < bigB ? -1 : bigA > bigB ? 1 : 0;
|
|
10483
|
+
}
|
|
10484
|
+
function sortIPv4Addresses(ips) {
|
|
10485
|
+
return [...ips].sort(compareIPv4);
|
|
10486
|
+
}
|
|
10487
|
+
function sortIPv6Addresses(ips) {
|
|
10488
|
+
return [...ips].sort(compareIPv6);
|
|
10489
|
+
}
|
|
10490
|
+
function parseSubnet(subnet) {
|
|
10491
|
+
const slashIndex = subnet.lastIndexOf("/");
|
|
10492
|
+
return {
|
|
10493
|
+
network: subnet.substring(0, slashIndex),
|
|
10494
|
+
prefix: parseInt(subnet.substring(slashIndex + 1), 10)
|
|
10495
|
+
};
|
|
10496
|
+
}
|
|
10497
|
+
function sortSubnets(subnets, type) {
|
|
10498
|
+
const compare = type === "ipv4" ? compareIPv4 : compareIPv6;
|
|
10499
|
+
return [...subnets].sort((a, b) => {
|
|
10500
|
+
const subA = parseSubnet(a);
|
|
10501
|
+
const subB = parseSubnet(b);
|
|
10502
|
+
const netCompare = compare(subA.network, subB.network);
|
|
10503
|
+
if (netCompare !== 0) return netCompare;
|
|
10504
|
+
return subA.prefix - subB.prefix;
|
|
10505
|
+
});
|
|
10506
|
+
}
|
|
10507
|
+
function isSubnetMask(ip) {
|
|
10508
|
+
if (!ip.startsWith("255.")) return false;
|
|
10509
|
+
const octets = ip.split(".").map(Number);
|
|
10510
|
+
const num = ((octets[0] ?? 0) << 24) + ((octets[1] ?? 0) << 16) + ((octets[2] ?? 0) << 8) + (octets[3] ?? 0);
|
|
10511
|
+
const inverted = ~num >>> 0;
|
|
10512
|
+
return inverted === 0 || (inverted & inverted + 1) === 0;
|
|
10513
|
+
}
|
|
10514
|
+
function isWildcardMask(ip) {
|
|
10515
|
+
if (!ip.startsWith("0.")) return false;
|
|
10516
|
+
const octets = ip.split(".").map(Number);
|
|
10517
|
+
const num = ((octets[0] ?? 0) << 24) + ((octets[1] ?? 0) << 16) + ((octets[2] ?? 0) << 8) + (octets[3] ?? 0);
|
|
10518
|
+
return num === 0 || (num + 1 & num) === 0;
|
|
10519
|
+
}
|
|
10520
|
+
function maskToCidr(mask) {
|
|
10521
|
+
if (!isSubnetMask(mask)) return -1;
|
|
10522
|
+
const octets = mask.split(".").map(Number);
|
|
10523
|
+
const num = ((octets[0] ?? 0) << 24) + ((octets[1] ?? 0) << 16) + ((octets[2] ?? 0) << 8) + (octets[3] ?? 0);
|
|
10524
|
+
let prefix = 0;
|
|
10525
|
+
let n = num >>> 0;
|
|
10526
|
+
while (n & 2147483648) {
|
|
10527
|
+
prefix++;
|
|
10528
|
+
n = n << 1 >>> 0;
|
|
10529
|
+
}
|
|
10530
|
+
return prefix;
|
|
10531
|
+
}
|
|
10532
|
+
function wildcardToCidr(wildcard) {
|
|
10533
|
+
if (!isWildcardMask(wildcard)) return -1;
|
|
10534
|
+
const octets = wildcard.split(".").map(Number);
|
|
10535
|
+
const num = ((octets[0] ?? 0) << 24) + ((octets[1] ?? 0) << 16) + ((octets[2] ?? 0) << 8) + (octets[3] ?? 0);
|
|
10536
|
+
let prefix = 0;
|
|
10537
|
+
let n = num >>> 0;
|
|
10538
|
+
while (prefix < 32 && !(n & 2147483648)) {
|
|
10539
|
+
prefix++;
|
|
10540
|
+
n = n << 1 >>> 0;
|
|
10541
|
+
}
|
|
10542
|
+
return prefix;
|
|
10543
|
+
}
|
|
10544
|
+
var IPV4_PATTERN = /\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b/g;
|
|
10545
|
+
var IPV4_CIDR_PATTERN = /\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\/(?:3[0-2]|[12]?[0-9])\b/g;
|
|
10546
|
+
var IPV4_WITH_MASK_PATTERN = /\b((?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\s+(255\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\b/g;
|
|
10547
|
+
var IPV4_WITH_MASK_KEYWORD_PATTERN = /\b((?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\s+mask\s+(255\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\b/gi;
|
|
10548
|
+
var IPV4_WITH_WILDCARD_PATTERN = /\b((?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\s+(0\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\b/g;
|
|
10549
|
+
var IPV6_PATTERN = /(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|:(?::[0-9a-fA-F]{1,4}){1,7}|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|(?:[0-9a-fA-F]{1,4}:){1,7}:|::/g;
|
|
10550
|
+
var IPV6_CIDR_PATTERN = /(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|:(?::[0-9a-fA-F]{1,4}){1,7}|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|(?:[0-9a-fA-F]{1,4}:){1,7}:|::)\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])/g;
|
|
10551
|
+
function createEmptyIPSummary() {
|
|
10552
|
+
return {
|
|
10553
|
+
ipv4Addresses: [],
|
|
10554
|
+
ipv6Addresses: [],
|
|
10555
|
+
ipv4Subnets: [],
|
|
10556
|
+
ipv6Subnets: [],
|
|
10557
|
+
counts: {
|
|
10558
|
+
ipv4: 0,
|
|
10559
|
+
ipv6: 0,
|
|
10560
|
+
ipv4Subnets: 0,
|
|
10561
|
+
ipv6Subnets: 0,
|
|
10562
|
+
total: 0
|
|
10563
|
+
}
|
|
10564
|
+
};
|
|
10565
|
+
}
|
|
10566
|
+
function extractIPSummary(content, options = {}) {
|
|
10567
|
+
if (!content || typeof content !== "string") {
|
|
10568
|
+
return createEmptyIPSummary();
|
|
10569
|
+
}
|
|
10570
|
+
const ipv4Set = /* @__PURE__ */ new Set();
|
|
10571
|
+
const ipv6Set = /* @__PURE__ */ new Set();
|
|
10572
|
+
const ipv4SubnetSet = /* @__PURE__ */ new Set();
|
|
10573
|
+
const ipv6SubnetSet = /* @__PURE__ */ new Set();
|
|
10574
|
+
const subnetNetworks = /* @__PURE__ */ new Set();
|
|
10575
|
+
const ipsWithMasks = /* @__PURE__ */ new Set();
|
|
10576
|
+
if (!options.skipSubnets) {
|
|
10577
|
+
const ipv4CidrMatches = content.matchAll(IPV4_CIDR_PATTERN);
|
|
10578
|
+
for (const match of ipv4CidrMatches) {
|
|
10579
|
+
const subnet = match[0];
|
|
10580
|
+
if (isValidSubnet(subnet)) {
|
|
10581
|
+
const { network } = parseSubnet(subnet);
|
|
10582
|
+
const normalizedNetwork = normalizeIPv4(network);
|
|
10583
|
+
ipv4SubnetSet.add(`${normalizedNetwork}/${parseSubnet(subnet).prefix}`);
|
|
10584
|
+
subnetNetworks.add(normalizedNetwork);
|
|
10585
|
+
}
|
|
10586
|
+
}
|
|
10587
|
+
const ipMaskMatches = content.matchAll(IPV4_WITH_MASK_PATTERN);
|
|
10588
|
+
for (const match of ipMaskMatches) {
|
|
10589
|
+
const ip = match[1];
|
|
10590
|
+
const mask = match[2];
|
|
10591
|
+
if (ip && mask && isValidIPv4(ip) && isSubnetMask(mask)) {
|
|
10592
|
+
const normalizedIP = normalizeIPv4(ip);
|
|
10593
|
+
const prefix = maskToCidr(mask);
|
|
10594
|
+
if (prefix >= 0) {
|
|
10595
|
+
ipv4SubnetSet.add(`${normalizedIP}/${prefix}`);
|
|
10596
|
+
ipsWithMasks.add(normalizedIP);
|
|
10597
|
+
}
|
|
10598
|
+
}
|
|
10599
|
+
}
|
|
10600
|
+
const ipMaskKeywordMatches = content.matchAll(IPV4_WITH_MASK_KEYWORD_PATTERN);
|
|
10601
|
+
for (const match of ipMaskKeywordMatches) {
|
|
10602
|
+
const ip = match[1];
|
|
10603
|
+
const mask = match[2];
|
|
10604
|
+
if (ip && mask && isValidIPv4(ip) && isSubnetMask(mask)) {
|
|
10605
|
+
const normalizedIP = normalizeIPv4(ip);
|
|
10606
|
+
const prefix = maskToCidr(mask);
|
|
10607
|
+
if (prefix >= 0) {
|
|
10608
|
+
ipv4SubnetSet.add(`${normalizedIP}/${prefix}`);
|
|
10609
|
+
ipsWithMasks.add(normalizedIP);
|
|
10610
|
+
}
|
|
10611
|
+
}
|
|
10612
|
+
}
|
|
10613
|
+
const ipWildcardMatches = content.matchAll(IPV4_WITH_WILDCARD_PATTERN);
|
|
10614
|
+
for (const match of ipWildcardMatches) {
|
|
10615
|
+
const ip = match[1];
|
|
10616
|
+
const wildcard = match[2];
|
|
10617
|
+
if (ip && wildcard && isValidIPv4(ip) && isWildcardMask(wildcard)) {
|
|
10618
|
+
const normalizedIP = normalizeIPv4(ip);
|
|
10619
|
+
const prefix = wildcardToCidr(wildcard);
|
|
10620
|
+
if (prefix >= 0) {
|
|
10621
|
+
ipv4SubnetSet.add(`${normalizedIP}/${prefix}`);
|
|
10622
|
+
ipsWithMasks.add(normalizedIP);
|
|
10623
|
+
}
|
|
10624
|
+
}
|
|
10625
|
+
}
|
|
10626
|
+
}
|
|
10627
|
+
const ipv4Matches = content.matchAll(IPV4_PATTERN);
|
|
10628
|
+
for (const match of ipv4Matches) {
|
|
10629
|
+
const ip = match[0];
|
|
10630
|
+
if (isValidIPv4(ip)) {
|
|
10631
|
+
const normalized = normalizeIPv4(ip);
|
|
10632
|
+
if (!subnetNetworks.has(normalized) && !ipsWithMasks.has(normalized) && !isSubnetMask(normalized) && !isWildcardMask(normalized)) {
|
|
10633
|
+
ipv4Set.add(normalized);
|
|
10634
|
+
}
|
|
10635
|
+
}
|
|
10636
|
+
}
|
|
10637
|
+
if (!options.skipIPv6) {
|
|
10638
|
+
if (!options.skipSubnets) {
|
|
10639
|
+
const ipv6CidrMatches = content.matchAll(IPV6_CIDR_PATTERN);
|
|
10640
|
+
for (const match of ipv6CidrMatches) {
|
|
10641
|
+
const subnet = match[0];
|
|
10642
|
+
if (isValidSubnet(subnet)) {
|
|
10643
|
+
const { network, prefix } = parseSubnet(subnet);
|
|
10644
|
+
const normalizedNetwork = normalizeIPv6(network);
|
|
10645
|
+
ipv6SubnetSet.add(`${normalizedNetwork}/${prefix}`);
|
|
10646
|
+
subnetNetworks.add(normalizedNetwork);
|
|
10647
|
+
}
|
|
10648
|
+
}
|
|
10649
|
+
}
|
|
10650
|
+
const ipv6Matches = content.matchAll(IPV6_PATTERN);
|
|
10651
|
+
for (const match of ipv6Matches) {
|
|
10652
|
+
const ip = match[0];
|
|
10653
|
+
if (isValidIPv6(ip)) {
|
|
10654
|
+
const normalized = normalizeIPv6(ip);
|
|
10655
|
+
if (!subnetNetworks.has(normalized)) {
|
|
10656
|
+
ipv6Set.add(normalized);
|
|
10657
|
+
}
|
|
10658
|
+
}
|
|
10659
|
+
}
|
|
10660
|
+
}
|
|
10661
|
+
const ipv4Addresses = sortIPv4Addresses([...ipv4Set]);
|
|
10662
|
+
const ipv6Addresses = sortIPv6Addresses([...ipv6Set]);
|
|
10663
|
+
const ipv4Subnets = sortSubnets([...ipv4SubnetSet], "ipv4");
|
|
10664
|
+
const ipv6Subnets = sortSubnets([...ipv6SubnetSet], "ipv6");
|
|
10665
|
+
const counts = {
|
|
10666
|
+
ipv4: ipv4Addresses.length,
|
|
10667
|
+
ipv6: ipv6Addresses.length,
|
|
10668
|
+
ipv4Subnets: ipv4Subnets.length,
|
|
10669
|
+
ipv6Subnets: ipv6Subnets.length,
|
|
10670
|
+
total: ipv4Addresses.length + ipv6Addresses.length + ipv4Subnets.length + ipv6Subnets.length
|
|
10671
|
+
};
|
|
10672
|
+
return {
|
|
10673
|
+
ipv4Addresses,
|
|
10674
|
+
ipv6Addresses,
|
|
10675
|
+
ipv4Subnets,
|
|
10676
|
+
ipv6Subnets,
|
|
10677
|
+
counts
|
|
10678
|
+
};
|
|
10679
|
+
}
|
|
10680
|
+
|
|
10336
10681
|
// index.ts
|
|
10337
10682
|
import { readFile } from "fs/promises";
|
|
10338
10683
|
import { statSync as statSync2 } from "fs";
|
|
@@ -10340,7 +10685,7 @@ import { resolve as resolve4, dirname as dirname2, basename } from "path";
|
|
|
10340
10685
|
|
|
10341
10686
|
// src/sarif.ts
|
|
10342
10687
|
import { relative } from "path";
|
|
10343
|
-
function generateSarif(results, filePath, rules, options = {}) {
|
|
10688
|
+
function generateSarif(results, filePath, rules, options = {}, ipSummary) {
|
|
10344
10689
|
const fileUri = options.relativePaths ? relative(options.baseDir ?? process.cwd(), filePath) : filePath;
|
|
10345
10690
|
const sarifResults = results.map((result) => {
|
|
10346
10691
|
return {
|
|
@@ -10407,7 +10752,7 @@ function generateSarif(results, filePath, rules, options = {}) {
|
|
|
10407
10752
|
tool: {
|
|
10408
10753
|
driver: {
|
|
10409
10754
|
name: "Sentriflow",
|
|
10410
|
-
version: "0.1.
|
|
10755
|
+
version: "0.1.8",
|
|
10411
10756
|
informationUri: "https://github.com/sentriflow/sentriflow",
|
|
10412
10757
|
rules: sarifRules,
|
|
10413
10758
|
// SEC-007: Include CWE taxonomy when rules reference it
|
|
@@ -10434,13 +10779,61 @@ function generateSarif(results, filePath, rules, options = {}) {
|
|
|
10434
10779
|
}
|
|
10435
10780
|
]
|
|
10436
10781
|
},
|
|
10437
|
-
results: sarifResults
|
|
10782
|
+
results: sarifResults,
|
|
10783
|
+
// Include IP summary in properties if available
|
|
10784
|
+
...ipSummary && {
|
|
10785
|
+
properties: {
|
|
10786
|
+
ipSummary
|
|
10787
|
+
}
|
|
10788
|
+
}
|
|
10438
10789
|
}
|
|
10439
10790
|
]
|
|
10440
10791
|
};
|
|
10441
10792
|
return JSON.stringify(report, null, 2);
|
|
10442
10793
|
}
|
|
10794
|
+
function aggregateIPSummaries(summaries) {
|
|
10795
|
+
if (summaries.length === 0) return void 0;
|
|
10796
|
+
const ipv4Set = /* @__PURE__ */ new Set();
|
|
10797
|
+
const ipv6Set = /* @__PURE__ */ new Set();
|
|
10798
|
+
const ipv4SubnetSet = /* @__PURE__ */ new Set();
|
|
10799
|
+
const ipv6SubnetSet = /* @__PURE__ */ new Set();
|
|
10800
|
+
for (const summary of summaries) {
|
|
10801
|
+
for (const ip of summary.ipv4Addresses) ipv4Set.add(ip);
|
|
10802
|
+
for (const ip of summary.ipv6Addresses) ipv6Set.add(ip);
|
|
10803
|
+
for (const subnet of summary.ipv4Subnets) ipv4SubnetSet.add(subnet);
|
|
10804
|
+
for (const subnet of summary.ipv6Subnets) ipv6SubnetSet.add(subnet);
|
|
10805
|
+
}
|
|
10806
|
+
const ipv4Addresses = [...ipv4Set].sort((a, b) => {
|
|
10807
|
+
const aParts = a.split(".").map(Number);
|
|
10808
|
+
const bParts = b.split(".").map(Number);
|
|
10809
|
+
for (let i = 0; i < 4; i++) {
|
|
10810
|
+
if ((aParts[i] ?? 0) !== (bParts[i] ?? 0)) {
|
|
10811
|
+
return (aParts[i] ?? 0) - (bParts[i] ?? 0);
|
|
10812
|
+
}
|
|
10813
|
+
}
|
|
10814
|
+
return 0;
|
|
10815
|
+
});
|
|
10816
|
+
const ipv6Addresses = [...ipv6Set].sort();
|
|
10817
|
+
const ipv4Subnets = [...ipv4SubnetSet].sort();
|
|
10818
|
+
const ipv6Subnets = [...ipv6SubnetSet].sort();
|
|
10819
|
+
return {
|
|
10820
|
+
ipv4Addresses,
|
|
10821
|
+
ipv6Addresses,
|
|
10822
|
+
ipv4Subnets,
|
|
10823
|
+
ipv6Subnets,
|
|
10824
|
+
counts: {
|
|
10825
|
+
ipv4: ipv4Addresses.length,
|
|
10826
|
+
ipv6: ipv6Addresses.length,
|
|
10827
|
+
ipv4Subnets: ipv4Subnets.length,
|
|
10828
|
+
ipv6Subnets: ipv6Subnets.length,
|
|
10829
|
+
total: ipv4Addresses.length + ipv6Addresses.length + ipv4Subnets.length + ipv6Subnets.length
|
|
10830
|
+
}
|
|
10831
|
+
};
|
|
10832
|
+
}
|
|
10443
10833
|
function generateMultiFileSarif(fileResults, rules, options = {}) {
|
|
10834
|
+
const aggregatedIpSummary = aggregateIPSummaries(
|
|
10835
|
+
fileResults.map((fr) => fr.ipSummary).filter((s) => !!s)
|
|
10836
|
+
);
|
|
10444
10837
|
const allSarifResults = fileResults.flatMap(({ filePath, results }) => {
|
|
10445
10838
|
const fileUri = options.relativePaths ? relative(options.baseDir ?? process.cwd(), filePath) : filePath;
|
|
10446
10839
|
return results.map((result) => ({
|
|
@@ -10513,7 +10906,7 @@ function generateMultiFileSarif(fileResults, rules, options = {}) {
|
|
|
10513
10906
|
tool: {
|
|
10514
10907
|
driver: {
|
|
10515
10908
|
name: "Sentriflow",
|
|
10516
|
-
version: "0.1.
|
|
10909
|
+
version: "0.1.8",
|
|
10517
10910
|
informationUri: "https://github.com/sentriflow/sentriflow",
|
|
10518
10911
|
rules: sarifRules,
|
|
10519
10912
|
// SEC-007: Include CWE taxonomy when rules reference it
|
|
@@ -10544,7 +10937,13 @@ function generateMultiFileSarif(fileResults, rules, options = {}) {
|
|
|
10544
10937
|
}
|
|
10545
10938
|
]
|
|
10546
10939
|
},
|
|
10547
|
-
results: allSarifResults
|
|
10940
|
+
results: allSarifResults,
|
|
10941
|
+
// Include aggregated IP summary in properties if available
|
|
10942
|
+
...aggregatedIpSummary && {
|
|
10943
|
+
properties: {
|
|
10944
|
+
ipSummary: aggregatedIpSummary
|
|
10945
|
+
}
|
|
10946
|
+
}
|
|
10548
10947
|
}
|
|
10549
10948
|
]
|
|
10550
10949
|
};
|
|
@@ -10556,10 +10955,12 @@ var NoMulticastBroadcastIp = {
|
|
|
10556
10955
|
id: "NET-IP-001",
|
|
10557
10956
|
selector: "ip address",
|
|
10558
10957
|
vendor: "common",
|
|
10958
|
+
category: "IP-Addressing",
|
|
10559
10959
|
metadata: {
|
|
10560
10960
|
level: "error",
|
|
10561
10961
|
obu: "Network Engineering",
|
|
10562
10962
|
owner: "NetOps",
|
|
10963
|
+
description: "Ensure IP addresses are not Multicast, Broadcast, or Network ID addresses.",
|
|
10563
10964
|
remediation: "Configure a valid unicast IP address. Do not use Multicast, Broadcast, or Network ID addresses."
|
|
10564
10965
|
},
|
|
10565
10966
|
check: (node) => {
|
|
@@ -10669,10 +11070,12 @@ var InterfaceDescriptionRequired = {
|
|
|
10669
11070
|
id: "NET-DOC-001",
|
|
10670
11071
|
selector: "interface",
|
|
10671
11072
|
vendor: "common",
|
|
11073
|
+
category: "Documentation",
|
|
10672
11074
|
metadata: {
|
|
10673
11075
|
level: "warning",
|
|
10674
11076
|
obu: "Network Engineering",
|
|
10675
11077
|
owner: "NetOps",
|
|
11078
|
+
description: "Ensure interfaces have descriptive labels for operational clarity.",
|
|
10676
11079
|
remediation: 'Add a description to the interface using the "description" command.'
|
|
10677
11080
|
},
|
|
10678
11081
|
check: (node) => {
|
|
@@ -10750,6 +11153,7 @@ var TrunkNoDTP = {
|
|
|
10750
11153
|
id: "NET-TRUNK-001",
|
|
10751
11154
|
selector: "interface",
|
|
10752
11155
|
vendor: "cisco-ios",
|
|
11156
|
+
category: "Network-Segmentation",
|
|
10753
11157
|
metadata: {
|
|
10754
11158
|
level: "warning",
|
|
10755
11159
|
obu: "Network Engineering",
|
|
@@ -10783,6 +11187,7 @@ var AccessExplicitMode = {
|
|
|
10783
11187
|
id: "NET-ACCESS-001",
|
|
10784
11188
|
selector: "interface",
|
|
10785
11189
|
vendor: "cisco-ios",
|
|
11190
|
+
category: "Network-Segmentation",
|
|
10786
11191
|
metadata: {
|
|
10787
11192
|
level: "warning",
|
|
10788
11193
|
obu: "Network Engineering",
|
|
@@ -10812,6 +11217,7 @@ var EnableSecretStrong = {
|
|
|
10812
11217
|
id: "NET-AAA-003",
|
|
10813
11218
|
selector: "enable",
|
|
10814
11219
|
vendor: "cisco-ios",
|
|
11220
|
+
category: "Authentication",
|
|
10815
11221
|
metadata: {
|
|
10816
11222
|
level: "error",
|
|
10817
11223
|
obu: "Security",
|
|
@@ -10848,6 +11254,7 @@ var CiscoNoPlaintextPasswords = {
|
|
|
10848
11254
|
id: "NET-SEC-001",
|
|
10849
11255
|
selector: "password",
|
|
10850
11256
|
vendor: ["cisco-ios", "cisco-nxos"],
|
|
11257
|
+
category: "Authentication",
|
|
10851
11258
|
metadata: {
|
|
10852
11259
|
level: "error",
|
|
10853
11260
|
obu: "Security",
|
|
@@ -10935,6 +11342,7 @@ var RootAuthRequired = {
|
|
|
10935
11342
|
id: "JUN-SYS-001",
|
|
10936
11343
|
selector: "system",
|
|
10937
11344
|
vendor: "juniper-junos",
|
|
11345
|
+
category: "Authentication",
|
|
10938
11346
|
metadata: {
|
|
10939
11347
|
level: "error",
|
|
10940
11348
|
obu: "Security",
|
|
@@ -10979,6 +11387,7 @@ var JunosBgpRouterId = {
|
|
|
10979
11387
|
id: "JUN-BGP-001",
|
|
10980
11388
|
selector: "routing-options",
|
|
10981
11389
|
vendor: "juniper-junos",
|
|
11390
|
+
category: "Routing",
|
|
10982
11391
|
metadata: {
|
|
10983
11392
|
level: "warning",
|
|
10984
11393
|
obu: "Network Engineering",
|
|
@@ -11011,6 +11420,7 @@ var JunosFirewallDefaultDeny = {
|
|
|
11011
11420
|
id: "JUN-FW-001",
|
|
11012
11421
|
selector: "firewall",
|
|
11013
11422
|
vendor: "juniper-junos",
|
|
11423
|
+
category: "Network-Segmentation",
|
|
11014
11424
|
metadata: {
|
|
11015
11425
|
level: "warning",
|
|
11016
11426
|
obu: "Security",
|
|
@@ -11082,6 +11492,7 @@ var SshEnabled = {
|
|
|
11082
11492
|
id: "ARU-SEC-001",
|
|
11083
11493
|
selector: "ssh",
|
|
11084
11494
|
vendor: ["aruba-aoscx", "aruba-aosswitch", "aruba-wlc"],
|
|
11495
|
+
category: "Session-Management",
|
|
11085
11496
|
metadata: {
|
|
11086
11497
|
level: "error",
|
|
11087
11498
|
obu: "Security",
|
|
@@ -11114,6 +11525,7 @@ var NtpConfigured = {
|
|
|
11114
11525
|
id: "ARU-NTP-001",
|
|
11115
11526
|
selector: "ntp",
|
|
11116
11527
|
vendor: ["aruba-aoscx", "aruba-aosswitch", "aruba-wlc"],
|
|
11528
|
+
category: "Time-Synchronization",
|
|
11117
11529
|
metadata: {
|
|
11118
11530
|
level: "warning",
|
|
11119
11531
|
obu: "Network Engineering",
|
|
@@ -11154,6 +11566,7 @@ var AosCxInterfaceDescription = {
|
|
|
11154
11566
|
id: "AOSCX-IF-001",
|
|
11155
11567
|
selector: "interface",
|
|
11156
11568
|
vendor: "aruba-aoscx",
|
|
11569
|
+
category: "Documentation",
|
|
11157
11570
|
metadata: {
|
|
11158
11571
|
level: "warning",
|
|
11159
11572
|
obu: "Network Engineering",
|
|
@@ -11195,6 +11608,7 @@ var AosCxTrunkAllowedVlans = {
|
|
|
11195
11608
|
id: "AOSCX-L2-001",
|
|
11196
11609
|
selector: "interface",
|
|
11197
11610
|
vendor: "aruba-aoscx",
|
|
11611
|
+
category: "Network-Segmentation",
|
|
11198
11612
|
metadata: {
|
|
11199
11613
|
level: "warning",
|
|
11200
11614
|
obu: "Network Engineering",
|
|
@@ -11245,6 +11659,7 @@ var AosSwitchVlanName = {
|
|
|
11245
11659
|
id: "AOSSW-L2-001",
|
|
11246
11660
|
selector: "vlan",
|
|
11247
11661
|
vendor: "aruba-aosswitch",
|
|
11662
|
+
category: "Documentation",
|
|
11248
11663
|
metadata: {
|
|
11249
11664
|
level: "warning",
|
|
11250
11665
|
obu: "Network Engineering",
|
|
@@ -11286,6 +11701,7 @@ var AosSwitchManagerPassword = {
|
|
|
11286
11701
|
id: "AOSSW-SEC-001",
|
|
11287
11702
|
selector: "password",
|
|
11288
11703
|
vendor: "aruba-aosswitch",
|
|
11704
|
+
category: "Authentication",
|
|
11289
11705
|
metadata: {
|
|
11290
11706
|
level: "error",
|
|
11291
11707
|
obu: "Security",
|
|
@@ -11326,6 +11742,7 @@ var WlcSsidEncryption = {
|
|
|
11326
11742
|
id: "ARUWLC-WLAN-001",
|
|
11327
11743
|
selector: "wlan ssid-profile",
|
|
11328
11744
|
vendor: "aruba-wlc",
|
|
11745
|
+
category: "Wireless",
|
|
11329
11746
|
metadata: {
|
|
11330
11747
|
level: "error",
|
|
11331
11748
|
obu: "Security",
|
|
@@ -11379,6 +11796,7 @@ var WlcRadiusHost = {
|
|
|
11379
11796
|
id: "ARUWLC-AAA-001",
|
|
11380
11797
|
selector: "aaa authentication-server radius",
|
|
11381
11798
|
vendor: "aruba-wlc",
|
|
11799
|
+
category: "Authentication",
|
|
11382
11800
|
metadata: {
|
|
11383
11801
|
level: "error",
|
|
11384
11802
|
obu: "Security",
|
|
@@ -11440,6 +11858,7 @@ var HostnameRequired = {
|
|
|
11440
11858
|
id: "PAN-SYS-001",
|
|
11441
11859
|
selector: "deviceconfig",
|
|
11442
11860
|
vendor: "paloalto-panos",
|
|
11861
|
+
category: "Documentation",
|
|
11443
11862
|
metadata: {
|
|
11444
11863
|
level: "warning",
|
|
11445
11864
|
obu: "Network Engineering",
|
|
@@ -11483,6 +11902,7 @@ var SecurityRuleLogging = {
|
|
|
11483
11902
|
id: "PAN-SEC-001",
|
|
11484
11903
|
selector: "rulebase",
|
|
11485
11904
|
vendor: "paloalto-panos",
|
|
11905
|
+
category: "Logging",
|
|
11486
11906
|
metadata: {
|
|
11487
11907
|
level: "warning",
|
|
11488
11908
|
obu: "Security",
|
|
@@ -11533,6 +11953,7 @@ var ZoneProtectionRequired = {
|
|
|
11533
11953
|
id: "PAN-ZONE-001",
|
|
11534
11954
|
selector: "zone",
|
|
11535
11955
|
vendor: "paloalto-panos",
|
|
11956
|
+
category: "Network-Segmentation",
|
|
11536
11957
|
metadata: {
|
|
11537
11958
|
level: "error",
|
|
11538
11959
|
obu: "Security",
|
|
@@ -11595,6 +12016,7 @@ var HostnameRequired2 = {
|
|
|
11595
12016
|
id: "ARI-SYS-001",
|
|
11596
12017
|
selector: "hostname",
|
|
11597
12018
|
vendor: "arista-eos",
|
|
12019
|
+
category: "Documentation",
|
|
11598
12020
|
metadata: {
|
|
11599
12021
|
level: "warning",
|
|
11600
12022
|
obu: "Network Engineering",
|
|
@@ -11629,6 +12051,7 @@ var MlagConfigComplete = {
|
|
|
11629
12051
|
id: "ARI-MLAG-001",
|
|
11630
12052
|
selector: "mlag configuration",
|
|
11631
12053
|
vendor: "arista-eos",
|
|
12054
|
+
category: "High-Availability",
|
|
11632
12055
|
metadata: {
|
|
11633
12056
|
level: "error",
|
|
11634
12057
|
obu: "Network Engineering",
|
|
@@ -11674,6 +12097,7 @@ var InterfaceDescription = {
|
|
|
11674
12097
|
id: "ARI-INT-001",
|
|
11675
12098
|
selector: "interface Ethernet",
|
|
11676
12099
|
vendor: "arista-eos",
|
|
12100
|
+
category: "Documentation",
|
|
11677
12101
|
metadata: {
|
|
11678
12102
|
level: "info",
|
|
11679
12103
|
obu: "Network Engineering",
|
|
@@ -11731,6 +12155,7 @@ var VyosHostnameRequired = {
|
|
|
11731
12155
|
id: "VYOS-SYS-001",
|
|
11732
12156
|
selector: "system",
|
|
11733
12157
|
vendor: "vyos",
|
|
12158
|
+
category: "Documentation",
|
|
11734
12159
|
metadata: {
|
|
11735
12160
|
level: "warning",
|
|
11736
12161
|
obu: "Network Engineering",
|
|
@@ -11763,6 +12188,7 @@ var VyosNoPlaintextPassword = {
|
|
|
11763
12188
|
id: "VYOS-SEC-001",
|
|
11764
12189
|
selector: "authentication",
|
|
11765
12190
|
vendor: "vyos",
|
|
12191
|
+
category: "Authentication",
|
|
11766
12192
|
metadata: {
|
|
11767
12193
|
level: "error",
|
|
11768
12194
|
obu: "Security",
|
|
@@ -11797,6 +12223,7 @@ var VyosInterfaceDescription = {
|
|
|
11797
12223
|
id: "VYOS-IF-001",
|
|
11798
12224
|
selector: "interfaces",
|
|
11799
12225
|
vendor: "vyos",
|
|
12226
|
+
category: "Documentation",
|
|
11800
12227
|
metadata: {
|
|
11801
12228
|
level: "warning",
|
|
11802
12229
|
obu: "Network Engineering",
|
|
@@ -11840,6 +12267,7 @@ var VyosFirewallDefaultAction = {
|
|
|
11840
12267
|
id: "VYOS-FW-001",
|
|
11841
12268
|
selector: "firewall",
|
|
11842
12269
|
vendor: "vyos",
|
|
12270
|
+
category: "Network-Segmentation",
|
|
11843
12271
|
metadata: {
|
|
11844
12272
|
level: "warning",
|
|
11845
12273
|
obu: "Security",
|
|
@@ -11907,6 +12335,7 @@ var HostnameRequired3 = {
|
|
|
11907
12335
|
id: "FGT-SYS-001",
|
|
11908
12336
|
selector: "config system global",
|
|
11909
12337
|
vendor: "fortinet-fortigate",
|
|
12338
|
+
category: "Documentation",
|
|
11910
12339
|
metadata: {
|
|
11911
12340
|
level: "warning",
|
|
11912
12341
|
obu: "Network Engineering",
|
|
@@ -11939,6 +12368,7 @@ var AdminTrustedHostRequired = {
|
|
|
11939
12368
|
id: "FGT-ADMIN-001",
|
|
11940
12369
|
selector: "config system admin",
|
|
11941
12370
|
vendor: "fortinet-fortigate",
|
|
12371
|
+
category: "Authentication",
|
|
11942
12372
|
metadata: {
|
|
11943
12373
|
level: "error",
|
|
11944
12374
|
obu: "Security",
|
|
@@ -11993,6 +12423,7 @@ var PolicyLoggingRequired = {
|
|
|
11993
12423
|
id: "FGT-POL-001",
|
|
11994
12424
|
selector: "config firewall policy",
|
|
11995
12425
|
vendor: "fortinet-fortigate",
|
|
12426
|
+
category: "Logging",
|
|
11996
12427
|
metadata: {
|
|
11997
12428
|
level: "warning",
|
|
11998
12429
|
obu: "Security",
|
|
@@ -12059,6 +12490,7 @@ var ExosSysnameRequired = {
|
|
|
12059
12490
|
id: "EXOS-SYS-001",
|
|
12060
12491
|
selector: "configure snmp sysname",
|
|
12061
12492
|
vendor: "extreme-exos",
|
|
12493
|
+
category: "Documentation",
|
|
12062
12494
|
metadata: {
|
|
12063
12495
|
level: "warning",
|
|
12064
12496
|
obu: "Network Engineering",
|
|
@@ -12092,6 +12524,7 @@ var ExosSsh2Enabled = {
|
|
|
12092
12524
|
id: "EXOS-SEC-001",
|
|
12093
12525
|
selector: "enable ssh2",
|
|
12094
12526
|
vendor: "extreme-exos",
|
|
12527
|
+
category: "Session-Management",
|
|
12095
12528
|
metadata: {
|
|
12096
12529
|
level: "warning",
|
|
12097
12530
|
obu: "Security",
|
|
@@ -12123,6 +12556,7 @@ var ExosVlanNaming = {
|
|
|
12123
12556
|
id: "EXOS-VLAN-001",
|
|
12124
12557
|
selector: "create vlan",
|
|
12125
12558
|
vendor: "extreme-exos",
|
|
12559
|
+
category: "Documentation",
|
|
12126
12560
|
metadata: {
|
|
12127
12561
|
level: "info",
|
|
12128
12562
|
obu: "Network Engineering",
|
|
@@ -12179,6 +12613,7 @@ var VossSysNameRequired = {
|
|
|
12179
12613
|
id: "VOSS-SYS-001",
|
|
12180
12614
|
selector: "snmp-server name",
|
|
12181
12615
|
vendor: "extreme-voss",
|
|
12616
|
+
category: "Documentation",
|
|
12182
12617
|
metadata: {
|
|
12183
12618
|
level: "warning",
|
|
12184
12619
|
obu: "Network Engineering",
|
|
@@ -12212,6 +12647,7 @@ var VossVlanIsidRequired = {
|
|
|
12212
12647
|
id: "VOSS-VLAN-001",
|
|
12213
12648
|
selector: "vlan create",
|
|
12214
12649
|
vendor: "extreme-voss",
|
|
12650
|
+
category: "Network-Segmentation",
|
|
12215
12651
|
metadata: {
|
|
12216
12652
|
level: "info",
|
|
12217
12653
|
obu: "Network Engineering",
|
|
@@ -12264,6 +12700,7 @@ var VossInterfaceDefaultVlan = {
|
|
|
12264
12700
|
id: "VOSS-INT-001",
|
|
12265
12701
|
selector: "interface GigabitEthernet",
|
|
12266
12702
|
vendor: "extreme-voss",
|
|
12703
|
+
category: "Network-Segmentation",
|
|
12267
12704
|
metadata: {
|
|
12268
12705
|
level: "info",
|
|
12269
12706
|
obu: "Network Engineering",
|
|
@@ -12348,6 +12785,7 @@ var SysnameRequired = {
|
|
|
12348
12785
|
id: "HUAWEI-SYS-001",
|
|
12349
12786
|
selector: "sysname",
|
|
12350
12787
|
vendor: "huawei-vrp",
|
|
12788
|
+
category: "Documentation",
|
|
12351
12789
|
metadata: {
|
|
12352
12790
|
level: "warning",
|
|
12353
12791
|
obu: "Network Engineering",
|
|
@@ -12380,6 +12818,7 @@ var InterfaceDescriptionRequired2 = {
|
|
|
12380
12818
|
id: "HUAWEI-IF-001",
|
|
12381
12819
|
selector: "interface",
|
|
12382
12820
|
vendor: "huawei-vrp",
|
|
12821
|
+
category: "Documentation",
|
|
12383
12822
|
metadata: {
|
|
12384
12823
|
level: "warning",
|
|
12385
12824
|
obu: "Network Engineering",
|
|
@@ -12432,6 +12871,7 @@ var VtySshRequired = {
|
|
|
12432
12871
|
id: "HUAWEI-VTY-002",
|
|
12433
12872
|
selector: "user-interface vty",
|
|
12434
12873
|
vendor: "huawei-vrp",
|
|
12874
|
+
category: "Session-Management",
|
|
12435
12875
|
metadata: {
|
|
12436
12876
|
level: "error",
|
|
12437
12877
|
obu: "Security",
|
|
@@ -12496,6 +12936,7 @@ var MikrotikSystemIdentity = {
|
|
|
12496
12936
|
id: "MIK-SYS-001",
|
|
12497
12937
|
selector: "/system identity",
|
|
12498
12938
|
vendor: "mikrotik-routeros",
|
|
12939
|
+
category: "Documentation",
|
|
12499
12940
|
metadata: {
|
|
12500
12941
|
level: "warning",
|
|
12501
12942
|
obu: "Network Engineering",
|
|
@@ -12528,6 +12969,7 @@ var MikrotikDisableUnusedServices = {
|
|
|
12528
12969
|
id: "MIK-SEC-001",
|
|
12529
12970
|
selector: "/ip service",
|
|
12530
12971
|
vendor: "mikrotik-routeros",
|
|
12972
|
+
category: "Service-Hardening",
|
|
12531
12973
|
metadata: {
|
|
12532
12974
|
level: "warning",
|
|
12533
12975
|
obu: "Security",
|
|
@@ -12572,6 +13014,7 @@ var MikrotikInputChainDrop = {
|
|
|
12572
13014
|
id: "MIK-FW-001",
|
|
12573
13015
|
selector: "/ip firewall filter",
|
|
12574
13016
|
vendor: "mikrotik-routeros",
|
|
13017
|
+
category: "Network-Segmentation",
|
|
12575
13018
|
metadata: {
|
|
12576
13019
|
level: "error",
|
|
12577
13020
|
obu: "Security",
|
|
@@ -12625,6 +13068,7 @@ var SystemNameRequired = {
|
|
|
12625
13068
|
id: "NOKIA-SYS-001",
|
|
12626
13069
|
selector: "system",
|
|
12627
13070
|
vendor: "nokia-sros",
|
|
13071
|
+
category: "Documentation",
|
|
12628
13072
|
metadata: {
|
|
12629
13073
|
level: "warning",
|
|
12630
13074
|
obu: "Network Engineering",
|
|
@@ -12657,6 +13101,7 @@ var PortDescriptionRequired = {
|
|
|
12657
13101
|
id: "NOKIA-PORT-001",
|
|
12658
13102
|
selector: "port",
|
|
12659
13103
|
vendor: "nokia-sros",
|
|
13104
|
+
category: "Documentation",
|
|
12660
13105
|
metadata: {
|
|
12661
13106
|
level: "warning",
|
|
12662
13107
|
obu: "Network Engineering",
|
|
@@ -12709,6 +13154,7 @@ var BgpRouterIdRequired = {
|
|
|
12709
13154
|
id: "NOKIA-BGP-001",
|
|
12710
13155
|
selector: "bgp",
|
|
12711
13156
|
vendor: "nokia-sros",
|
|
13157
|
+
category: "Routing",
|
|
12712
13158
|
metadata: {
|
|
12713
13159
|
level: "warning",
|
|
12714
13160
|
obu: "Network Engineering",
|
|
@@ -12765,6 +13211,7 @@ var CumulusInterfaceDescription = {
|
|
|
12765
13211
|
id: "CUM-IF-001",
|
|
12766
13212
|
selector: "iface",
|
|
12767
13213
|
vendor: "cumulus-linux",
|
|
13214
|
+
category: "Documentation",
|
|
12768
13215
|
metadata: {
|
|
12769
13216
|
level: "warning",
|
|
12770
13217
|
obu: "Network Engineering",
|
|
@@ -12807,6 +13254,7 @@ var CumulusBridgeVlans = {
|
|
|
12807
13254
|
id: "CUM-BR-001",
|
|
12808
13255
|
selector: "iface",
|
|
12809
13256
|
vendor: "cumulus-linux",
|
|
13257
|
+
category: "Network-Segmentation",
|
|
12810
13258
|
metadata: {
|
|
12811
13259
|
level: "warning",
|
|
12812
13260
|
obu: "Network Engineering",
|
|
@@ -12859,6 +13307,7 @@ var CumulusBgpRouterId = {
|
|
|
12859
13307
|
id: "CUM-BGP-001",
|
|
12860
13308
|
selector: "router bgp",
|
|
12861
13309
|
vendor: "cumulus-linux",
|
|
13310
|
+
category: "Routing",
|
|
12862
13311
|
metadata: {
|
|
12863
13312
|
level: "warning",
|
|
12864
13313
|
obu: "Network Engineering",
|
|
@@ -12915,6 +13364,7 @@ var cisco_json_rules_default = {
|
|
|
12915
13364
|
id: "JSON-CISCO-001",
|
|
12916
13365
|
selector: "interface",
|
|
12917
13366
|
vendor: "cisco-ios",
|
|
13367
|
+
category: "Network-Segmentation",
|
|
12918
13368
|
metadata: {
|
|
12919
13369
|
level: "warning",
|
|
12920
13370
|
obu: "Network Engineering",
|
|
@@ -12953,6 +13403,7 @@ var cisco_json_rules_default = {
|
|
|
12953
13403
|
id: "JSON-CISCO-002",
|
|
12954
13404
|
selector: "interface",
|
|
12955
13405
|
vendor: "cisco-ios",
|
|
13406
|
+
category: "Network-Segmentation",
|
|
12956
13407
|
metadata: {
|
|
12957
13408
|
level: "info",
|
|
12958
13409
|
obu: "Network Engineering",
|
|
@@ -12991,6 +13442,7 @@ var cisco_json_rules_default = {
|
|
|
12991
13442
|
id: "JSON-CISCO-003",
|
|
12992
13443
|
selector: "interface",
|
|
12993
13444
|
vendor: "cisco-ios",
|
|
13445
|
+
category: "Documentation",
|
|
12994
13446
|
metadata: {
|
|
12995
13447
|
level: "warning",
|
|
12996
13448
|
obu: "Network Engineering",
|
|
@@ -13024,6 +13476,7 @@ var cisco_json_rules_default = {
|
|
|
13024
13476
|
id: "JSON-CISCO-004",
|
|
13025
13477
|
selector: "interface",
|
|
13026
13478
|
vendor: "cisco-ios",
|
|
13479
|
+
category: "Protocol-Security",
|
|
13027
13480
|
metadata: {
|
|
13028
13481
|
level: "error",
|
|
13029
13482
|
obu: "Security",
|
|
@@ -13066,6 +13519,7 @@ var cisco_json_rules_default = {
|
|
|
13066
13519
|
id: "JSON-CISCO-005",
|
|
13067
13520
|
selector: "line vty",
|
|
13068
13521
|
vendor: "cisco-ios",
|
|
13522
|
+
category: "Session-Management",
|
|
13069
13523
|
metadata: {
|
|
13070
13524
|
level: "error",
|
|
13071
13525
|
obu: "Security",
|
|
@@ -13101,6 +13555,7 @@ var common_json_rules_default = {
|
|
|
13101
13555
|
id: "JSON-COMMON-001",
|
|
13102
13556
|
selector: "interface",
|
|
13103
13557
|
vendor: "common",
|
|
13558
|
+
category: "Documentation",
|
|
13104
13559
|
metadata: {
|
|
13105
13560
|
level: "info",
|
|
13106
13561
|
obu: "Network Engineering",
|
|
@@ -13148,6 +13603,7 @@ var juniper_json_rules_default = {
|
|
|
13148
13603
|
id: "JSON-JUNOS-001",
|
|
13149
13604
|
selector: "system services",
|
|
13150
13605
|
vendor: "juniper-junos",
|
|
13606
|
+
category: "Session-Management",
|
|
13151
13607
|
metadata: {
|
|
13152
13608
|
level: "error",
|
|
13153
13609
|
obu: "Security",
|
|
@@ -13180,6 +13636,7 @@ var juniper_json_rules_default = {
|
|
|
13180
13636
|
id: "JSON-JUNOS-002",
|
|
13181
13637
|
selector: "system services",
|
|
13182
13638
|
vendor: "juniper-junos",
|
|
13639
|
+
category: "Service-Hardening",
|
|
13183
13640
|
metadata: {
|
|
13184
13641
|
level: "error",
|
|
13185
13642
|
obu: "Security",
|
|
@@ -13202,6 +13659,7 @@ var juniper_json_rules_default = {
|
|
|
13202
13659
|
id: "JSON-JUNOS-003",
|
|
13203
13660
|
selector: "system",
|
|
13204
13661
|
vendor: "juniper-junos",
|
|
13662
|
+
category: "Session-Management",
|
|
13205
13663
|
metadata: {
|
|
13206
13664
|
level: "warning",
|
|
13207
13665
|
obu: "Security",
|
|
@@ -13221,6 +13679,7 @@ var juniper_json_rules_default = {
|
|
|
13221
13679
|
id: "JSON-JUNOS-004",
|
|
13222
13680
|
selector: "protocols ospf area",
|
|
13223
13681
|
vendor: "juniper-junos",
|
|
13682
|
+
category: "Routing",
|
|
13224
13683
|
metadata: {
|
|
13225
13684
|
level: "warning",
|
|
13226
13685
|
obu: "Network Engineering",
|
|
@@ -13240,6 +13699,7 @@ var juniper_json_rules_default = {
|
|
|
13240
13699
|
id: "JSON-JUNOS-005",
|
|
13241
13700
|
selector: "system syslog",
|
|
13242
13701
|
vendor: "juniper-junos",
|
|
13702
|
+
category: "Logging",
|
|
13243
13703
|
metadata: {
|
|
13244
13704
|
level: "warning",
|
|
13245
13705
|
obu: "Operations",
|
|
@@ -14397,7 +14857,7 @@ function isStdinRequested(files) {
|
|
|
14397
14857
|
|
|
14398
14858
|
// index.ts
|
|
14399
14859
|
var program = new Command();
|
|
14400
|
-
program.name("sentriflow").description("SentriFlow Network Configuration Validator").version("0.1.
|
|
14860
|
+
program.name("sentriflow").description("SentriFlow Network Configuration Validator").version("0.1.8").argument("[files...]", "Path(s) to configuration file(s) (supports multiple files)").option("--ast", "Output the AST instead of rule results").option("-f, --format <format>", "Output format (json, sarif)", "json").option("-q, --quiet", "Only output failures (suppress passed results)").option("-c, --config <path>", "Path to config file (default: auto-detect)").option("--no-config", "Ignore config file").option("-r, --rules <path>", "Additional rules file to load (legacy)").option("-p, --rule-pack <path>", "Rule pack file to load").option(
|
|
14401
14861
|
"--encrypted-pack <path...>",
|
|
14402
14862
|
"SEC-012: Path(s) to encrypted rule pack(s) (.grpx), can specify multiple"
|
|
14403
14863
|
).option(
|
|
@@ -14690,10 +15150,12 @@ Parsing complete: ${allAsts.length} files`);
|
|
|
14690
15150
|
const passed = results2.filter((r) => r.passed).length;
|
|
14691
15151
|
totalFailures += failures;
|
|
14692
15152
|
totalPassed += passed;
|
|
15153
|
+
const fileIpSummary = extractIPSummary(content2);
|
|
14693
15154
|
allFileResults.push({
|
|
14694
15155
|
filePath: filePath2,
|
|
14695
15156
|
results: results2,
|
|
14696
|
-
vendor: { id: vendor2.id, name: vendor2.name }
|
|
15157
|
+
vendor: { id: vendor2.id, name: vendor2.name },
|
|
15158
|
+
ipSummary: fileIpSummary
|
|
14697
15159
|
});
|
|
14698
15160
|
} catch (err) {
|
|
14699
15161
|
const errMsg = err instanceof Error ? err.message : "Unknown error";
|
|
@@ -14725,7 +15187,8 @@ Parsing complete: ${allAsts.length} files`);
|
|
|
14725
15187
|
files: allFileResults.map((fr) => ({
|
|
14726
15188
|
file: fr.filePath,
|
|
14727
15189
|
vendor: fr.vendor,
|
|
14728
|
-
results: fr.results
|
|
15190
|
+
results: fr.results,
|
|
15191
|
+
ipSummary: fr.ipSummary
|
|
14729
15192
|
}))
|
|
14730
15193
|
};
|
|
14731
15194
|
console.log(JSON.stringify(output, null, 2));
|
|
@@ -14801,17 +15264,19 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
|
|
|
14801
15264
|
if (options.quiet) {
|
|
14802
15265
|
results2 = results2.filter((r) => !r.passed);
|
|
14803
15266
|
}
|
|
15267
|
+
const stdinIpSummary = extractIPSummary(content2);
|
|
14804
15268
|
if (options.format === "sarif") {
|
|
14805
15269
|
const sarifOptions = {
|
|
14806
15270
|
relativePaths: options.relativePaths,
|
|
14807
15271
|
baseDir: process.cwd()
|
|
14808
15272
|
};
|
|
14809
|
-
console.log(generateSarif(results2, "<stdin>", stdinRules, sarifOptions));
|
|
15273
|
+
console.log(generateSarif(results2, "<stdin>", stdinRules, sarifOptions, stdinIpSummary));
|
|
14810
15274
|
} else {
|
|
14811
15275
|
const output = {
|
|
14812
15276
|
file: "<stdin>",
|
|
14813
15277
|
vendor: { id: vendor2.id, name: vendor2.name },
|
|
14814
|
-
results: results2
|
|
15278
|
+
results: results2,
|
|
15279
|
+
ipSummary: stdinIpSummary
|
|
14815
15280
|
};
|
|
14816
15281
|
console.log(JSON.stringify(output, null, 2));
|
|
14817
15282
|
}
|
|
@@ -14870,10 +15335,12 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
|
|
|
14870
15335
|
const passed = results2.filter((r) => r.passed).length;
|
|
14871
15336
|
totalFailures += failures;
|
|
14872
15337
|
totalPassed += passed;
|
|
15338
|
+
const fileIpSummary = extractIPSummary(content2);
|
|
14873
15339
|
allFileResults.push({
|
|
14874
15340
|
filePath: filePath2,
|
|
14875
15341
|
results: results2,
|
|
14876
|
-
vendor: { id: vendor2.id, name: vendor2.name }
|
|
15342
|
+
vendor: { id: vendor2.id, name: vendor2.name },
|
|
15343
|
+
ipSummary: fileIpSummary
|
|
14877
15344
|
});
|
|
14878
15345
|
} catch (err) {
|
|
14879
15346
|
const errMsg = err instanceof Error ? err.message : "Unknown error";
|
|
@@ -14900,7 +15367,8 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
|
|
|
14900
15367
|
files: allFileResults.map((fr) => ({
|
|
14901
15368
|
file: fr.filePath,
|
|
14902
15369
|
vendor: fr.vendor,
|
|
14903
|
-
results: fr.results
|
|
15370
|
+
results: fr.results,
|
|
15371
|
+
ipSummary: fr.ipSummary
|
|
14904
15372
|
}))
|
|
14905
15373
|
};
|
|
14906
15374
|
console.log(JSON.stringify(output, null, 2));
|
|
@@ -14985,13 +15453,14 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
|
|
|
14985
15453
|
if (options.quiet) {
|
|
14986
15454
|
results = results.filter((r) => !r.passed);
|
|
14987
15455
|
}
|
|
15456
|
+
const ipSummary = extractIPSummary(content);
|
|
14988
15457
|
if (options.format === "sarif") {
|
|
14989
15458
|
const sarifOptions = {
|
|
14990
15459
|
relativePaths: options.relativePaths,
|
|
14991
15460
|
baseDir: process.cwd()
|
|
14992
15461
|
};
|
|
14993
15462
|
console.log(
|
|
14994
|
-
generateSarif(results, filePath, singleFileRules, sarifOptions)
|
|
15463
|
+
generateSarif(results, filePath, singleFileRules, sarifOptions, ipSummary)
|
|
14995
15464
|
);
|
|
14996
15465
|
} else {
|
|
14997
15466
|
const output = {
|
|
@@ -14999,7 +15468,8 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
|
|
|
14999
15468
|
id: vendor.id,
|
|
15000
15469
|
name: vendor.name
|
|
15001
15470
|
},
|
|
15002
|
-
results
|
|
15471
|
+
results,
|
|
15472
|
+
ipSummary
|
|
15003
15473
|
};
|
|
15004
15474
|
console.log(JSON.stringify(output, null, 2));
|
|
15005
15475
|
}
|