Skip to content

Read your first scan

You have cxg installed. This page runs one scan against a target on your own machine and reads back everything it produced: the summary on your terminal, the five severity counts, and the JSON file it wrote to disk. By the end you can tell a real finding from a clean run, and you know where to look for the detail.

  • cxg installed and on your PATH. See Installation.
  • Templates fetched. Run cxg template update if you have not.
  • Python 3, to serve the demo target.
  1. Serve a directory that has a finding in it: an exposed listing.

    Terminal window
    mkdir -p cxg-firstscan/data
    cd cxg-firstscan
    echo "customer-export.csv placeholder" > data/customer-export.csv
    python3 -m http.server 8000 --bind 127.0.0.1

    Leave it running. Open a second terminal in the same directory.

  2. Scan it with one template.

    Terminal window
    cxg scan --scope http://127.0.0.1:8000 --templates directory-listing-common-paths
    ════════════════════════════════════════════════════════════════════════════════
    Scan Summary
    ════════════════════════════════════════════════════════════════════════════════
    Scan ID: fc29c609-b89c-4fe2-9855-5382348a72dd
    Duration: 0.01s
    Targets Scanned: 1
    Templates Executed: 1
    Findings by Severity:
    CRITICAL: 0
    HIGH: 0
    MEDIUM: 1
    LOW: 0
    INFO: 0
    TOTAL: 1
    ════════════════════════════════════════════════════════════════════════════════

    MEDIUM: 1 is the line that proves it worked. Scan ID and Duration differ on every run.

The block splits into two halves.

The top four lines are what ran. Targets Scanned and Templates Executed count what cxg actually reached. A scan that finds no target still prints Templates Executed: 0, which is how you catch a target that was never up.

Findings by Severity tallies the findings by the severity each one carries. A finding’s severity is set by its template’s author, not by the scan. The five levels, highest first:

Level What the author is saying
CRITICAL Exploitable now, high impact. Act before anything else.
HIGH Serious, likely exploitable.
MEDIUM Real exposure, lower impact or harder to reach. The demo finding is here.
LOW Minor, or needs an unlikely precondition.
INFO Not a weakness: context, fingerprinting, or a template reporting that it found nothing.

INFO earns a second look. Some templates emit an INFO finding to say the check ran and matched nothing, so a non-zero INFO count is not evidence of a problem, and TOTAL counts those lines too.

The summary is the headline. The finding itself, with its request, response, and evidence, goes to scan-results.json in the working directory.

Terminal window
python3 -m json.tool scan-results.json
{
"scan_id": "fc29c609-b89c-4fe2-9855-5382348a72dd",
"started_at": "2026-08-13T07:40:15.286395Z",
"completed_at": "2026-08-13T07:40:15.294462Z",
"findings": [
{
"id": "b753911e-f076-4db8-b200-db030ac58796",
"target": "http://127.0.0.1:8000",
"template_id": "directory-listing-common-paths",
"severity": "medium",
"confidence": 85,
"title": "Directory Listing Exposure (Common Paths)",
"evidence": {
"request": "GET http://127.0.0.1:8000/data/\n",

Truncated after the first evidence line. The block continues with the full response body, matched_patterns, and a data object, and the file ends with statistics and errors.

Three things are worth knowing about this file:

  • evidence.response holds the whole response body. That is what makes a finding auditable after the run, because you can see exactly what cxg matched on.
  • The keys inside evidence.data come out in a different order every run. Read that object by key, never by position.
  • cvss_score, remediation, and cwe_ids are often empty. They come from the template, and not every template sets them.

Change where results go, and in what format

Section titled “Change where results go, and in what format”

--output sets the basename and --output-format the format. The default is scan-results.json.

Terminal window
cxg scan --scope http://127.0.0.1:8000 --templates directory-listing-common-paths \
--output first-scan --output-format json,sarif

That writes first-scan.json and first-scan.sarif. Five formats exist: json, csv, sarif, html, and markdown. You can ask for several at once. The extension you type on --output is replaced by each format’s own, so --output report.txt --output-format json still writes report.json.

Stop the server with Ctrl+C, then remove the directory.

Terminal window
cd ..
rm -rf cxg-firstscan
  • The server is not running, or not on 8000. Check with curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8000/. You want 200.
  • data/ is in the wrong place. It must sit inside the directory you served.
  • The template is missing. cxg search --query "directory listing" should find it; if not, run cxg template update.

A scan that reaches nothing still exits 0. Add -v to see the warnings behind a silent zero.