aws-security-mcp 0.6.2 → 0.6.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.
@@ -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.2";
240
+ var VERSION = "0.6.3";
241
241
 
242
242
  // src/utils/aws-client.ts
243
243
  import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
@@ -3874,6 +3874,12 @@ var zhI18n = {
3874
3874
  trendTitle: "30\u65E5\u8D8B\u52BF",
3875
3875
  findingsBySeverity: "\u6309\u4E25\u91CD\u6027\u5206\u7C7B\u7684\u53D1\u73B0",
3876
3876
  showMoreCount: (n) => `\u663E\u793A\u5269\u4F59 ${n} \u9879\u2026`,
3877
+ // Filter toolbar
3878
+ filterSeverity: "\u4E25\u91CD\u6027\uFF1A",
3879
+ filterModule: "\u6A21\u5757\uFF1A",
3880
+ filterAll: "\u5168\u90E8",
3881
+ filterAllModules: "\u5168\u90E8\u6A21\u5757",
3882
+ filterCountTpl: "\u663E\u793A {shown} / {total} \u4E2A\u53D1\u73B0",
3877
3883
  // Extended — MLPS extras
3878
3884
  // Markdown report
3879
3885
  executiveSummary: "\u6267\u884C\u6458\u8981",
@@ -4144,6 +4150,12 @@ var enI18n = {
4144
4150
  trendTitle: "30-Day Trends",
4145
4151
  findingsBySeverity: "Findings by Severity",
4146
4152
  showMoreCount: (n) => `Show ${n} more\u2026`,
4153
+ // Filter toolbar
4154
+ filterSeverity: "Severity:",
4155
+ filterModule: "Module:",
4156
+ filterAll: "All",
4157
+ filterAllModules: "All Modules",
4158
+ filterCountTpl: "Showing {shown} / {total} findings",
4147
4159
  // Extended \u2014 MLPS extras
4148
4160
  // Markdown report
4149
4161
  executiveSummary: "Executive Summary",
@@ -7459,7 +7471,16 @@ function sharedCss() {
7459
7471
  .rec-body ol{padding-left:24px}
7460
7472
  .rec-body li{margin-bottom:8px;color:#cbd5e1;font-size:13px}
7461
7473
  .rec-body .badge{margin-right:6px;vertical-align:middle}
7474
+ .filter-toolbar{display:flex;flex-wrap:wrap;gap:16px;align-items:center;margin-bottom:20px;padding:12px 16px;background:#1e293b;border:1px solid #334155;border-radius:8px}
7475
+ .filter-group{display:flex;align-items:center;gap:8px}
7476
+ .filter-label{color:#94a3b8;font-size:13px}
7477
+ .filter-btn{padding:4px 12px;border-radius:4px;border:1px solid #475569;background:transparent;color:#cbd5e1;cursor:pointer;font-size:13px}
7478
+ .filter-btn:hover{background:#334155}
7479
+ .filter-btn.active{background:#3b82f6;border-color:#3b82f6;color:#fff}
7480
+ .filter-select{padding:4px 8px;border-radius:4px;border:1px solid #475569;background:#0f172a;color:#cbd5e1;font-size:13px}
7481
+ .filter-count{color:#64748b;font-size:13px;margin-left:auto}
7462
7482
  @media print{
7483
+ .filter-toolbar{display:none !important}
7463
7484
  body{background:#fff;color:#1e293b;-webkit-print-color-adjust:exact;print-color-adjust:exact}
7464
7485
  .container{max-width:100%;padding:20px}
7465
7486
  .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}
@@ -7718,13 +7739,14 @@ function generateHtmlReport(scanResults, history, lang) {
7718
7739
  </section>`;
7719
7740
  }
7720
7741
  let findingsHtml;
7742
+ let filterToolbarHtml = "";
7721
7743
  if (summary.totalFindings === 0) {
7722
7744
  findingsHtml = `<div class="no-findings">${esc(t.noIssuesFound)}</div>`;
7723
7745
  } else {
7724
7746
  const FOLD_THRESHOLD = 20;
7725
- const renderCard = (f) => {
7747
+ const renderCard = (f, moduleKey) => {
7726
7748
  const sev = f.severity.toLowerCase();
7727
- return `<div class="finding-card sev-${esc(sev)}">
7749
+ return `<div class="finding-card sev-${esc(sev)}" data-severity="${esc(f.severity)}" data-module="${esc(moduleKey)}">
7728
7750
  <span class="badge badge-${esc(sev)}">${esc(f.severity)}</span>
7729
7751
  <span class="finding-title-text">${esc(f.title)}</span>
7730
7752
  <span class="finding-resource">${esc(f.resourceArn || f.resourceId)}</span>
@@ -7735,12 +7757,12 @@ function generateHtmlReport(scanResults, history, lang) {
7735
7757
  </div></details>
7736
7758
  </div>`;
7737
7759
  };
7738
- const renderCards = (findings) => {
7760
+ const renderCards = (findings, moduleKey) => {
7739
7761
  if (findings.length <= FOLD_THRESHOLD) {
7740
- return findings.map(renderCard).join("\n");
7762
+ return findings.map((f) => renderCard(f, moduleKey)).join("\n");
7741
7763
  }
7742
- const first = findings.slice(0, FOLD_THRESHOLD).map(renderCard).join("\n");
7743
- const rest = findings.slice(FOLD_THRESHOLD).map(renderCard).join("\n");
7764
+ const first = findings.slice(0, FOLD_THRESHOLD).map((f) => renderCard(f, moduleKey)).join("\n");
7765
+ const rest = findings.slice(FOLD_THRESHOLD).map((f) => renderCard(f, moduleKey)).join("\n");
7744
7766
  return `${first}
7745
7767
  <details><summary>${t.showRemainingFindings(findings.length - FOLD_THRESHOLD)}</summary>
7746
7768
  ${rest}
@@ -7775,7 +7797,7 @@ ${rest}
7775
7797
  if (aHasCritHigh !== bHasCritHigh) return aHasCritHigh ? -1 : 1;
7776
7798
  return b[1].length - a[1].length;
7777
7799
  });
7778
- const renderSeverityGroups = (findings) => {
7800
+ const renderSeverityGroups = (findings, moduleKey) => {
7779
7801
  return SEVERITY_ORDER2.map((sev) => {
7780
7802
  const sevFindings = findings.filter((f) => f.severity === sev);
7781
7803
  if (sevFindings.length === 0) return "";
@@ -7784,7 +7806,7 @@ ${rest}
7784
7806
  const label = sev.charAt(0) + sev.slice(1).toLowerCase();
7785
7807
  return `<details class="severity-group-fold">
7786
7808
  <summary><h4>${emoji} ${label} (${sevFindings.length})</h4></summary>
7787
- ${renderCards(sevFindings)}
7809
+ ${renderCards(sevFindings, moduleKey)}
7788
7810
  </details>`;
7789
7811
  }).filter(Boolean).join("\n");
7790
7812
  };
@@ -7796,16 +7818,38 @@ ${rest}
7796
7818
  findingsHtml = moduleEntries.map(([modName, modFindings, subCatLabel]) => {
7797
7819
  const badges = renderModuleBadges(modFindings);
7798
7820
  const displayName = subCatLabel ?? (t.moduleNames[modName] ?? modName);
7799
- return `<details class="module-fold">
7821
+ return `<details class="module-fold" data-module="${esc(modName)}">
7800
7822
  <summary>
7801
7823
  <h3>&#128274; ${esc(displayName)} (${modFindings.length})</h3>
7802
7824
  <span class="module-badges">${badges}</span>
7803
7825
  </summary>
7804
7826
  <div class="module-body">
7805
- ${renderSeverityGroups(modFindings)}
7827
+ ${renderSeverityGroups(modFindings, modName)}
7806
7828
  </div>
7807
7829
  </details>`;
7808
7830
  }).join("\n");
7831
+ const moduleOptions = moduleEntries.map(([modKey, , subCatLabel]) => {
7832
+ const label = subCatLabel ?? (t.moduleNames[modKey] ?? modKey);
7833
+ return `<option value="${esc(modKey)}">${esc(label)}</option>`;
7834
+ }).join("\n ");
7835
+ filterToolbarHtml = `<div class="filter-toolbar" id="filterBar">
7836
+ <div class="filter-group">
7837
+ <span class="filter-label">${esc(t.filterSeverity)}</span>
7838
+ <button class="filter-btn active" data-severity="ALL">${esc(t.filterAll)}</button>
7839
+ <button class="filter-btn" data-severity="CRITICAL">Critical</button>
7840
+ <button class="filter-btn" data-severity="HIGH">High</button>
7841
+ <button class="filter-btn" data-severity="MEDIUM">Medium</button>
7842
+ <button class="filter-btn" data-severity="LOW">Low</button>
7843
+ </div>
7844
+ <div class="filter-group">
7845
+ <span class="filter-label">${esc(t.filterModule)}</span>
7846
+ <select class="filter-select" id="moduleFilter">
7847
+ <option value="ALL">${esc(t.filterAllModules)}</option>
7848
+ ${moduleOptions}
7849
+ </select>
7850
+ </div>
7851
+ <div class="filter-count" id="filterCount" data-tpl="${esc(t.filterCountTpl)}"></div>
7852
+ </div>`;
7809
7853
  }
7810
7854
  let trendHtml = "";
7811
7855
  if (history && history.length >= 2) {
@@ -7961,6 +8005,43 @@ ${remaining.map(renderRec).join("\n")}
7961
8005
  </div>
7962
8006
  </details>`;
7963
8007
  }
8008
+ const filterScript = summary.totalFindings > 0 ? `<script>
8009
+ (function(){
8010
+ var activeSev='ALL',activeMod='ALL';
8011
+ var countEl=document.getElementById('filterCount');
8012
+ var tpl=countEl?countEl.getAttribute('data-tpl'):'';
8013
+ function apply(){
8014
+ var cards=document.querySelectorAll('.finding-card[data-severity]');
8015
+ var shown=0,total=cards.length;
8016
+ cards.forEach(function(c){
8017
+ var sevOk=activeSev==='ALL'||c.getAttribute('data-severity')===activeSev;
8018
+ var modOk=activeMod==='ALL'||c.getAttribute('data-module')===activeMod;
8019
+ c.style.display=(sevOk&&modOk)?'':'none';
8020
+ if(sevOk&&modOk)shown++;
8021
+ });
8022
+ if(countEl)countEl.textContent=tpl.replace('{shown}',shown).replace('{total}',total);
8023
+ document.querySelectorAll('.module-fold').forEach(function(f){
8024
+ var mod=f.getAttribute('data-module');
8025
+ if(activeMod!=='ALL'&&mod!==activeMod){f.style.display='none';return;}
8026
+ f.style.display='';
8027
+ });
8028
+ document.querySelectorAll('.severity-group-fold').forEach(function(g){
8029
+ g.style.display=g.querySelectorAll('.finding-card:not([style*="display: none"])').length?'':'none';
8030
+ });
8031
+ }
8032
+ document.querySelectorAll('.filter-btn[data-severity]').forEach(function(b){
8033
+ b.addEventListener('click',function(){
8034
+ document.querySelectorAll('.filter-btn[data-severity]').forEach(function(x){x.classList.remove('active')});
8035
+ b.classList.add('active');
8036
+ activeSev=b.getAttribute('data-severity');
8037
+ apply();
8038
+ });
8039
+ });
8040
+ var sel=document.getElementById('moduleFilter');
8041
+ if(sel)sel.addEventListener('change',function(){activeMod=sel.value;apply();});
8042
+ apply();
8043
+ })();
8044
+ </script>` : "";
7964
8045
  return `<!DOCTYPE html>
7965
8046
  <html lang="${htmlLang}">
7966
8047
  <head>
@@ -8017,6 +8098,7 @@ ${buildServiceReminderHtml(modules, lang)}
8017
8098
 
8018
8099
  <section>
8019
8100
  <h2>${esc(t.allFindings)}</h2>
8101
+ ${filterToolbarHtml}
8020
8102
  ${findingsHtml}
8021
8103
  </section>
8022
8104
 
@@ -8028,6 +8110,7 @@ ${recsHtml}
8028
8110
  </footer>
8029
8111
 
8030
8112
  </div>
8113
+ ${filterScript}
8031
8114
  </body>
8032
8115
  </html>`;
8033
8116
  }