DefaceMeter is a small, static, browser-based prototype that estimates the likelihood of a website defacement given a JSON vulnerability report.
You upload a report (see sample_report.json), optionally tune the weights of three factors, and DefaceMeter calculates:
- A per-vulnerability contribution score
Vi - An aggregate probability that at least one vulnerability could plausibly lead to a defacement outcome (using an independence approximation)
- A single “DefacementScore” shown as a percentage gauge
This project is intentionally lightweight: it runs entirely in the browser with plain HTML/CSS/JavaScript and requires no build step.
index.html— UI layout (upload panel, processing panel, results panel)styles.css— visual styling (glass panels, gauge, table, loader)app.js— scoring model + UI logicsample_report.json— an example input file you can use to demo the tool
DefaceMeter builds a probability from three normalized factors per vulnerability:
Derived from CVSS:
C = clamp(cvss, 0..10) / 10
So a CVSS 10.0 maps to C = 1.0 and CVSS 5.0 maps to C = 0.5.
A simple heuristic based on exploit flags:
- If
public_exploit=trueandmetasploit=true→E = 1.0 - Else if
poc=true→E = 0.8 - Else if
complex_poc=true→E = 0.5 - Else →
E = 0.05
If the exploit object is missing or invalid, DefaceMeter defaults to 0.05.
Normalizes a vulnerability’s historical usage/frequency (historical.count) relative to the maximum count in the uploaded dataset:
H = log(1 + count) / log(1 + maxCount)
If counts are missing or invalid, DefaceMeter uses 0.05.
Each vulnerability gets a weighted score:
Vi = wC * C + wE * E + wH * H
Weights are user-adjustable (C, E, H) and are automatically normalized to sum to 1.
To convert multiple Vi values into one number, DefaceMeter uses an independent-event approximation:
RawProb = 1 - ∏(1 - Vi)DefacementScore = 100 * RawProb
This is why the UI warns: “Interpret cautiously: This is a synthesized probability using independent event approximation.”
DefaceMeter expects JSON shaped like this (matching the schema shown in the UI):
{
"meta": { "generated": "ISO8601", "scope": "string", "tool": "string" },
"weights": { "C": 0.5, "E": 0.3, "H": 0.2 },
"vulnerabilities": [
{
"id": "string",
"title": "string",
"cvss": 9.8,
"exploit": {
"public_exploit": true,
"metasploit": false,
"poc": true,
"complex_poc": false
},
"historical": { "count": 37, "class": "SQL Injection" },
"category": "Injection",
"asset": "api.example.com",
"description": "Human readable...",
"references": ["https://..."],
"tags": ["critical", "webapp", "sqli"]
}
]
}Notes:
weightsin the JSON is optional; the UI also allows overriding weights.historical.countis used for the historical normalization.- Extra fields are ignored by the scoring logic (but may appear in the raw JSON viewer).
Because the UI fetches sample_report.json for the “Download Sample JSON” link, the simplest way to run is with a tiny local web server.
cd /path/to/defacemeter
python3 -m http.server 8000Then open:
Serve the folder with any static server of your choice and open the served URL in your browser.
- Open the app in your browser.
- Upload a vulnerability report JSON (or use the link to download
sample_report.json). - (Optional) Adjust
C,E,Hweights and click Normalize. - Review the results:
- Gauge = aggregate likelihood percent
- Table = per-vulnerability
C,E,H, andVi - Insights = short auto-generated guidance based on score and top contributors
- This is a prototype scoring model, not a guarantee or a forensic conclusion.
- The aggregate probability uses an independence approximation; in real environments, vulnerabilities and attacker behavior are often correlated.
Vivalues are heuristics derived from CVSS + exploit flags + dataset-local historical normalization; they are best used for relative prioritization within the same report.
If you want to change the model, the core functions are in app.js:
computeC(cvss)computeE(exploit)computeH(count, maxCount)computeScores(data, overrideWeights)
The UI uses the returned contributions list to render the table and generate top-contributor insights.