@panguard-ai/panguard-scan 0.1.0

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.
Files changed (105) hide show
  1. package/dist/cli/commands.d.ts +13 -0
  2. package/dist/cli/commands.d.ts.map +1 -0
  3. package/dist/cli/commands.js +132 -0
  4. package/dist/cli/commands.js.map +1 -0
  5. package/dist/cli/index.d.ts +9 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +138 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/index.d.ts +20 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +21 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/report/compliance-map.d.ts +91 -0
  14. package/dist/report/compliance-map.d.ts.map +1 -0
  15. package/dist/report/compliance-map.js +156 -0
  16. package/dist/report/compliance-map.js.map +1 -0
  17. package/dist/report/index.d.ts +14 -0
  18. package/dist/report/index.d.ts.map +1 -0
  19. package/dist/report/index.js +13 -0
  20. package/dist/report/index.js.map +1 -0
  21. package/dist/report/pdf-generator.d.ts +41 -0
  22. package/dist/report/pdf-generator.d.ts.map +1 -0
  23. package/dist/report/pdf-generator.js +238 -0
  24. package/dist/report/pdf-generator.js.map +1 -0
  25. package/dist/report/sections/compliance.d.ts +28 -0
  26. package/dist/report/sections/compliance.d.ts.map +1 -0
  27. package/dist/report/sections/compliance.js +227 -0
  28. package/dist/report/sections/compliance.js.map +1 -0
  29. package/dist/report/sections/cover.d.ts +22 -0
  30. package/dist/report/sections/cover.d.ts.map +1 -0
  31. package/dist/report/sections/cover.js +190 -0
  32. package/dist/report/sections/cover.js.map +1 -0
  33. package/dist/report/sections/executive-summary.d.ts +22 -0
  34. package/dist/report/sections/executive-summary.d.ts.map +1 -0
  35. package/dist/report/sections/executive-summary.js +206 -0
  36. package/dist/report/sections/executive-summary.js.map +1 -0
  37. package/dist/report/sections/findings-table.d.ts +28 -0
  38. package/dist/report/sections/findings-table.d.ts.map +1 -0
  39. package/dist/report/sections/findings-table.js +189 -0
  40. package/dist/report/sections/findings-table.js.map +1 -0
  41. package/dist/report/sections/remediation.d.ts +28 -0
  42. package/dist/report/sections/remediation.d.ts.map +1 -0
  43. package/dist/report/sections/remediation.js +157 -0
  44. package/dist/report/sections/remediation.js.map +1 -0
  45. package/dist/report/styles.d.ts +65 -0
  46. package/dist/report/styles.d.ts.map +1 -0
  47. package/dist/report/styles.js +80 -0
  48. package/dist/report/styles.js.map +1 -0
  49. package/dist/scanners/cve-checker.d.ts +21 -0
  50. package/dist/scanners/cve-checker.d.ts.map +1 -0
  51. package/dist/scanners/cve-checker.js +198 -0
  52. package/dist/scanners/cve-checker.js.map +1 -0
  53. package/dist/scanners/discovery-scanner.d.ts +24 -0
  54. package/dist/scanners/discovery-scanner.d.ts.map +1 -0
  55. package/dist/scanners/discovery-scanner.js +208 -0
  56. package/dist/scanners/discovery-scanner.js.map +1 -0
  57. package/dist/scanners/index.d.ts +54 -0
  58. package/dist/scanners/index.d.ts.map +1 -0
  59. package/dist/scanners/index.js +328 -0
  60. package/dist/scanners/index.js.map +1 -0
  61. package/dist/scanners/open-ports.d.ts +25 -0
  62. package/dist/scanners/open-ports.d.ts.map +1 -0
  63. package/dist/scanners/open-ports.js +198 -0
  64. package/dist/scanners/open-ports.js.map +1 -0
  65. package/dist/scanners/password-policy.d.ts +23 -0
  66. package/dist/scanners/password-policy.d.ts.map +1 -0
  67. package/dist/scanners/password-policy.js +324 -0
  68. package/dist/scanners/password-policy.js.map +1 -0
  69. package/dist/scanners/remote/dns-checker.d.ts +21 -0
  70. package/dist/scanners/remote/dns-checker.d.ts.map +1 -0
  71. package/dist/scanners/remote/dns-checker.js +103 -0
  72. package/dist/scanners/remote/dns-checker.js.map +1 -0
  73. package/dist/scanners/remote/http-headers.d.ts +19 -0
  74. package/dist/scanners/remote/http-headers.d.ts.map +1 -0
  75. package/dist/scanners/remote/http-headers.js +65 -0
  76. package/dist/scanners/remote/http-headers.js.map +1 -0
  77. package/dist/scanners/remote/index.d.ts +22 -0
  78. package/dist/scanners/remote/index.d.ts.map +1 -0
  79. package/dist/scanners/remote/index.js +120 -0
  80. package/dist/scanners/remote/index.js.map +1 -0
  81. package/dist/scanners/remote/port-scanner.d.ts +20 -0
  82. package/dist/scanners/remote/port-scanner.d.ts.map +1 -0
  83. package/dist/scanners/remote/port-scanner.js +65 -0
  84. package/dist/scanners/remote/port-scanner.js.map +1 -0
  85. package/dist/scanners/remote/ssl-checker.d.ts +24 -0
  86. package/dist/scanners/remote/ssl-checker.d.ts.map +1 -0
  87. package/dist/scanners/remote/ssl-checker.js +109 -0
  88. package/dist/scanners/remote/ssl-checker.js.map +1 -0
  89. package/dist/scanners/scheduled-tasks.d.ts +26 -0
  90. package/dist/scanners/scheduled-tasks.d.ts.map +1 -0
  91. package/dist/scanners/scheduled-tasks.js +299 -0
  92. package/dist/scanners/scheduled-tasks.js.map +1 -0
  93. package/dist/scanners/shared-folders.d.ts +25 -0
  94. package/dist/scanners/shared-folders.d.ts.map +1 -0
  95. package/dist/scanners/shared-folders.js +310 -0
  96. package/dist/scanners/shared-folders.js.map +1 -0
  97. package/dist/scanners/ssl-checker.d.ts +27 -0
  98. package/dist/scanners/ssl-checker.d.ts.map +1 -0
  99. package/dist/scanners/ssl-checker.js +197 -0
  100. package/dist/scanners/ssl-checker.js.map +1 -0
  101. package/dist/scanners/types.d.ts +140 -0
  102. package/dist/scanners/types.d.ts.map +1 -0
  103. package/dist/scanners/types.js +31 -0
  104. package/dist/scanners/types.js.map +1 -0
  105. package/package.json +38 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * SSL/TLS certificate checker
