aws-security-mcp 0.5.2 → 0.5.3
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/README.md +1 -8
- package/dist/bin/aws-security-mcp.js +42 -209
- package/dist/bin/aws-security-mcp.js.map +1 -1
- package/dist/src/index.js +42 -209
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ MCP server for automated AWS security scanning — 19 modules, risk scoring, zer
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- **19 Security Scan Modules** —
|
|
12
|
+
- **19 Security Scan Modules** — Security Hub, GuardDuty, Inspector, Trusted Advisor, Config Rules, Access Analyzer, Patch Compliance, and more
|
|
13
13
|
- **Risk Scoring** — every finding scored 0-10 with severity (CRITICAL/HIGH/MEDIUM/LOW) and priority (P0-P3)
|
|
14
14
|
- **100% Read-Only** — uses only Describe/Get/List API calls; never modifies your AWS resources
|
|
15
15
|
- **Multi-Account Support** — scan all accounts in an AWS Organization via `org_mode` with cross-account role assumption
|
|
@@ -246,8 +246,6 @@ Attach this policy to the IAM user or role running the scanner. All actions are
|
|
|
246
246
|
|
|
247
247
|
## Scan Modules
|
|
248
248
|
|
|
249
|
-
### Unique Scanners (15)
|
|
250
|
-
|
|
251
249
|
| Module | What It Checks | Risk Score Range |
|
|
252
250
|
|--------|---------------|-----------------|
|
|
253
251
|
| **Service Detection** | Enabled security services (Security Hub, GuardDuty, Inspector, Config, Macie, CloudTrail) and maturity level | 5.0 - 7.5 |
|
|
@@ -265,11 +263,6 @@ Attach this policy to the IAM user or role running the scanner. All actions are
|
|
|
265
263
|
| **Patch Compliance** | SSM Patch Manager compliance status for managed instances | 3.0 - 9.5 |
|
|
266
264
|
| **IMDSv2 Enforcement** | EC2 instances not enforcing IMDSv2 (HttpTokens != required) | 7.5 |
|
|
267
265
|
| **WAF Coverage** | Internet-facing ALBs without WAF Web ACL protection | 7.5 |
|
|
268
|
-
|
|
269
|
-
### Aggregation Scanners (4)
|
|
270
|
-
|
|
271
|
-
| Module | Source Service | Risk Score Range |
|
|
272
|
-
|--------|---------------|-----------------|
|
|
273
266
|
| **Security Hub Findings** | AWS Security Hub (FSBP, CIS, PCI DSS) | 3.0 - 9.5 |
|
|
274
267
|
| **GuardDuty Findings** | Amazon GuardDuty threat detection | 3.0 - 9.5 |
|
|
275
268
|
| **Inspector Findings** | Amazon Inspector vulnerability scanning | 3.0 - 9.5 |
|
|
@@ -237,7 +237,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
237
237
|
import { z } from "zod";
|
|
238
238
|
|
|
239
239
|
// src/version.ts
|
|
240
|
-
var VERSION = "0.5.
|
|
240
|
+
var VERSION = "0.5.3";
|
|
241
241
|
|
|
242
242
|
// src/utils/aws-client.ts
|
|
243
243
|
import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
|
|
@@ -2439,7 +2439,6 @@ import {
|
|
|
2439
2439
|
DescribeNetworkInterfacesCommand,
|
|
2440
2440
|
DescribeSecurityGroupsCommand as DescribeSecurityGroupsCommand2
|
|
2441
2441
|
} from "@aws-sdk/client-ec2";
|
|
2442
|
-
var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
2443
2442
|
function makeFinding9(opts) {
|
|
2444
2443
|
const severity = severityFromScore(opts.riskScore);
|
|
2445
2444
|
return { ...opts, severity, priority: priorityFromSeverity(severity) };
|
|
@@ -6908,9 +6907,8 @@ var MLPS3_CHECK_MAPPING = [
|
|
|
6908
6907
|
},
|
|
6909
6908
|
{
|
|
6910
6909
|
id: "L3-SMC1-09",
|
|
6911
|
-
type: "
|
|
6912
|
-
|
|
6913
|
-
findingPatterns: ["CloudWatch"]
|
|
6910
|
+
type: "manual",
|
|
6911
|
+
guidance: "\u9700\u914D\u7F6E CloudWatch \u96C6\u4E2D\u76D1\u63A7\u5E73\u53F0\uFF0C\u7ED3\u5408 SNS \u8FDB\u884C\u544A\u8B66\u901A\u77E5"
|
|
6914
6912
|
},
|
|
6915
6913
|
{
|
|
6916
6914
|
id: "L3-SMC1-10",
|
|
@@ -7004,226 +7002,57 @@ function evaluateAllFullChecks(scanResults) {
|
|
|
7004
7002
|
return evaluateFullCheck(item, mapping, allFindings, scanModules);
|
|
7005
7003
|
});
|
|
7006
7004
|
}
|
|
7007
|
-
var MLPS_CHECKS = [
|
|
7008
|
-
// 一、身份鉴别
|
|
7009
|
-
{
|
|
7010
|
-
id: "8.1.4.1a",
|
|
7011
|
-
category: "\u8EAB\u4EFD\u9274\u522B",
|
|
7012
|
-
name: "\u5BC6\u7801\u7B56\u7565",
|
|
7013
|
-
modules: ["security_hub_findings"],
|
|
7014
|
-
findingPatterns: ["password policy", "password length", "complexity", "password expiry", "reuse prevention", "IAM.7", "IAM.10"]
|
|
7015
|
-
},
|
|
7016
|
-
{
|
|
7017
|
-
id: "8.1.4.1a",
|
|
7018
|
-
category: "\u8EAB\u4EFD\u9274\u522B",
|
|
7019
|
-
name: "\u5BC6\u94A5\u8F6E\u6362",
|
|
7020
|
-
modules: ["security_hub_findings"],
|
|
7021
|
-
findingPatterns: ["access key older", "access key rotated", "IAM.3", "IAM.4"]
|
|
7022
|
-
},
|
|
7023
|
-
{
|
|
7024
|
-
id: "8.1.4.1d",
|
|
7025
|
-
category: "\u8EAB\u4EFD\u9274\u522B",
|
|
7026
|
-
name: "\u53CC\u56E0\u7D20\u8BA4\u8BC1",
|
|
7027
|
-
modules: ["security_hub_findings"],
|
|
7028
|
-
findingPatterns: ["MFA", "IAM.5", "IAM.6"]
|
|
7029
|
-
},
|
|
7030
|
-
// 二、访问控制
|
|
7031
|
-
{
|
|
7032
|
-
id: "8.1.4.2c",
|
|
7033
|
-
category: "\u8BBF\u95EE\u63A7\u5236",
|
|
7034
|
-
name: "\u6700\u5C0F\u6743\u9650",
|
|
7035
|
-
modules: ["iam_privilege_escalation", "security_hub_findings"],
|
|
7036
|
-
findingPatterns: [
|
|
7037
|
-
"AdministratorAccess",
|
|
7038
|
-
"PowerUserAccess",
|
|
7039
|
-
"IAMFullAccess",
|
|
7040
|
-
"over-permissive",
|
|
7041
|
-
"privilege escalation",
|
|
7042
|
-
"self-grant",
|
|
7043
|
-
"iam:*",
|
|
7044
|
-
"create admin",
|
|
7045
|
-
"Lambda role passing",
|
|
7046
|
-
"CreateAccessKey",
|
|
7047
|
-
"AssumeRole"
|
|
7048
|
-
]
|
|
7049
|
-
},
|
|
7050
|
-
{
|
|
7051
|
-
id: "8.1.4.2",
|
|
7052
|
-
category: "\u8BBF\u95EE\u63A7\u5236",
|
|
7053
|
-
name: "\u5B89\u5168\u7EC4",
|
|
7054
|
-
modules: ["network_reachability", "security_hub_findings"],
|
|
7055
|
-
findingPatterns: ["allows all ports", "allows SSH", "allows RDP", "MySQL", "PostgreSQL", "MongoDB", "Redis", "high-risk port", "security group", "EC2.18", "EC2.19"]
|
|
7056
|
-
},
|
|
7057
|
-
// 三、安全审计
|
|
7058
|
-
{
|
|
7059
|
-
id: "8.1.4.3a",
|
|
7060
|
-
category: "\u5B89\u5168\u5BA1\u8BA1",
|
|
7061
|
-
name: "\u5BA1\u8BA1\u529F\u80FD",
|
|
7062
|
-
modules: ["security_hub_findings"],
|
|
7063
|
-
findingPatterns: ["CloudTrail", "not enabled", "multi-region", "not logging", "CloudTrail.1"]
|
|
7064
|
-
},
|
|
7065
|
-
{
|
|
7066
|
-
id: "8.1.4.3b",
|
|
7067
|
-
category: "\u5B89\u5168\u5BA1\u8BA1",
|
|
7068
|
-
name: "\u5BA1\u8BA1\u5B8C\u6574\u6027",
|
|
7069
|
-
modules: ["security_hub_findings"],
|
|
7070
|
-
findingPatterns: ["log file validation", "log integrity", "log validation", "CloudTrail.4", "CloudTrail.5"]
|
|
7071
|
-
},
|
|
7072
|
-
{
|
|
7073
|
-
id: "8.1.4.3c",
|
|
7074
|
-
category: "\u5B89\u5168\u5BA1\u8BA1",
|
|
7075
|
-
name: "\u5BA1\u8BA1\u4FDD\u62A4",
|
|
7076
|
-
modules: ["security_hub_findings"],
|
|
7077
|
-
findingPatterns: ["CloudTrail", "S3 bucket", "encryption", "versioning", "Block Public Access", "CloudTrail.6", "CloudTrail.7"]
|
|
7078
|
-
},
|
|
7079
|
-
// 四、入侵防范
|
|
7080
|
-
{
|
|
7081
|
-
id: "8.1.4.4a",
|
|
7082
|
-
category: "\u5165\u4FB5\u9632\u8303",
|
|
7083
|
-
name: "GuardDuty \u5A01\u80C1\u68C0\u6D4B",
|
|
7084
|
-
modules: ["service_detection", "guardduty_findings"],
|
|
7085
|
-
findingPatterns: ["GuardDuty"]
|
|
7086
|
-
},
|
|
7087
|
-
{
|
|
7088
|
-
id: "8.1.4.4a",
|
|
7089
|
-
category: "\u5165\u4FB5\u9632\u8303",
|
|
7090
|
-
name: "Inspector \u6F0F\u6D1E\u626B\u63CF",
|
|
7091
|
-
modules: ["service_detection", "inspector_findings"],
|
|
7092
|
-
findingPatterns: ["Inspector", "CVE-"]
|
|
7093
|
-
},
|
|
7094
|
-
// 五、数据安全
|
|
7095
|
-
{
|
|
7096
|
-
id: "8.1.4.5a",
|
|
7097
|
-
category: "\u6570\u636E\u5B89\u5168",
|
|
7098
|
-
name: "\u4F20\u8F93\u52A0\u5BC6",
|
|
7099
|
-
modules: ["ssl_certificate", "security_hub_findings"],
|
|
7100
|
-
findingPatterns: ["HTTPS", "TLS", "HTTP listener", "certificate", "ELB.1"]
|
|
7101
|
-
},
|
|
7102
|
-
{
|
|
7103
|
-
id: "8.1.4.5b",
|
|
7104
|
-
category: "\u6570\u636E\u5B89\u5168",
|
|
7105
|
-
name: "S3 \u5B58\u50A8\u52A0\u5BC6",
|
|
7106
|
-
modules: ["security_hub_findings"],
|
|
7107
|
-
findingPatterns: ["no default encryption", "not encrypted", "S3.4"]
|
|
7108
|
-
},
|
|
7109
|
-
{
|
|
7110
|
-
id: "8.1.4.5b",
|
|
7111
|
-
category: "\u6570\u636E\u5B89\u5168",
|
|
7112
|
-
name: "EBS \u9ED8\u8BA4\u52A0\u5BC6",
|
|
7113
|
-
modules: ["security_hub_findings"],
|
|
7114
|
-
findingPatterns: ["EBS default encryption", "EC2.7"]
|
|
7115
|
-
},
|
|
7116
|
-
{
|
|
7117
|
-
id: "8.1.4.5b",
|
|
7118
|
-
category: "\u6570\u636E\u5B89\u5168",
|
|
7119
|
-
name: "RDS \u5B58\u50A8\u52A0\u5BC6",
|
|
7120
|
-
modules: ["security_hub_findings"],
|
|
7121
|
-
findingPatterns: ["storage is not encrypted", "RDS.3"]
|
|
7122
|
-
},
|
|
7123
|
-
// 六、网络安全
|
|
7124
|
-
{
|
|
7125
|
-
id: "8.1.3.1a",
|
|
7126
|
-
category: "\u7F51\u7EDC\u5B89\u5168",
|
|
7127
|
-
name: "\u7F51\u7EDC\u67B6\u6784",
|
|
7128
|
-
modules: ["security_hub_findings"],
|
|
7129
|
-
findingPatterns: ["default VPC", "EC2.2"]
|
|
7130
|
-
},
|
|
7131
|
-
{
|
|
7132
|
-
id: "8.1.3.2a",
|
|
7133
|
-
category: "\u7F51\u7EDC\u5B89\u5168",
|
|
7134
|
-
name: "\u8FB9\u754C\u9632\u62A4",
|
|
7135
|
-
modules: ["network_reachability", "security_hub_findings"],
|
|
7136
|
-
findingPatterns: ["allows all ports", "allows SSH", "allows RDP", "security group", "EC2.18", "EC2.19"]
|
|
7137
|
-
}
|
|
7138
|
-
];
|
|
7139
|
-
var CATEGORY_ORDER = [
|
|
7140
|
-
"\u8EAB\u4EFD\u9274\u522B",
|
|
7141
|
-
"\u8BBF\u95EE\u63A7\u5236",
|
|
7142
|
-
"\u5B89\u5168\u5BA1\u8BA1",
|
|
7143
|
-
"\u5165\u4FB5\u9632\u8303",
|
|
7144
|
-
"\u6570\u636E\u5B89\u5168",
|
|
7145
|
-
"\u7F51\u7EDC\u5B89\u5168"
|
|
7146
|
-
];
|
|
7147
|
-
var CATEGORY_SECTION = {
|
|
7148
|
-
"\u8EAB\u4EFD\u9274\u522B": "\u4E00\u3001\u8EAB\u4EFD\u9274\u522B",
|
|
7149
|
-
"\u8BBF\u95EE\u63A7\u5236": "\u4E8C\u3001\u8BBF\u95EE\u63A7\u5236",
|
|
7150
|
-
"\u5B89\u5168\u5BA1\u8BA1": "\u4E09\u3001\u5B89\u5168\u5BA1\u8BA1",
|
|
7151
|
-
"\u5165\u4FB5\u9632\u8303": "\u56DB\u3001\u5165\u4FB5\u9632\u8303",
|
|
7152
|
-
"\u6570\u636E\u5B89\u5168": "\u4E94\u3001\u6570\u636E\u5B89\u5168",
|
|
7153
|
-
"\u7F51\u7EDC\u5B89\u5168": "\u516D\u3001\u7F51\u7EDC\u5B89\u5168"
|
|
7154
|
-
};
|
|
7155
|
-
function evaluateCheck(check, allFindings, scanModules) {
|
|
7156
|
-
const allModulesPresent = check.modules.every(
|
|
7157
|
-
(mod) => scanModules.some((m) => m.module === mod && m.status === "success")
|
|
7158
|
-
);
|
|
7159
|
-
if (!allModulesPresent) {
|
|
7160
|
-
return { check, status: "unknown", relatedFindings: [] };
|
|
7161
|
-
}
|
|
7162
|
-
const relatedFindings = allFindings.filter((f) => {
|
|
7163
|
-
const moduleMatch = check.modules.some((mod) => f.module === mod);
|
|
7164
|
-
if (!moduleMatch) return false;
|
|
7165
|
-
const text = `${f.title} ${f.description}`.toLowerCase();
|
|
7166
|
-
return check.findingPatterns.some(
|
|
7167
|
-
(pattern) => text.includes(pattern.toLowerCase())
|
|
7168
|
-
);
|
|
7169
|
-
});
|
|
7170
|
-
return {
|
|
7171
|
-
check,
|
|
7172
|
-
status: relatedFindings.length === 0 ? "clean" : "issues",
|
|
7173
|
-
relatedFindings
|
|
7174
|
-
};
|
|
7175
|
-
}
|
|
7176
7005
|
function generateMlps3Report(scanResults) {
|
|
7177
7006
|
const { accountId, region, scanStart } = scanResults;
|
|
7178
7007
|
const scanTime = scanStart.replace("T", " ").replace(/\.\d+Z$/, " UTC");
|
|
7179
|
-
const
|
|
7180
|
-
|
|
7181
|
-
);
|
|
7182
|
-
const
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
const
|
|
7187
|
-
|
|
7188
|
-
);
|
|
7189
|
-
const cleanCount = results.filter((r) => r.status === "clean").length;
|
|
7190
|
-
const issuesCount = results.filter((r) => r.status === "issues").length;
|
|
7191
|
-
const unknownCount = results.filter((r) => r.status === "unknown").length;
|
|
7192
|
-
const checkedTotal = cleanCount + issuesCount;
|
|
7193
|
-
const total = results.length;
|
|
7008
|
+
const results = evaluateAllFullChecks(scanResults);
|
|
7009
|
+
const autoResults = results.filter((r) => r.mapping.type === "auto");
|
|
7010
|
+
const autoClean = autoResults.filter((r) => r.status === "clean").length;
|
|
7011
|
+
const autoIssues = autoResults.filter((r) => r.status === "issues").length;
|
|
7012
|
+
const autoUnknown = autoResults.filter((r) => r.status === "unknown").length;
|
|
7013
|
+
const checkedTotal = autoClean + autoIssues;
|
|
7014
|
+
const cloudCount = results.filter((r) => r.status === "cloud_provider").length;
|
|
7015
|
+
const manualCount = results.filter((r) => r.status === "manual").length;
|
|
7016
|
+
const naCount = results.filter((r) => r.status === "not_applicable").length;
|
|
7194
7017
|
const lines = [];
|
|
7195
7018
|
lines.push("# \u7B49\u4FDD\u4E09\u7EA7\u9884\u68C0\u62A5\u544A");
|
|
7196
7019
|
lines.push("> **\u672C\u62A5\u544A\u4E3A\u7B49\u4FDD\u4E09\u7EA7\u9884\u68C0\u53C2\u8003\uFF0C\u63D0\u4F9B\u4E91\u5E73\u53F0\u914D\u7F6E\u68C0\u67E5\u6570\u636E\u4E0E\u5EFA\u8BAE\u3002\u5408\u89C4\u5224\u5B9A\uFF08\u7B26\u5408/\u90E8\u5206\u7B26\u5408/\u4E0D\u7B26\u5408\uFF09\u9700\u7531\u6301\u8BC1\u6D4B\u8BC4\u673A\u6784\u6839\u636E\u5B9E\u9645\u60C5\u51B5\u786E\u8BA4\u3002**");
|
|
7020
|
+
lines.push("> **\uFF08GB/T 22239-2019 \u5B8C\u6574\u68C0\u67E5\u6E05\u5355 184 \u9879\uFF09**");
|
|
7197
7021
|
lines.push("");
|
|
7198
7022
|
lines.push("## \u8D26\u6237\u4FE1\u606F");
|
|
7199
7023
|
lines.push(`- Account: ${accountId} | Region: ${region} | \u626B\u63CF\u65F6\u95F4: ${scanTime}`);
|
|
7200
7024
|
lines.push("");
|
|
7201
7025
|
lines.push("## \u9884\u68C0\u603B\u89C8");
|
|
7202
|
-
lines.push(`- \u5DF2\u68C0\u67E5 ${checkedTotal} \u9879
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7026
|
+
lines.push(`- \u5DF2\u68C0\u67E5: ${checkedTotal} \u9879\uFF08\u672A\u53D1\u73B0\u95EE\u9898: ${autoClean} \u9879 | \u53D1\u73B0\u95EE\u9898: ${autoIssues} \u9879\uFF09`);
|
|
7027
|
+
if (autoUnknown > 0) {
|
|
7028
|
+
lines.push(`- \u672A\u68C0\u67E5: ${autoUnknown} \u9879\uFF08\u5BF9\u5E94\u626B\u63CF\u6A21\u5757\u672A\u8FD0\u884C\uFF09`);
|
|
7029
|
+
}
|
|
7030
|
+
lines.push(`- \u4E91\u5E73\u53F0\u8D1F\u8D23: ${cloudCount} \u9879`);
|
|
7031
|
+
lines.push(`- \u9700\u4EBA\u5DE5\u8BC4\u4F30: ${manualCount} \u9879`);
|
|
7032
|
+
if (naCount > 0) {
|
|
7033
|
+
lines.push(`- \u4E0D\u9002\u7528: ${naCount} \u9879`);
|
|
7207
7034
|
}
|
|
7208
7035
|
lines.push("");
|
|
7209
|
-
for (const category of
|
|
7210
|
-
const sectionTitle =
|
|
7211
|
-
const
|
|
7212
|
-
|
|
7036
|
+
for (const category of MLPS3_CATEGORY_ORDER) {
|
|
7037
|
+
const sectionTitle = MLPS3_CATEGORY_SECTION[category];
|
|
7038
|
+
const catResults = results.filter(
|
|
7039
|
+
(r) => r.item.categoryCn === category && r.status !== "not_applicable"
|
|
7040
|
+
);
|
|
7041
|
+
if (catResults.length === 0) continue;
|
|
7213
7042
|
lines.push(`## ${sectionTitle}`);
|
|
7214
7043
|
lines.push("");
|
|
7215
|
-
const
|
|
7216
|
-
for (const r of
|
|
7217
|
-
const
|
|
7218
|
-
|
|
7219
|
-
|
|
7044
|
+
const controlMap = /* @__PURE__ */ new Map();
|
|
7045
|
+
for (const r of catResults) {
|
|
7046
|
+
const key = r.item.controlCn;
|
|
7047
|
+
if (!controlMap.has(key)) controlMap.set(key, []);
|
|
7048
|
+
controlMap.get(key).push(r);
|
|
7220
7049
|
}
|
|
7221
|
-
for (const [
|
|
7222
|
-
lines.push(`### ${
|
|
7223
|
-
for (const r of
|
|
7224
|
-
const icon = r.status === "clean" ? "\u2705" : r.status === "issues" ? "\u274C" : "\u26A0\uFE0F";
|
|
7225
|
-
const
|
|
7226
|
-
lines.push(`- [${icon}] ${r.
|
|
7050
|
+
for (const [controlName, controlResults] of controlMap) {
|
|
7051
|
+
lines.push(`### ${controlName}`);
|
|
7052
|
+
for (const r of controlResults) {
|
|
7053
|
+
const icon = r.status === "clean" ? "\u2705" : r.status === "issues" ? "\u274C" : r.status === "unknown" ? "\u26A0\uFE0F" : r.status === "manual" ? "\u{1F4CB}" : "\u{1F3E2}";
|
|
7054
|
+
const suffix = r.status === "unknown" ? " \u2014 \u672A\u68C0\u67E5" : r.status === "manual" ? ` \u2014 ${r.mapping.guidance ?? "\u9700\u4EBA\u5DE5\u8BC4\u4F30"}` : r.status === "cloud_provider" ? ` \u2014 ${r.mapping.note ?? "\u4E91\u5E73\u53F0\u8D1F\u8D23"}` : r.status === "clean" ? " \u672A\u53D1\u73B0\u95EE\u9898" : " \u53D1\u73B0\u95EE\u9898";
|
|
7055
|
+
lines.push(`- [${icon}] ${r.item.id} ${r.item.requirementCn.slice(0, 60)}${r.item.requirementCn.length > 60 ? "\u2026" : ""}${suffix}`);
|
|
7227
7056
|
if (r.status === "issues" && r.relatedFindings.length > 0) {
|
|
7228
7057
|
for (const f of r.relatedFindings.slice(0, 3)) {
|
|
7229
7058
|
lines.push(` - ${f.severity}: ${f.title}`);
|
|
@@ -7260,6 +7089,10 @@ function generateMlps3Report(scanResults) {
|
|
|
7260
7089
|
}
|
|
7261
7090
|
lines.push("");
|
|
7262
7091
|
}
|
|
7092
|
+
if (naCount > 0) {
|
|
7093
|
+
lines.push(`> \u4E0D\u9002\u7528\u9879: ${naCount} \u9879\uFF08\u7269\u8054\u7F51/\u65E0\u7EBF\u7F51\u7EDC/\u79FB\u52A8\u7EC8\u7AEF/\u5DE5\u63A7\u7CFB\u7EDF/\u53EF\u4FE1\u9A8C\u8BC1\u7B49\uFF09`);
|
|
7094
|
+
lines.push("");
|
|
7095
|
+
}
|
|
7263
7096
|
return lines.join("\n");
|
|
7264
7097
|
}
|
|
7265
7098
|
|