-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
122 lines (95 loc) · 2.73 KB
/
Copy pathapp.js
File metadata and controls
122 lines (95 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { parseCSP } from "./core/parser.js";
import { generateCSPReport } from "./core/report.js";
const textarea = document.getElementById("search");
const scoreEl = document.getElementById("score");
const levelEl = document.getElementById("level");
const sourcesEl = document.getElementById("sources");
const findingsEl = document.getElementById("findings");
const matchesEl = document.getElementById("matches");
const exportBtn = document.getElementById("exportBtn");
let gadgets = null;
let isLoaded = false;
/**
* Load database
*/
fetch("./data/gadgets.json")
.then(res => res.json())
.then(json => {
gadgets = json;
isLoaded = true;
})
.catch(err => {
console.error("Failed to load gadgets:", err);
gadgets = [];
isLoaded = false;
});
/**
* Render UI report
*/
function renderReport(report) {
scoreEl.textContent = `${report.score}/100`;
levelEl.textContent = report.level;
sourcesEl.textContent = report.summary.exposedSources;
findingsEl.innerHTML = report.findings.length
? report.findings.map(f => `
<li>
<strong>${f.severity}</strong> — ${f.directive}<br>
${f.issue}
</li>
`).join("")
: "<li>No issues found</li>";
matchesEl.innerHTML = report.matches.length
? report.matches.map(m => `
<li>
<strong>${m.domain}</strong><br>
<code>${m.payload}</code>
</li>
`).join("")
: "<li>No matches found</li>";
}
/**
* Live CSP analyzer
*/
function analyzeInput(value) {
if (!isLoaded || !gadgets) return;
const trimmed = value.trim();
if (!trimmed) {
scoreEl.textContent = "0/100";
levelEl.textContent = "-";
sourcesEl.textContent = "0";
findingsEl.innerHTML = "<li>No analysis yet</li>";
matchesEl.innerHTML = "<li>No matches yet</li>";
return;
}
const parsed = parseCSP(trimmed);
const report = generateCSPReport(parsed, gadgets);
renderReport(report);
}
/**
* Input listener (live analysis)
*/
textarea.addEventListener("input", (e) => {
analyzeInput(e.target.value);
});
/**
* Export CSP report
*/
exportBtn.addEventListener("click", () => {
const value = textarea.value;
if (!value || !value.trim()) return;
if (!gadgets) return;
const report = generateCSPReport(
parseCSP(value),
gadgets
);
const blob = new Blob(
[JSON.stringify(report, null, 2)],
{ type: "application/json" }
);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "csp-report.json";
a.click();
URL.revokeObjectURL(url);
});