3
+ * SSL/TLS 憑證檢查器
4
+ *
5
+ * Checks SSL/TLS certificates on HTTPS-capable ports for expiration and
6
+ * validity issues. Connects to localhost on identified ports to inspect
7
+ * the presented certificate.
8
+ * 檢查具有 HTTPS 功能的埠上的 SSL/TLS 憑證是否有到期和有效性問題。
9
+ * 連線到 localhost 上已識別的埠以檢查呈現的憑證。
10
+ *
11
+ * @module @panguard-ai/panguard-scan/scanners/ssl-checker
12
+ */
13
+ import { type PortInfo } from '@panguard-ai/core';
14
+ import type { Finding } from './types.js';
15
+ /**
16
+ * Check SSL/TLS certificates on all HTTPS-capable ports
17
+ * 檢查所有具有 HTTPS 功能的埠上的 SSL/TLS 憑證
18
+ *
19
+ * Iterates through the provided port list, identifies ports that are likely
20
+ * serving HTTPS, and checks each certificate for expiration.
21
+ * 遍歷提供的埠列表,識別可能提供 HTTPS 服務的埠,並檢查每個憑證的到期情況。
22
+ *
23
+ * @param ports - Array of open port info from discovery / 來自偵察的開放埠資訊陣列
24
+ * @returns Array of certificate-related findings / 與憑證相關的發現陣列
25
+ */
26
+ export declare function checkSslCertificates(ports: PortInfo[]): Promise<Finding[]>;
27
+ //# sourceMappingURL=ssl-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssl-checker.d.ts","sourceRoot":"","sources":["../../src/scanners/ssl-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA8K1C;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA2BhF"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * SSL/TLS certificate checker
3
+ * SSL/TLS 憑證檢查器
4
+ *
5
+ * Checks SSL/TLS certificates on HTTPS-capable ports for expiration and
6
+ * validity issues. Connects to localhost on identified ports to inspect
7
+ * the presented certificate.
8
+ * 檢查具有 HTTPS 功能的埠上的 SSL/TLS 憑證是否有到期和有效性問題。
9
+ * 連線到 localhost 上已識別的埠以檢查呈現的憑證。
10
+ *
11
+ * @module @panguard-ai/panguard-scan/scanners/ssl-checker
12
+ */
13
+ import tls from 'node:tls';
14
+ import { createLogger } from '@panguard-ai/core';
15
+ const logger = createLogger('panguard-scan:ssl-checker');
16
+ /**
17
+ * Well-known HTTPS port numbers
18
+ * 已知的 HTTPS 埠號
19
+ */
20
+ const HTTPS_PORTS = new Set([443, 8443]);
21
+ /**
22
+ * Number of days before expiration to trigger a warning
23
+ * 到期前觸發警告的天數
24
+ */
25
+ const EXPIRY_WARNING_DAYS = 30;
26
+ /**
27
+ * Connection timeout in milliseconds
28
+ * 連線逾時(毫秒)
29
+ */
30
+ const CONNECT_TIMEOUT_MS = 5_000;
31
+ /**
32
+ * Determine whether a port is likely serving HTTPS
33
+ * 判斷埠是否可能提供 HTTPS 服務
34
+ *
35
+ * @param portInfo - Port information to evaluate / 要評估的埠資訊
36
+ * @returns True if the port likely serves HTTPS / 如果埠可能提供 HTTPS 服務則為 true
37
+ */
38
+ function isHttpsPort(portInfo) {
39
+ if (HTTPS_PORTS.has(portInfo.port))
40
+ return true;
41
+ if (portInfo.service && portInfo.service.toLowerCase().includes('https'))
42
+ return true;
43
+ return false;
44
+ }
45
+ /**
46
+ * Check the SSL certificate on a single port
47
+ * 檢查單一埠上的 SSL 憑證
48
+ *
49
+ * Establishes a TLS connection to localhost on the specified port and
50
+ * inspects the certificate's validity period.
51
+ * 在指定埠上建立到 localhost 的 TLS 連線,並檢查憑證的有效期間。
52
+ *
53
+ * @param port - Port number to check / 要檢查的埠號
54
+ * @returns A Finding if the certificate is expired or expiring soon, or null / 如果憑證已過期或即將到期則回傳 Finding,否則為 null
55
+ */
56
+ async function checkCertOnPort(port) {
57
+ return new Promise((resolve) => {
58
+ const socket = tls.connect({
59
+ host: 'localhost',
60
+ port,
61
+ rejectUnauthorized: false,
62
+ timeout: CONNECT_TIMEOUT_MS,
63
+ }, () => {
64
+ try {
65
+ const cert = socket.getPeerCertificate();
66
+ if (!cert || !cert.valid_to) {
67
+ logger.debug(`No certificate found on port ${port}`);
68
+ socket.destroy();
69
+ resolve(null);
70
+ return;
71
+ }
72
+ const validTo = new Date(cert.valid_to);
73
+ const validFrom = new Date(cert.valid_from);
74
+ const now = new Date();
75
+ const daysUntilExpiry = Math.floor((validTo.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
76
+ const subject = cert.subject?.CN || 'unknown';
77
+ if (now > validTo) {
78
+ // Certificate has expired
79
+ // 憑證已過期
80
+ logger.info(`Expired certificate on port ${port}: expired ${Math.abs(daysUntilExpiry)} days ago`);
81
+ socket.destroy();
82
+ resolve({
83
+ id: `SCAN-SSL-${port}`,
84
+ title: `Expired SSL certificate on port ${port} / ` + `埠 ${port} 上的 SSL 憑證已過期`,
85
+ description: `The SSL/TLS certificate on port ${port} (subject: ${subject}) ` +
86
+ `expired on ${validTo.toISOString().split('T')[0]}. ` +
87
+ `It has been expired for ${Math.abs(daysUntilExpiry)} day(s). / ` +
88
+ `埠 ${port} 上的 SSL/TLS 憑證(主體:${subject})` +
89
+ `已於 ${validTo.toISOString().split('T')[0]} 過期。` +
90
+ `已過期 ${Math.abs(daysUntilExpiry)} 天。`,
91
+ severity: 'high',
92
+ category: 'certificate',
93
+ remediation: `Renew the SSL/TLS certificate for port ${port} immediately. ` +
94
+ "Consider using automated certificate management (e.g., Let's Encrypt). / " +
95
+ `立即續期埠 ${port} 的 SSL/TLS 憑證。` +
96
+ "考慮使用自動憑證管理(例如 Let's Encrypt)。",
97
+ complianceRef: '4.4',
98
+ details: `Subject: ${subject}, Valid from: ${validFrom.toISOString()}, ` +
99
+ `Valid to: ${validTo.toISOString()}, Days expired: ${Math.abs(daysUntilExpiry)}`,
100
+ });
101
+ return;
102
+ }
103
+ if (daysUntilExpiry <= EXPIRY_WARNING_DAYS) {
104
+ // Certificate expiring soon
105
+ // 憑證即將到期
106
+ logger.info(`Certificate on port ${port} expiring in ${daysUntilExpiry} days`);
107
+ socket.destroy();
108
+ resolve({
109
+ id: `SCAN-SSL-${port}`,
110
+ title: `SSL certificate expiring soon on port ${port} / ` +
111
+ `埠 ${port} 上的 SSL 憑證即將到期`,
112
+ description: `The SSL/TLS certificate on port ${port} (subject: ${subject}) ` +
113
+ `will expire on ${validTo.toISOString().split('T')[0]} ` +
114
+ `(${daysUntilExpiry} day(s) remaining). / ` +
115
+ `埠 ${port} 上的 SSL/TLS 憑證(主體:${subject})` +
116
+ `將於 ${validTo.toISOString().split('T')[0]} 到期` +
117
+ `(剩餘 ${daysUntilExpiry} 天)。`,
118
+ severity: 'medium',
119
+ category: 'certificate',
120
+ remediation: `Renew the SSL/TLS certificate for port ${port} before it expires. ` +
121
+ 'Set up automated renewal to prevent future expirations. / ' +
122
+ `在到期前續期埠 ${port} 的 SSL/TLS 憑證。` +
123
+ '設定自動續期以防止未來過期。',
124
+ complianceRef: '4.4',
125
+ details: `Subject: ${subject}, Valid from: ${validFrom.toISOString()}, ` +
126
+ `Valid to: ${validTo.toISOString()}, Days remaining: ${daysUntilExpiry}`,
127
+ });
128
+ return;
129
+ }
130
+ // Certificate is valid and not expiring soon
131
+ // 憑證有效且不會很快到期
132
+ logger.debug(`Certificate on port ${port} is valid (expires in ${daysUntilExpiry} days)`);
133
+ socket.destroy();
134
+ resolve(null);
135
+ }
136
+ catch (err) {
137
+ logger.debug(`Error reading certificate on port ${port}`, {
138
+ error: err instanceof Error ? err.message : String(err),
139
+ });
140
+ socket.destroy();
141
+ resolve(null);
142
+ }
143
+ });
144
+ // Handle connection errors
145
+ // 處理連線錯誤
146
+ socket.on('error', (err) => {
147
+ logger.debug(`TLS connection error on port ${port}`, {
148
+ error: err.message,
149
+ });
150
+ socket.destroy();
151
+ resolve(null);
152
+ });
153
+ // Handle timeout
154
+ // 處理逾時
155
+ socket.on('timeout', () => {
156
+ logger.debug(`TLS connection timeout on port ${port}`);
157
+ socket.destroy();
158
+ resolve(null);
159
+ });
160
+ });
161
+ }
162
+ /**
163
+ * Check SSL/TLS certificates on all HTTPS-capable ports
164
+ * 檢查所有具有 HTTPS 功能的埠上的 SSL/TLS 憑證
165
+ *
166
+ * Iterates through the provided port list, identifies ports that are likely
167
+ * serving HTTPS, and checks each certificate for expiration.
168
+ * 遍歷提供的埠列表,識別可能提供 HTTPS 服務的埠,並檢查每個憑證的到期情況。
169
+ *
170
+ * @param ports - Array of open port info from discovery / 來自偵察的開放埠資訊陣列
171
+ * @returns Array of certificate-related findings / 與憑證相關的發現陣列
172
+ */
173
+ export async function checkSslCertificates(ports) {
174
+ const findings = [];
175
+ const httpsPorts = ports.filter(isHttpsPort);
176
+ if (httpsPorts.length === 0) {
177
+ logger.info('No HTTPS-capable ports found to check');
178
+ return findings;
179
+ }
180
+ logger.info(`Checking SSL certificates on ${httpsPorts.length} HTTPS-capable port(s)`);
181
+ for (const portInfo of httpsPorts) {
182
+ try {
183
+ const finding = await checkCertOnPort(portInfo.port);
184
+ if (finding) {
185
+ findings.push(finding);
186
+ }
187
+ }
188
+ catch (err) {
189
+ logger.debug(`Failed to check SSL on port ${portInfo.port}`, {
190
+ error: err instanceof Error ? err.message : String(err),
191
+ });
192
+ }
193
+ }
194
+ logger.info(`SSL certificate check complete: ${findings.length} finding(s)`);
195
+ return findings;
196
+ }
197
+ //# sourceMappingURL=ssl-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssl-checker.js","sourceRoot":"","sources":["../../src/scanners/ssl-checker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * PanguardScan scanner type definitions
3
+ * PanguardScan 掃描器型別定義
4
+ *
5
+ * @module @panguard-ai/panguard-scan/scanners/types
6
+ */
7
+ import type { DiscoveryResult, Severity, Language } from '@panguard-ai/core';
8
+ /**
9
+ * Scan configuration options
10
+ * 掃描配置選項
11
+ */
12
+ export interface ScanConfig {
13
+ /**
14
+ * Scan depth - 'quick' (~30s) or 'full' (~60s)
15
+ * 掃描深度 - 'quick'(約 30 秒)或 'full'(約 60 秒)
16
+ */
17
+ depth: 'quick' | 'full';
18
+ /**
19
+ * Output language
20
+ * 輸出語言
21
+ */
22
+ lang: Language;
23
+ /**
24
+ * Output PDF file path
25
+ * 輸出 PDF 檔案路徑
26
+ */
27
+ output?: string;
28
+ /**
29
+ * Enable verbose output
30
+ * 啟用詳細輸出
31
+ */
32
+ verbose?: boolean;
33
+ }
34
+ /**
35
+ * Individual security finding from a scanner
36
+ * 掃描器的個別安全發現
37
+ */
38
+ export interface Finding {
39
+ /**
40
+ * Unique finding identifier
41
+ * 唯一發現識別碼
42
+ */
43
+ id: string;
44
+ /**
45
+ * Finding title (human-readable)
46
+ * 發現標題(人類可讀)
47
+ */
48
+ title: string;
49
+ /**
50
+ * Detailed description
51
+ * 詳細描述
52
+ */
53
+ description: string;
54
+ /**
55
+ * Severity level
56
+ * 嚴重等級
57
+ */
58
+ severity: Severity;
59
+ /**
60
+ * Finding category (e.g. 'password', 'network', 'system')
61
+ * 發現分類(如 'password'、'network'、'system')
62
+ */
63
+ category: string;
64
+ /**
65
+ * Remediation recommendation
66
+ * 修復建議
67
+ */
68
+ remediation: string;
69
+ /**
70
+ * Taiwan ISMS compliance reference (e.g. "4.1.2")
71
+ * 台灣資通安全管理法條目參照(如 "4.1.2")
72
+ */
73
+ complianceRef?: string;
74
+ /**
75
+ * Additional technical details
76
+ * 額外技術詳情
77
+ */
78
+ details?: string;
79
+ /**
80
+ * Manual fix commands for free-tier users
81
+ * 免費版用戶的手動修復指令
82
+ */
83
+ manualFix?: string[];
84
+ }
85
+ /**
86
+ * Complete scan result
87
+ * 完整掃描結果
88
+ */
89
+ export interface ScanResult {
90
+ /**
91
+ * Environment discovery result from core
92
+ * 來自 core 的環境偵察結果
93
+ */
94
+ discovery: DiscoveryResult;
95
+ /**
96
+ * All security findings (sorted by severity)
97
+ * 所有安全發現(按嚴重度排序)
98
+ */
99
+ findings: Finding[];
100
+ /**
101
+ * Overall risk score (0-100)
102
+ * 總體風險評分(0-100)
103
+ */
104
+ riskScore: number;
105
+ /**
106
+ * Risk level label
107
+ * 風險等級標籤
108
+ */
109
+ riskLevel: Severity;
110
+ /**
111
+ * Scan duration in milliseconds
112
+ * 掃描持續時間(毫秒)
113
+ */
114
+ scanDuration: number;
115
+ /**
116
+ * Scan timestamp (ISO 8601)
117
+ * 掃描時間戳(ISO 8601)
118
+ */
119
+ scannedAt: string;
120
+ /**
121
+ * Scan configuration used
122
+ * 使用的掃描配置
123
+ */
124
+ config: ScanConfig;
125
+ }
126
+ /**
127
+ * Severity sort order (lower = more severe)
128
+ * 嚴重度排序(越低越嚴重)
129
+ */
130
+ export declare const SEVERITY_ORDER: Record<string, number>;
131
+ /**
132
+ * Sort findings by severity (most severe first)
133
+ * 按嚴重度排序發現(最嚴重的在前)
134
+ *
135
+ * @param a - First finding / 第一個發現
136
+ * @param b - Second finding / 第二個發現
137
+ * @returns Sort comparison value / 排序比較值
138
+ */
139
+ export declare function sortBySeverity(a: Finding, b: Finding): number;
140
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scanners/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IAExB;;;OAGG;IACH,IAAI,EAAE,QAAQ,CAAC;IAEf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,SAAS,EAAE,eAAe,CAAC;IAE3B;;;OAGG;IACH,QAAQ,EAAE,OAAO,EAAE,CAAC;IAEpB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,SAAS,EAAE,QAAQ,CAAC;IAEpB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMjD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAI7D"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * PanguardScan scanner type definitions
3
+ * PanguardScan 掃描器型別定義
4
+ *
5
+ * @module @panguard-ai/panguard-scan/scanners/types
6
+ */
7
+ /**
8
+ * Severity sort order (lower = more severe)
9
+ * 嚴重度排序(越低越嚴重)
10
+ */
11
+ export const SEVERITY_ORDER = {
12
+ critical: 0,
13
+ high: 1,
14
+ medium: 2,
15
+ low: 3,
16
+ info: 4,
17
+ };
18
+ /**
19
+ * Sort findings by severity (most severe first)
20
+ * 按嚴重度排序發現(最嚴重的在前)
21
+ *
22
+ * @param a - First finding / 第一個發現
23
+ * @param b - Second finding / 第二個發現
24
+ * @returns Sort comparison value / 排序比較值
25
+ */
26
+ export function sortBySeverity(a, b) {
27
+ const aOrder = SEVERITY_ORDER[a.severity] ?? 5;
28
+ const bOrder = SEVERITY_ORDER[b.severity] ?? 5;
29
+ return aOrder - bOrder;
30
+ }
31
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/scanners/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA8IH;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,CAAU,EAAE,CAAU;IACnD,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,MAAM,GAAG,MAAM,CAAC;AACzB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@panguard-ai/panguard-scan",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "60-second security scanning CLI tool / 60 秒資安健檢工具",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "panguard-scan": "./dist/cli/index.js"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "package.json",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc --build",
21
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
22
+ "typecheck": "tsc --noEmit",
23
+ "test": "vitest run",
24
+ "dev": "tsc --build --watch",
25
+ "prepublishOnly": "pnpm run build"
26
+ },
27
+ "dependencies": {
28
+ "@panguard-ai/core": "workspace:*",
29
+ "@panguard-ai/security-hardening": "workspace:*",
30
+ "commander": "^12.0.0",
31
+ "pdfkit": "^0.15.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.14.0",
35
+ "@types/pdfkit": "^0.13.0",
36
+ "typescript": "~5.7.3"
37
+ }
38
+ }