@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.
- package/dist/cli/commands.d.ts +13 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +132 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +138 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/report/compliance-map.d.ts +91 -0
- package/dist/report/compliance-map.d.ts.map +1 -0
- package/dist/report/compliance-map.js +156 -0
- package/dist/report/compliance-map.js.map +1 -0
- package/dist/report/index.d.ts +14 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +13 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/pdf-generator.d.ts +41 -0
- package/dist/report/pdf-generator.d.ts.map +1 -0
- package/dist/report/pdf-generator.js +238 -0
- package/dist/report/pdf-generator.js.map +1 -0
- package/dist/report/sections/compliance.d.ts +28 -0
- package/dist/report/sections/compliance.d.ts.map +1 -0
- package/dist/report/sections/compliance.js +227 -0
- package/dist/report/sections/compliance.js.map +1 -0
- package/dist/report/sections/cover.d.ts +22 -0
- package/dist/report/sections/cover.d.ts.map +1 -0
- package/dist/report/sections/cover.js +190 -0
- package/dist/report/sections/cover.js.map +1 -0
- package/dist/report/sections/executive-summary.d.ts +22 -0
- package/dist/report/sections/executive-summary.d.ts.map +1 -0
- package/dist/report/sections/executive-summary.js +206 -0
- package/dist/report/sections/executive-summary.js.map +1 -0
- package/dist/report/sections/findings-table.d.ts +28 -0
- package/dist/report/sections/findings-table.d.ts.map +1 -0
- package/dist/report/sections/findings-table.js +189 -0
- package/dist/report/sections/findings-table.js.map +1 -0
- package/dist/report/sections/remediation.d.ts +28 -0
- package/dist/report/sections/remediation.d.ts.map +1 -0
- package/dist/report/sections/remediation.js +157 -0
- package/dist/report/sections/remediation.js.map +1 -0
- package/dist/report/styles.d.ts +65 -0
- package/dist/report/styles.d.ts.map +1 -0
- package/dist/report/styles.js +80 -0
- package/dist/report/styles.js.map +1 -0
- package/dist/scanners/cve-checker.d.ts +21 -0
- package/dist/scanners/cve-checker.d.ts.map +1 -0
- package/dist/scanners/cve-checker.js +198 -0
- package/dist/scanners/cve-checker.js.map +1 -0
- package/dist/scanners/discovery-scanner.d.ts +24 -0
- package/dist/scanners/discovery-scanner.d.ts.map +1 -0
- package/dist/scanners/discovery-scanner.js +208 -0
- package/dist/scanners/discovery-scanner.js.map +1 -0
- package/dist/scanners/index.d.ts +54 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +328 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/open-ports.d.ts +25 -0
- package/dist/scanners/open-ports.d.ts.map +1 -0
- package/dist/scanners/open-ports.js +198 -0
- package/dist/scanners/open-ports.js.map +1 -0
- package/dist/scanners/password-policy.d.ts +23 -0
- package/dist/scanners/password-policy.d.ts.map +1 -0
- package/dist/scanners/password-policy.js +324 -0
- package/dist/scanners/password-policy.js.map +1 -0
- package/dist/scanners/remote/dns-checker.d.ts +21 -0
- package/dist/scanners/remote/dns-checker.d.ts.map +1 -0
- package/dist/scanners/remote/dns-checker.js +103 -0
- package/dist/scanners/remote/dns-checker.js.map +1 -0
- package/dist/scanners/remote/http-headers.d.ts +19 -0
- package/dist/scanners/remote/http-headers.d.ts.map +1 -0
- package/dist/scanners/remote/http-headers.js +65 -0
- package/dist/scanners/remote/http-headers.js.map +1 -0
- package/dist/scanners/remote/index.d.ts +22 -0
- package/dist/scanners/remote/index.d.ts.map +1 -0
- package/dist/scanners/remote/index.js +120 -0
- package/dist/scanners/remote/index.js.map +1 -0
- package/dist/scanners/remote/port-scanner.d.ts +20 -0
- package/dist/scanners/remote/port-scanner.d.ts.map +1 -0
- package/dist/scanners/remote/port-scanner.js +65 -0
- package/dist/scanners/remote/port-scanner.js.map +1 -0
- package/dist/scanners/remote/ssl-checker.d.ts +24 -0
- package/dist/scanners/remote/ssl-checker.d.ts.map +1 -0
- package/dist/scanners/remote/ssl-checker.js +109 -0
- package/dist/scanners/remote/ssl-checker.js.map +1 -0
- package/dist/scanners/scheduled-tasks.d.ts +26 -0
- package/dist/scanners/scheduled-tasks.d.ts.map +1 -0
- package/dist/scanners/scheduled-tasks.js +299 -0
- package/dist/scanners/scheduled-tasks.js.map +1 -0
- package/dist/scanners/shared-folders.d.ts +25 -0
- package/dist/scanners/shared-folders.d.ts.map +1 -0
- package/dist/scanners/shared-folders.js +310 -0
- package/dist/scanners/shared-folders.js.map +1 -0
- package/dist/scanners/ssl-checker.d.ts +27 -0
- package/dist/scanners/ssl-checker.d.ts.map +1 -0
- package/dist/scanners/ssl-checker.js +197 -0
- package/dist/scanners/ssl-checker.js.map +1 -0
- package/dist/scanners/types.d.ts +140 -0
- package/dist/scanners/types.d.ts.map +1 -0
- package/dist/scanners/types.js +31 -0
- package/dist/scanners/types.js.map +1 -0
- 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
|
+
}
|