Scan a target
A scan is three decisions: what to point at, which templates to run, and what to
write out. This guide works through each against a target on your own machine,
and calls out the flags whose behaviour does not match their --help text.
flowchart TB
TP["templates on disk:<br/>local, user, system"] --> FI["filter by id, tag, severity,<br/>or language, then exclude"]
SC["--scope: URL, host,<br/>domain, CIDR, @file"] --> TG["the targets to hit"]
FI --> RUN["every selected template runs<br/>against every target"]
TG --> RUN
RUN --> OUT["scan-results.json<br/>and any other format"]
RUN --> EC["an exit code"]
class OUT,EC emphasis
Before you start
Section titled “Before you start”cxginstalled. See Installation. You have also read your first scan.- Python 3, for the demo targets.
Set up two targets
Section titled “Set up two targets”Two servers, so scope selection has something to select between.
-
Serve two directories, each with an exposed listing.
Terminal window mkdir -p cxg-scan/a/data cxg-scan/b/datacd cxg-scanecho x > a/data/export.csvecho y > b/data/export.csv(cd a && python3 -m http.server 8000 --bind 127.0.0.1 &)(cd b && python3 -m http.server 8001 --bind 127.0.0.1 &) -
Confirm both answer.
Terminal window curl -s -o /dev/null -w '8000 %{http_code}\n' http://127.0.0.1:8000/curl -s -o /dev/null -w '8001 %{http_code}\n' http://127.0.0.1:8001/8000 2008001 200
Choose a scope
Section titled “Choose a scope”--scope is one flag that reads several shapes. A single URL is the simplest:
cxg scan --scope http://127.0.0.1:8000 --templates directory-listing-common-pathsA comma-separated list scans each entry:
cxg scan --scope http://127.0.0.1:8000,http://127.0.0.1:8001 \ --templates directory-listing-common-paths Targets Scanned: 2... MEDIUM: 2
TOTAL: 2For more than a couple of targets, put one per line in a file and pass it with
@:
printf 'http://127.0.0.1:8000\nhttp://127.0.0.1:8001\n' > targets.txtcxg scan --scope @targets.txt --templates directory-listing-common-paths Targets Scanned: 2--scope also accepts bare hosts, domains, and CIDR blocks like
192.168.1.0/24. For those, cxg scans each template’s own default ports.
Narrow the templates
Section titled “Narrow the templates”Running one template by ID is the tightest scope, and what the examples above use. To run a set, filter instead.
By tag:
cxg scan --scope http://127.0.0.1:8000 --tags exposureBy severity, one value or the flag repeated:
cxg scan --scope http://127.0.0.1:8000 --severity highcxg scan --scope http://127.0.0.1:8000 --severity high --severity critical--severity selects which templates run. It does not change the severity each
finding reports. See reading a scan.
Exclude by exact ID
Section titled “Exclude by exact ID”To drop a specific template from a filtered run, name it in full:
cxg scan --scope http://127.0.0.1:8000 --tags exposure \ --exclude-templates directory-listing-common-paths TOTAL: 0Write the output your pipeline needs
Section titled “Write the output your pipeline needs”--output sets the basename; --output-format sets one or more formats.
cxg scan --scope http://127.0.0.1:8000 --templates directory-listing-common-paths \ --output scan --output-format json,sarif,html,markdown,csvThat writes scan.json, scan.sarif, scan.html, scan.markdown, and
scan.csv from one run. Pick by consumer:
| Format | For |
|---|---|
json |
Automation. The full finding, evidence included. The default. |
sarif |
CI code-scanning: GitHub Advanced Security, VS Code. |
csv |
A spreadsheet: one row per finding, no evidence body. |
html |
A human reading a report. |
markdown |
Dropping into a doc or a ticket. |
The extension you type is replaced by the format’s own, so
--output report.txt --output-format json writes report.json.
Check what the exit code tells you
Section titled “Check what the exit code tells you”In a pipeline, the exit status matters as much as the file:
| Situation | Exit |
|---|---|
| Scan ran, with findings, with none, or against a dead port | 0 |
| A template ID or filter matched nothing to run | 1 |
A scan that reaches an unresponsive target still exits 0 with TOTAL: 0. A
non-zero exit here means cxg could not assemble a run, not that the target is
clean, so do not treat 0 as “secure”. Add -v to see per-template warnings.
Clean up
Section titled “Clean up”kill %1 %2 2>/dev/nullcd ..rm -rf cxg-scanWhat to change next
Section titled “What to change next”- Tune the load.
--rate-limit,--parallel-targets, and--parallel-templatescontrol how hard a scan hits a target.--safedrops the checks that can disrupt a production system. - Pass context to a template.
--context '{"param_name":"id"}'feeds JSON to templates that need parameters. Many auth-class templates report anINFOline telling you exactly which context keys they want.
Related
Section titled “Related”- Read your first scan covers the summary and the results file.
cxg scanlists every flag, including the ones marked[NOT IMPLEMENTED].

