-
Notifications
You must be signed in to change notification settings - Fork 0
interpreting results
This guide explains how to read Purplemet analysis results, prioritize remediation, and configure security gates for your context.
Every analysis returns a rating (A, B, C, D, E, F) and classifies issues by severity (CRITICAL, HIGH, MEDIUM, LOW, INFO).
Both are computed and defined by the Purplemet platform — the CLI only consumes these values. Refer to the official Purplemet documentation for authoritative definitions, scoring rules, and examples.
Four output formats are available, each designed for a different audience:
- Human — developer in a terminal (default)
- JSON — CI/CD pipelines and automated processing
- SARIF — security tool integrations (GitHub Code Scanning, Defect Dojo, VS Code)
- HTML — everyone (stakeholders, managers, auditors, clients)
The terminal output shows a color-coded summary. The format below is illustrative — actual values (rating, severities, CVE counts, technology categories, gate messages) come from the Purplemet API:
Purplemet • https://your-app.com • DONE
────────────────────────────────────────────────────────────
Analysis: <uuid>
Title: <site title>
IP: <origin ip>
HTTP: <status code>
Duration: <duration>
Rating: <A-F> (score: <0-100>)
Issues: <total> — broken down by severity
CVEs: <count>
Tech: <count> technologies (<unsafe> unsafe)
WAF: <WAF product or none>
Issues (...)
────────────────────────────────────────────────────────────
<SEVERITY> <name or CVE id>
<type> • CWE-<id> • CVSS <score> • EPSS <pct>
<description>
...
Technologies (...)
────────────────────────────────────────────────────────────
<name> <version> <category> <CVE count if any>
Certificates
────────────────────────────────────────────────────────────
<subject> expires <date> (<days> left)
Gates (N configured)
────────────────────────────────────────────────────────────
✓ <gate> passed
✗ <gate> failed
<failure message>
X passed, Y failed / N gates
The JSON output is designed for CI/CD pipelines and automated processing. JSON goes to stdout; progress updates and gate summaries go to stderr.
During analysis, the CLI emits periodic status updates to stderr so CI logs show progress:
[purplemet] Waiting for analysis...
[purplemet] Scanning — 25% (30s)
[purplemet] Analyzing — 75% (1m15s)
[purplemet] Analysis complete (2m05s)
purplemet-cli analyze https://your-app.com --jsonTop-level structure:
| Field | Type | Description |
|---|---|---|
meta.version |
string | CLI version that generated the report |
meta.timestamp |
string | ISO 8601 timestamp |
analysis |
object | Full analysis data (see below) |
gates |
object | Per-gate evaluation results |
ignoredCount |
int | Number of IGNORED issues excluded from analysis.issues (always present, 0 when none) |
error |
string | Error message (only on failure) |
Fields are omitted when empty. The JSON is encoded with
omitempty: a field appears only when it holds a non-zero / non-empty value. A trivial site (no CVEs, no end-of-life technology, no exposed services) therefore emits a subset of the fields below — e.g.cveCnt,kevCntandunsafeCntare absent when0, andcertificates/serviceswhen empty. The tables below list the key fields the CLI emits, not a guaranteed-present set.
analysis object — key fields:
| Field | Type | Description |
|---|---|---|
id |
string | Analysis UUID |
site.id |
string | Site UUID |
url |
string | Analyzed URL |
status |
string |
DONE, ERROR, WARNING, ABORTED
|
rating |
string | Letter grade A–F |
score |
int | Numeric score (0–100, lower is better) |
issueCnt |
int | Total issue count |
issueCnts |
object | {"CRITICAL": 0, "HIGH": 2, "MEDIUM": 3, ...} |
cveCnt |
int | Number of CVEs |
kevCnt |
int | CISA Known Exploited Vulnerabilities count |
technologyCnt |
int | Technologies detected |
unsafeCnt |
int | Unsafe components count |
waf |
string | WAF product name (empty if none) |
duration |
string | ISO 8601 duration |
remoteIp |
string | Origin IP address |
httpResponseCode |
int | HTTP status code |
issues |
array | Detailed issue list |
technologies |
array | Technology details |
certificates |
array | SSL certificate details |
services |
array | Exposed services |
issues[] — each issue:
| Field | Type | Description |
|---|---|---|
id |
string | Issue ID |
severity |
string |
CRITICAL, HIGH, MEDIUM, LOW, INFO
|
type |
string | Category: SSL_TLS_PROTOCOLS, CERTIFICATES, HTTP_HEADERS, COOKIES, etc. |
name |
string | CVE identifier or vulnerability name |
description |
string | Detailed description |
reference |
string | External reference URL |
cweId |
int | CWE number |
cweName |
string | CWE name |
exploitMaturity |
string |
ATTACKED if actively exploited |
status |
string |
OPEN, FIXED, REJECTED, IGNORED
|
weight |
int | Internal weight used to compute the score |
technology.name |
string | Affected technology |
technology.version |
string | Affected version |
details.cvss3Score |
float | CVSS v3 score (0–10) |
details.cvss3Vector |
string | CVSS v3 vector string |
details.epssScore |
float | EPSS score (0–1) |
details.epssPercentile |
string | EPSS percentile |
details.cisaAdditionDate |
string | Date added to CISA KEV catalog |
details.cisaRequiredAction |
string | CISA recommended action |
technologies[] — each technology:
| Field | Type | Description |
|---|---|---|
id |
string | Technology UUID |
name |
string | Product name |
version |
string | Detected version |
category |
string | Technology category as defined by the Purplemet platform |
cveCnt |
int | Known CVE count |
endOfLife |
int | End-of-life date as a unix-ms timestamp (omitted when the component is not end-of-life) |
latestVersion |
string | Latest available version |
ossfScorecard.score |
float | OpenSSF Scorecard score (0–10) |
gates object:
Each gate key (e.g. severity, rating, cvss, eol, waf) maps to:
| Field | Type | Description |
|---|---|---|
name |
string | Gate identifier |
passed |
bool |
true if gate passed or was skipped |
skipped |
bool |
true if gate was not enabled |
message |
string | Failure reason (empty if passed) |
Gate summary on stderr (CI-friendly):
In JSON/SARIF mode, the CLI also prints a human-readable gate summary to stderr so CI logs show which gates failed without parsing JSON:
[purplemet] FAILED severity: severity gate: 1 critical (threshold: high)
[purplemet] FAILED eol: EOL gate: 2 end-of-life component(s) (jQuery 2.1.4, PHP 7.4)
[purplemet] 2/4 gate(s) failed
Example — parsing gates in CI:
# Check if any gate failed
FAILED=$(echo "$RESULT" | jq '[.gates[] | select(.skipped == false and .passed == false)] | length')
if [ "$FAILED" -gt 0 ]; then
echo "Failed gates:"
echo "$RESULT" | jq -r '.gates[] | select(.passed == false and .skipped == false) | " \(.name): \(.message)"'
fiSARIF 2.1.0 output is compatible with GitHub Code Scanning, Azure DevOps Advanced Security, and any SARIF viewer.
purplemet-cli analyze https://your-app.com --format sarif --output-file results.sarifStructure:
- Each unique issue type becomes a SARIF rule with its severity, CWE, and description
- Each finding becomes a SARIF result referencing that rule
- The analyzed URL is used as the artifact location
- Analysis metadata and gate results are in
runs[].properties
Severity mapping to SARIF levels:
| Purplemet Severity | SARIF Level |
|---|---|
| Critical, High | error |
| Medium | warning |
| Low, Info | note |
runs[].properties — analysis metadata:
| Field | Type | Description |
|---|---|---|
rating |
string | Letter grade A–F |
score |
int | Numeric score (0–100, lower is better) |
url |
string | Analyzed URL |
issueCnt |
int | Total issue count |
issueCnts |
object | Issues by severity |
cveCnt |
int | CVE count |
kevCnt |
int | KEV count |
gates |
object | Per-gate pass/fail results (only configured gates) |
These custom properties follow the SARIF 2.1.0 specification and are accessible by tools like GitHub Code Scanning, Defect Dojo, and any SARIF viewer that supports properties.
Generates a standalone HTML report suitable for sharing with stakeholders, archiving as audit evidence, or publishing as a CI/CD pipeline artifact.
purplemet-cli analyze https://your-app.com --format html --output-file report.htmlThe report is a self-contained .html file (no external dependencies) with a dark theme. It includes:
- Security rating with color-coded badge (A–F)
- Issue summary by severity (critical, high, medium, low, info)
- Issue details table — severity, name, type, technology, CVSS, EPSS, CWE, description
- Technologies table — name, version, category, flags (EOL, CVE count, latest version)
- Certificates table — common name, issuer, expiry date, status
- Sensitive services table — service name, port, protocol, IP address
- Gates summary — configured gates with pass/fail status and failure messages
- Overview metrics — total issues, CVE count, technology count, KEV count
- Analysis details — ID, status, duration, WAF, remote IP, HTTP code, redirect URL, CLI version
General security guidance — not Purplemet-specific. Refer to your organization's policies and the official Purplemet documentation for authoritative remediation workflows.
Common industry signals for prioritization:
- CISA KEV catalog — vulnerabilities listed by CISA as actively exploited
- EPSS score — probability of exploitation in the next 30 days (maintained by FIRST.org)
- CVSS score — severity rating of a vulnerability (maintained by FIRST.org)
- Public exploit availability
- End-of-life status of affected components
Combine these with your context (internal vs public, data sensitivity, compensating controls) to set remediation priorities.
- CVSS measures the severity of a vulnerability (how bad it is if exploited)
- EPSS measures the probability of exploitation (how likely it will be exploited in the wild)
A high CVSS + high EPSS issue is typically the highest priority. See first.org/cvss and first.org/epss for authoritative definitions.
Start strict to catch issues before production:
purplemet-cli analyze https://staging.example.com --json \
--fail-on-severity high \
--fail-on-eol \
--fail-on-kev \
--fail-on-ssl \
--fail-on-certAdd broader checks for runtime concerns:
purplemet-cli analyze https://app.example.com --json \
--fail-on-severity high \
--fail-on-eol \
--fail-on-kev \
--fail-on-active-exploits \
--fail-on-cert-expiry 30 \
--require-waf \
--fail-on-sensitive-servicesCombine severity with specific policy gates:
purplemet-cli analyze https://app.example.com --json \
--fail-on-severity medium \
--fail-on-cvss 7.0 \
--fail-on-epss 0.5 \
--fail-on-eol \
--fail-on-ssl \
--fail-on-headers \
--fail-on-cookies \
--fail-on-ossf-score 5.0 \
--exclude-tech "php"Start permissive, tighten over time:
-
Week 1:
--fail-on-severity critical— block only critical issues -
Week 2:
--fail-on-severity high --fail-on-kev— add high severity + known exploits -
Month 2: Add
--fail-on-eol --fail-on-ssl --fail-on-cert -
Month 3: Add
--fail-on-headers --fail-on-cookies --require-waf
This avoids overwhelming teams with hundreds of findings on day one.
Use the diff command to compare two analyses and measure improvement:
purplemet-cli diff <analysisId1> <analysisId2> --site-id <siteId>Output shows the delta for rating, score, issues, CVEs, and technologies:
Rating: C → B
Score: 45 → 18 (-27)
Issues: 25 → 12 (-13)
CVEs: 5 → 1 (-4)
Use scheduled analyses (sites schedule or CI/CD cron) to monitor security posture continuously.