aws-security-mcp 0.6.3 → 0.7.1

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.
@@ -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.6.3";
240
+ var VERSION = "0.7.1";
241
241
 
242
242
  // src/utils/aws-client.ts
243
243
  import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
@@ -1245,7 +1245,7 @@ async function dnsResolves(hostname) {
1245
1245
  var DnsDanglingScanner = class {
1246
1246
  moduleName = "dns_dangling";
1247
1247
  async scan(ctx) {
1248
- const { region, partition, accountId } = ctx;
1248
+ const { region, partition } = ctx;
1249
1249
  const startMs = Date.now();
1250
1250
  const findings = [];
1251
1251
  const warnings = [];
@@ -2867,6 +2867,22 @@ import {
2867
2867
  SecurityHubClient as SecurityHubClient2,
2868
2868
  GetFindingsCommand
2869
2869
  } from "@aws-sdk/client-securityhub";
2870
+
2871
+ // src/utils/sh-source.ts
2872
+ function getSecurityHubSource(finding) {
2873
+ const impact = finding.impact ?? "";
2874
+ const match = impact.match(/^Source:\s*([^(]+)/);
2875
+ if (!match) return "Other";
2876
+ const product = match[1].trim();
2877
+ if (product === "Security Hub" || product.includes("Foundational")) return "FSBP";
2878
+ if (product === "Inspector" || product.includes("Inspector")) return "Inspector";
2879
+ if (product === "GuardDuty" || product.includes("GuardDuty")) return "GuardDuty";
2880
+ if (product === "Config" || product.includes("Config")) return "Config";
2881
+ if (product === "IAM Access Analyzer" || product.includes("Access Analyzer")) return "Access Analyzer";
2882
+ return "Other";
2883
+ }
2884
+
2885
+ // src/scanners/security-hub-findings.ts
2870
2886
  function shSeverityToScore(label) {
2871
2887
  switch (label) {
2872
2888
  case "CRITICAL":
@@ -2936,7 +2952,7 @@ var SecurityHubFindingsScanner = class {
2936
2952
  if (recText && !["See References", "None Provided", ""].includes(recText.trim())) {
2937
2953
  remediationSteps.push(recText);
2938
2954
  }
2939
- findings.push({
2955
+ const finding = {
2940
2956
  severity,
2941
2957
  title: f.Title ?? "Security Hub Finding",
2942
2958
  resourceType,
@@ -2950,7 +2966,9 @@ var SecurityHubFindingsScanner = class {
2950
2966
  priority: priorityFromSeverity(severity),
2951
2967
  module: this.moduleName,
2952
2968
  accountId: f.AwsAccountId ?? accountId
2953
- });
2969
+ };
2970
+ finding.source = getSecurityHubSource(finding);
2971
+ findings.push(finding);
2954
2972
  }
2955
2973
  nextToken = resp.NextToken;
2956
2974
  } while (nextToken);
@@ -7244,11 +7262,24 @@ function generateMlps3Report(scanResults, lang) {
7244
7262
  function esc(s) {
7245
7263
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
7246
7264
  }
7265
+ function safeUrl(url) {
7266
+ try {
7267
+ const u = new URL(url);
7268
+ if (u.protocol === "https:" || u.protocol === "http:") return url;
7269
+ return null;
7270
+ } catch {
7271
+ return null;
7272
+ }
7273
+ }
7247
7274
  function escWithLinks(s) {
7248
7275
  const parts = s.split(/(https?:\/\/\S+)/);
7249
7276
  return parts.map((part, i) => {
7250
7277
  if (i % 2 === 1) {
7251
- return `<a href="${esc(part)}" style="color:#60a5fa" target="_blank" rel="noopener">${esc(part)}</a>`;
7278
+ const safe = safeUrl(part);
7279
+ if (safe) {
7280
+ return `<a href="${esc(safe)}" style="color:#60a5fa" target="_blank" rel="noopener">${esc(part)}</a>`;
7281
+ }
7282
+ return esc(part);
7252
7283
  }
7253
7284
  return esc(part);
7254
7285
  }).join("");
@@ -7274,18 +7305,6 @@ var SEVERITY_ORDER2 = ["CRITICAL", "HIGH", "MEDIUM", "LOW"];
7274
7305
  function getRecommendationTemplate(rem) {
7275
7306
  return rem.replace(/\b(i-[0-9a-f]+)\b/g, "{instance}").replace(/\b(vol-[0-9a-f]+)\b/g, "{volume}").replace(/\b(sg-[0-9a-f]+)\b/g, "{sg}").replace(/\b(eipalloc-[0-9a-f]+)\b/g, "{eip}").replace(/\b(arn:aws[-\w]*:[^"\s]+)\b/g, "{arn}").replace(/"[^"]+"/g, "{name}").replace(/bucket \S+/g, "bucket {name}").replace(/instance \S+/g, "instance {id}").replace(/volume \S+/g, "volume {id}").replace(/rule \S+/g, "rule {name}");
7276
7307
  }
7277
- function getSecurityHubSource(finding) {
7278
- const impact = finding.impact ?? "";
7279
- const match = impact.match(/^Source:\s*([^(]+)/);
7280
- if (!match) return "Other";
7281
- const product = match[1].trim();
7282
- if (product === "Security Hub" || product.includes("Foundational")) return "FSBP";
7283
- if (product === "Inspector" || product.includes("Inspector")) return "Inspector";
7284
- if (product === "GuardDuty" || product.includes("GuardDuty")) return "GuardDuty";
7285
- if (product === "Config" || product.includes("Config")) return "Config";
7286
- if (product === "IAM Access Analyzer" || product.includes("Access Analyzer")) return "Access Analyzer";
7287
- return "Other";
7288
- }
7289
7308
  var SECURITY_HUB_SUB_CAT_ORDER = ["FSBP", "Inspector", "GuardDuty", "Config", "Access Analyzer", "Other"];
7290
7309
  function scoreColor(score) {
7291
7310
  if (score >= 80) return "#22c55e";
@@ -7481,6 +7500,7 @@ function sharedCss() {
7481
7500
  .filter-count{color:#64748b;font-size:13px;margin-left:auto}
7482
7501
  @media print{
7483
7502
  .filter-toolbar{display:none !important}
7503
+ .finding-card,.module-fold{display:block !important}
7484
7504
  body{background:#fff;color:#1e293b;-webkit-print-color-adjust:exact;print-color-adjust:exact}
7485
7505
  .container{max-width:100%;padding:20px}
7486
7506
  .card,.score-card,.stat-card,.chart-box,.finding-fold,.top5-card,.trend-chart,.category-fold,.module-fold,.finding-card,.rec-fold{background:#fff;border:1px solid #e2e8f0}
@@ -7987,7 +8007,8 @@ ${rest}
7987
8007
  const renderRec = (r) => {
7988
8008
  const sev = r.severity.toLowerCase();
7989
8009
  const countLabel = r.count > 1 ? ` (&times; ${r.count})` : "";
7990
- const linkHtml = r.url ? ` <a href="${esc(r.url)}" style="color:#60a5fa" target="_blank" rel="noopener">&#128214;</a>` : "";
8010
+ const safeLink = r.url ? safeUrl(r.url) : null;
8011
+ const linkHtml = safeLink ? ` <a href="${esc(safeLink)}" style="color:#60a5fa" target="_blank" rel="noopener">&#128214;</a>` : "";
7991
8012
  return `<li><span class="badge badge-${esc(sev)}">${esc(r.severity)}</span> ${esc(r.text)}${countLabel}${linkHtml}</li>`;
7992
8013
  };
7993
8014
  const TOP_N = 10;
@@ -8023,7 +8044,8 @@ ${remaining.map(renderRec).join("\n")}
8023
8044
  document.querySelectorAll('.module-fold').forEach(function(f){
8024
8045
  var mod=f.getAttribute('data-module');
8025
8046
  if(activeMod!=='ALL'&&mod!==activeMod){f.style.display='none';return;}
8026
- f.style.display='';
8047
+ var hasVisible=f.querySelectorAll('.finding-card:not([style*="display: none"])').length>0;
8048
+ f.style.display=hasVisible?'':'none';
8027
8049
  });
8028
8050
  document.querySelectorAll('.severity-group-fold').forEach(function(g){
8029
8051
  g.style.display=g.querySelectorAll('.finding-card:not([style*="display: none"])').length?'':'none';
@@ -8145,7 +8167,6 @@ function generateMlps3HtmlReport(scanResults, history, lang) {
8145
8167
  </section>`;
8146
8168
  }
8147
8169
  const isEn = (lang ?? "zh") === "en";
8148
- const itemCat = (r) => isEn ? r.item.categoryEn : r.item.categoryCn;
8149
8170
  const itemControl = (r) => isEn ? r.item.controlEn : r.item.controlCn;
8150
8171
  const itemReq = (r) => isEn ? r.item.requirementEn : r.item.requirementCn;
8151
8172
  const categoryMap = /* @__PURE__ */ new Map();
@@ -8347,7 +8368,8 @@ ${itemsHtml}
8347
8368
  const renderMlpsRec = (r) => {
8348
8369
  const sev = r.severity.toLowerCase();
8349
8370
  const countLabel = r.count > 1 ? ` (&times; ${r.count})` : "";
8350
- const linkHtml = r.url ? ` <a href="${esc(r.url)}" style="color:#60a5fa" target="_blank" rel="noopener">&#128214;</a>` : "";
8371
+ const safeLink = r.url ? safeUrl(r.url) : null;
8372
+ const linkHtml = safeLink ? ` <a href="${esc(safeLink)}" style="color:#60a5fa" target="_blank" rel="noopener">&#128214;</a>` : "";
8351
8373
  return `<li><span class="badge badge-${esc(sev)}">${esc(r.severity)}</span> ${esc(r.text)}${countLabel}${linkHtml}</li>`;
8352
8374
  };
8353
8375
  const MLPS_TOP_N = 10;