vite-plugin-vue-security 1.2.0 → 1.4.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/LICENSE +21 -0
- package/index.js +206 -9
- package/package.json +9 -5
- package/vite.config.example.js +0 -28
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ereddate
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
|
|
4
|
-
// Import the security scanner with rule-based architecture
|
|
5
|
-
const { SecurityScanner } = require('vue-security-scanner
|
|
4
|
+
// Import the security scanner with rule-based architecture from npm package
|
|
5
|
+
const { SecurityScanner } = require('vue-security-scanner');
|
|
6
6
|
const IgnoreManager = require('vue-security-scanner/src/utils/ignore-manager');
|
|
7
|
+
const AdvancedReportGenerator = require('vue-security-scanner/src/reporting/advanced-report-generator');
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Vite Plugin for Vue Security Scanning
|
|
10
11
|
* Performs security scans on Vue.js projects during the build process
|
|
12
|
+
* with advanced semantic analysis and enterprise-grade reporting
|
|
11
13
|
*/
|
|
12
14
|
function vueSecurityPlugin(options = {}) {
|
|
13
15
|
const config = {
|
|
@@ -17,11 +19,21 @@ function vueSecurityPlugin(options = {}) {
|
|
|
17
19
|
reportLevel: 'warning', // 'error', 'warning', or 'info'
|
|
18
20
|
outputFile: null, // Optional output file for security report
|
|
19
21
|
exclude: [], // Patterns to exclude from scanning
|
|
22
|
+
|
|
23
|
+
// NEW: Advanced features
|
|
24
|
+
enableSemanticAnalysis: true, // Enable AST-based semantic analysis
|
|
25
|
+
enableDependencyScanning: true, // Enable dependency vulnerability scanning
|
|
26
|
+
enableAdvancedReport: false, // Enable advanced reporting with trends and compliance
|
|
27
|
+
reportHistoryPath: '.vue-security-reports', // Path for report history
|
|
28
|
+
complianceStandards: ['OWASP', 'GDPR', 'HIPAA', 'PCI-DSS', 'SOX'], // Compliance standards to check
|
|
29
|
+
|
|
20
30
|
...options
|
|
21
31
|
};
|
|
22
32
|
|
|
23
33
|
let scanner;
|
|
24
34
|
let ignoreManager;
|
|
35
|
+
let advancedReportGenerator;
|
|
36
|
+
let allVulnerabilities = []; // Collect all vulnerabilities for final report
|
|
25
37
|
|
|
26
38
|
return {
|
|
27
39
|
name: 'vue-security',
|
|
@@ -40,6 +52,15 @@ function vueSecurityPlugin(options = {}) {
|
|
|
40
52
|
output: {
|
|
41
53
|
showProgress: false, // Disable progress in build process
|
|
42
54
|
format: 'json'
|
|
55
|
+
},
|
|
56
|
+
performance: {
|
|
57
|
+
enableSemanticAnalysis: config.enableSemanticAnalysis,
|
|
58
|
+
enableNpmAudit: config.enableDependencyScanning,
|
|
59
|
+
enableVulnerabilityDB: config.enableDependencyScanning
|
|
60
|
+
},
|
|
61
|
+
compliance: {
|
|
62
|
+
enabled: config.enableAdvancedReport,
|
|
63
|
+
standards: config.complianceStandards
|
|
43
64
|
}
|
|
44
65
|
};
|
|
45
66
|
|
|
@@ -48,6 +69,14 @@ function vueSecurityPlugin(options = {}) {
|
|
|
48
69
|
|
|
49
70
|
// Initialize ignore manager
|
|
50
71
|
ignoreManager = new IgnoreManager(process.cwd());
|
|
72
|
+
|
|
73
|
+
// Initialize advanced report generator if enabled
|
|
74
|
+
if (config.enableAdvancedReport) {
|
|
75
|
+
advancedReportGenerator = new AdvancedReportGenerator();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Clear previous vulnerabilities
|
|
79
|
+
allVulnerabilities = [];
|
|
51
80
|
},
|
|
52
81
|
|
|
53
82
|
async transform(code, id) {
|
|
@@ -76,6 +105,9 @@ function vueSecurityPlugin(options = {}) {
|
|
|
76
105
|
const result = await scanner.scanFile(id, code);
|
|
77
106
|
const vulnerabilities = result.vulnerabilities || [];
|
|
78
107
|
|
|
108
|
+
// Collect vulnerabilities for final report
|
|
109
|
+
allVulnerabilities.push(...vulnerabilities);
|
|
110
|
+
|
|
79
111
|
// Report vulnerabilities
|
|
80
112
|
if (vulnerabilities.length > 0) {
|
|
81
113
|
vulnerabilities.forEach(vuln => {
|
|
@@ -89,6 +121,9 @@ function vueSecurityPlugin(options = {}) {
|
|
|
89
121
|
if (vuln.ruleId) {
|
|
90
122
|
message += `Rule: ${vuln.ruleId}\n`;
|
|
91
123
|
}
|
|
124
|
+
if (vuln.confidence) {
|
|
125
|
+
message += `Confidence: ${vuln.confidence}\n`;
|
|
126
|
+
}
|
|
92
127
|
|
|
93
128
|
// Log based on report level
|
|
94
129
|
if (config.reportLevel === 'error' ||
|
|
@@ -99,11 +134,6 @@ function vueSecurityPlugin(options = {}) {
|
|
|
99
134
|
}
|
|
100
135
|
});
|
|
101
136
|
|
|
102
|
-
// Optionally write to output file
|
|
103
|
-
if (config.outputFile) {
|
|
104
|
-
await writeSecurityReport(config.outputFile, vulnerabilities);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
137
|
// Fail build if configured to do so
|
|
108
138
|
if (config.failOnError) {
|
|
109
139
|
const highSeverityVulns = vulnerabilities.filter(v => v.severity === 'High' || v.severity === 'Critical');
|
|
@@ -128,6 +158,70 @@ function vueSecurityPlugin(options = {}) {
|
|
|
128
158
|
if (errors && errors.length > 0) {
|
|
129
159
|
console.log(`Build completed with ${errors.length} errors.`);
|
|
130
160
|
}
|
|
161
|
+
|
|
162
|
+
// Scan dependencies if enabled
|
|
163
|
+
if (config.enableDependencyScanning) {
|
|
164
|
+
try {
|
|
165
|
+
console.log('Scanning dependencies for vulnerabilities...');
|
|
166
|
+
const dependencyScanner = require('vue-security-scanner/src/analysis/dependency-scanner');
|
|
167
|
+
const depScanner = new dependencyScanner({
|
|
168
|
+
enableNpmAudit: true,
|
|
169
|
+
enableVulnerabilityDB: true
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const depVulns = await depScanner.scanDependencies(process.cwd());
|
|
173
|
+
allVulnerabilities.push(...depVulns);
|
|
174
|
+
|
|
175
|
+
console.log(`Found ${depVulns.length} dependency vulnerabilities.`);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.warn('Dependency scanning failed:', error.message);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Generate report
|
|
182
|
+
if (allVulnerabilities.length > 0) {
|
|
183
|
+
const scanResult = {
|
|
184
|
+
summary: {
|
|
185
|
+
totalVulnerabilities: allVulnerabilities.length,
|
|
186
|
+
critical: allVulnerabilities.filter(v => v.severity === 'Critical').length,
|
|
187
|
+
high: allVulnerabilities.filter(v => v.severity === 'High').length,
|
|
188
|
+
medium: allVulnerabilities.filter(v => v.severity === 'Medium').length,
|
|
189
|
+
low: allVulnerabilities.filter(v => v.severity === 'Low').length
|
|
190
|
+
},
|
|
191
|
+
vulnerabilities: allVulnerabilities,
|
|
192
|
+
scanInfo: {
|
|
193
|
+
scannerVersion: '1.3.0',
|
|
194
|
+
scanDate: new Date().toISOString(),
|
|
195
|
+
projectPath: process.cwd()
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Generate advanced report if enabled
|
|
200
|
+
if (config.enableAdvancedReport && advancedReportGenerator) {
|
|
201
|
+
try {
|
|
202
|
+
const advancedReport = advancedReportGenerator.generateAdvancedReport(scanResult, {
|
|
203
|
+
includeTrends: true,
|
|
204
|
+
includeCompliance: true,
|
|
205
|
+
historyPath: config.reportHistoryPath
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
if (config.outputFile) {
|
|
209
|
+
const reportPath = config.outputFile.endsWith('.html')
|
|
210
|
+
? config.outputFile
|
|
211
|
+
: config.outputFile.replace('.json', '.html');
|
|
212
|
+
|
|
213
|
+
await writeAdvancedReport(reportPath, advancedReport, 'html');
|
|
214
|
+
}
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.warn('Advanced report generation failed:', error.message);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Write basic report
|
|
221
|
+
if (config.outputFile) {
|
|
222
|
+
await writeSecurityReport(config.outputFile, allVulnerabilities, scanResult);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
131
225
|
}
|
|
132
226
|
};
|
|
133
227
|
}
|
|
@@ -135,11 +229,12 @@ function vueSecurityPlugin(options = {}) {
|
|
|
135
229
|
/**
|
|
136
230
|
* Write security report to file
|
|
137
231
|
*/
|
|
138
|
-
async function writeSecurityReport(outputFile, vulnerabilities) {
|
|
232
|
+
async function writeSecurityReport(outputFile, vulnerabilities, scanResult) {
|
|
139
233
|
try {
|
|
140
234
|
const report = {
|
|
141
235
|
timestamp: new Date().toISOString(),
|
|
142
236
|
totalVulnerabilities: vulnerabilities.length,
|
|
237
|
+
summary: scanResult.summary,
|
|
143
238
|
vulnerabilities: vulnerabilities.map(v => ({
|
|
144
239
|
type: v.type,
|
|
145
240
|
severity: v.severity,
|
|
@@ -147,7 +242,8 @@ async function writeSecurityReport(outputFile, vulnerabilities) {
|
|
|
147
242
|
line: v.line,
|
|
148
243
|
description: v.description,
|
|
149
244
|
recommendation: v.recommendation,
|
|
150
|
-
ruleId: v.ruleId
|
|
245
|
+
ruleId: v.ruleId,
|
|
246
|
+
confidence: v.confidence
|
|
151
247
|
}))
|
|
152
248
|
};
|
|
153
249
|
|
|
@@ -163,4 +259,105 @@ async function writeSecurityReport(outputFile, vulnerabilities) {
|
|
|
163
259
|
}
|
|
164
260
|
}
|
|
165
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Write advanced report to file (HTML or JSON)
|
|
264
|
+
*/
|
|
265
|
+
async function writeAdvancedReport(outputFile, advancedReport, format = 'json') {
|
|
266
|
+
try {
|
|
267
|
+
const dir = path.dirname(outputFile);
|
|
268
|
+
if (!fs.existsSync(dir)) {
|
|
269
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (format === 'html') {
|
|
273
|
+
const htmlReport = generateHTMLReport(advancedReport);
|
|
274
|
+
await fs.promises.writeFile(outputFile, htmlReport);
|
|
275
|
+
console.log(`Advanced HTML report written to ${outputFile}`);
|
|
276
|
+
} else {
|
|
277
|
+
await fs.promises.writeFile(outputFile, JSON.stringify(advancedReport, null, 2));
|
|
278
|
+
console.log(`Advanced JSON report written to ${outputFile}`);
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.error('Error writing advanced report:', error.message);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Generate HTML report from advanced report data
|
|
287
|
+
*/
|
|
288
|
+
function generateHTMLReport(report) {
|
|
289
|
+
return `<!DOCTYPE html>
|
|
290
|
+
<html lang="en">
|
|
291
|
+
<head>
|
|
292
|
+
<meta charset="UTF-8">
|
|
293
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
294
|
+
<title>Vue Security Scanner Report</title>
|
|
295
|
+
<style>
|
|
296
|
+
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
|
|
297
|
+
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; }
|
|
298
|
+
h1 { color: #333; }
|
|
299
|
+
.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 20px 0; }
|
|
300
|
+
.summary-card { padding: 15px; border-radius: 5px; color: white; }
|
|
301
|
+
.critical { background: #d32f2f; }
|
|
302
|
+
.high { background: #f57c00; }
|
|
303
|
+
.medium { background: #fbc02d; }
|
|
304
|
+
.low { background: #388e3c; }
|
|
305
|
+
.vulnerability { border: 1px solid #ddd; padding: 15px; margin: 10px 0; border-radius: 5px; }
|
|
306
|
+
.vulnerability.critical { border-left: 5px solid #d32f2f; }
|
|
307
|
+
.vulnerability.high { border-left: 5px solid #f57c00; }
|
|
308
|
+
.vulnerability.medium { border-left: 5px solid #fbc02d; }
|
|
309
|
+
.vulnerability.low { border-left: 5px solid #388e3c; }
|
|
310
|
+
.compliance { margin-top: 30px; padding: 15px; background: #e3f2fd; border-radius: 5px; }
|
|
311
|
+
</style>
|
|
312
|
+
</head>
|
|
313
|
+
<body>
|
|
314
|
+
<div class="container">
|
|
315
|
+
<h1>🔒 Vue Security Scanner Report</h1>
|
|
316
|
+
<p><strong>Generated:</strong> ${report.metadata.generatedAt}</p>
|
|
317
|
+
<p><strong>Scanner Version:</strong> ${report.metadata.scannerVersion}</p>
|
|
318
|
+
|
|
319
|
+
<div class="summary">
|
|
320
|
+
<div class="summary-card critical">
|
|
321
|
+
<h3>Critical</h3>
|
|
322
|
+
<p>${report.summary.critical || 0}</p>
|
|
323
|
+
</div>
|
|
324
|
+
<div class="summary-card high">
|
|
325
|
+
<h3>High</h3>
|
|
326
|
+
<p>${report.summary.high || 0}</p>
|
|
327
|
+
</div>
|
|
328
|
+
<div class="summary-card medium">
|
|
329
|
+
<h3>Medium</h3>
|
|
330
|
+
<p>${report.summary.medium || 0}</p>
|
|
331
|
+
</div>
|
|
332
|
+
<div class="summary-card low">
|
|
333
|
+
<h3>Low</h3>
|
|
334
|
+
<p>${report.summary.low || 0}</p>
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
|
|
338
|
+
${report.compliance ? `
|
|
339
|
+
<div class="compliance">
|
|
340
|
+
<h2>📋 Compliance Status</h2>
|
|
341
|
+
${Object.entries(report.compliance).map(([standard, status]) => `
|
|
342
|
+
<p><strong>${standard}:</strong> ${status.status === 'compliant' ? '✅ Compliant' : '⚠️ Non-compliant'}</p>
|
|
343
|
+
`).join('')}
|
|
344
|
+
</div>
|
|
345
|
+
` : ''}
|
|
346
|
+
|
|
347
|
+
<h2>Vulnerabilities (${report.vulnerabilities.length})</h2>
|
|
348
|
+
${report.vulnerabilities.map(vuln => `
|
|
349
|
+
<div class="vulnerability ${vuln.severity.toLowerCase()}">
|
|
350
|
+
<h3>${vuln.type} - ${vuln.severity}</h3>
|
|
351
|
+
<p><strong>File:</strong> ${vuln.file}</p>
|
|
352
|
+
<p><strong>Line:</strong> ${vuln.line}</p>
|
|
353
|
+
<p><strong>Description:</strong> ${vuln.description}</p>
|
|
354
|
+
<p><strong>Recommendation:</strong> ${vuln.recommendation}</p>
|
|
355
|
+
${vuln.confidence ? `<p><strong>Confidence:</strong> ${vuln.confidence}</p>` : ''}
|
|
356
|
+
</div>
|
|
357
|
+
`).join('')}
|
|
358
|
+
</div>
|
|
359
|
+
</body>
|
|
360
|
+
</html>`;
|
|
361
|
+
}
|
|
362
|
+
|
|
166
363
|
module.exports = vueSecurityPlugin;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-vue-security",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "A Vite plugin that performs security scans on Vue.js projects during the build process",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "A Vite plugin that performs security scans on Vue.js projects during the build process with advanced semantic analysis and enterprise-grade reporting",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -14,9 +14,13 @@
|
|
|
14
14
|
"scanner",
|
|
15
15
|
"vulnerability",
|
|
16
16
|
"xss",
|
|
17
|
-
"owasp"
|
|
17
|
+
"owasp",
|
|
18
|
+
"ast",
|
|
19
|
+
"semantic-analysis",
|
|
20
|
+
"dependency-scanning",
|
|
21
|
+
"compliance"
|
|
18
22
|
],
|
|
19
|
-
"author": "
|
|
23
|
+
"author": "ereddate",
|
|
20
24
|
"license": "MIT",
|
|
21
25
|
"peerDependencies": {
|
|
22
26
|
"vite": "^4.0.0 || ^5.0.0",
|
|
@@ -24,7 +28,7 @@
|
|
|
24
28
|
},
|
|
25
29
|
"dependencies": {
|
|
26
30
|
"cheerio": "^1.0.0-rc.12",
|
|
27
|
-
"vue-security-scanner": "^1.
|
|
31
|
+
"vue-security-scanner": "^1.4.0"
|
|
28
32
|
},
|
|
29
33
|
"repository": {
|
|
30
34
|
"type": "git",
|
package/vite.config.example.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// 示例:如何在Vite项目中使用Vue安全插件
|
|
2
|
-
// vite.config.js
|
|
3
|
-
|
|
4
|
-
import { defineConfig } from 'vite';
|
|
5
|
-
import vue from '@vitejs/plugin-vue';
|
|
6
|
-
import vueSecurityPlugin from 'vite-plugin-vue-security';
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
plugins: [
|
|
10
|
-
// 启用Vue安全扫描插件
|
|
11
|
-
vueSecurityPlugin({
|
|
12
|
-
enabled: true, // 启用安全扫描
|
|
13
|
-
failOnError: false, // 发现安全问题时不中断构建
|
|
14
|
-
reportLevel: 'warning', // 报告级别:'error', 'warning', 或 'info'
|
|
15
|
-
outputFile: './security-report.json', // 安全报告输出文件
|
|
16
|
-
exclude: [ // 排除扫描的文件模式
|
|
17
|
-
'node_modules',
|
|
18
|
-
'dist',
|
|
19
|
-
'public'
|
|
20
|
-
]
|
|
21
|
-
}),
|
|
22
|
-
|
|
23
|
-
// Vue插件
|
|
24
|
-
vue()
|
|
25
|
-
],
|
|
26
|
-
|
|
27
|
-
// 其他Vite配置...
|
|
28
|
-
});
|