report, serve and new-marker¶
Three small utilities that work on what is already on disk. report renders a
stored run in another format. serve opens a local viewer over the run
history. new-marker prints a marker. None of them sends a request to your
target.
veridor report¶
report turns a run JSON document into SARIF, JUnit XML, a GitLab SAST
report, a GitLab Code Quality report or Markdown, without repeating the
probes. It also renders a drift report as Markdown.
Use it when the run is finished and you need a format you did not ask for at
the time, or a second copy for another system. To write reports during the
run itself, use veridor run --report FORMAT=PATH, which is repeatable; see
writing them from the run.
Flags¶
| Flag | Does |
|---|---|
--from-run RUN.json |
the run JSON veridor run --json wrote. --input is the older spelling |
--from-drift DRIFT.json |
a drift report written by veridor map --baseline … --drift |
--format FORMAT |
sarif, junit, gitlab-sast, codequality or markdown. Required unless --sarif is given |
--output PATH |
where to write. - or no --output writes to stdout |
--sarif PATH |
the older spelling of --format sarif --output PATH |
Exactly one of --from-run and --from-drift is required.
Run it¶
run.json is the run document from the
capsule page: one confirmed finding, gate exit 1.
veridor report --from-run run.json --format junit --output out.junit
veridor report --from-run run.json --format markdown
Wrote JUnit report to out.junit
## Veridor run `20261110T043547Z-dab5f6`
**Gate failed (exit 1):** 1 finding about the target.
Policy: `--fail-on new+confirmed`.
Target: `http://127.0.0.1:18805`. Config: `veridor.capsule-demo.json`.
| Probes | Matched their declaration | Vulnerable | Unexpected denial | Inconclusive | New | Unchanged | Resolved |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| 6 | 5 | 1 | 0 | 0 | 1 | 0 | 0 |
Evidence: 1 confirmed, 0 suspected, 0 ungraded.
#### Gate reasons
- `findings` (exit 1): 1 finding about the target.
…
Both exit 0. A file output prints Wrote <label> report to PATH; the labels
are SARIF, JUnit, GitLab SAST, GitLab Code Quality and Markdown.
The JUnit file records the gate as properties:
<testsuites name="veridor" tests="7" failures="2" errors="0" skipped="0" time="0.006">
<testsuite name="veridor" tests="7" failures="2" errors="0" skipped="0" time="0.006" timestamp="2026-11-10T04:35:47">
<properties>
<property name="veridor.run_id" value="20261110T043547Z-dab5f6" />
…
<property name="veridor.gate.exit_code" value="1" />
<property name="veridor.gate.fail_on" value="new+confirmed" />
…
The gate travels, except in SARIF¶
veridor run records the exit-code decision in the run document as a gate
object. Every format except SARIF renders it, so a run that exited 3 because
nothing was answered never renders as a pass. SARIF carries findings only: a
run that exited 3 for an unproven denial or an unclean teardown renders as
zero results, the same as a run that exited 0. For SARIF, read the job's exit
code. The reason codes and each format's mapping are on
reports and
SARIF and code scanning.
Drift renders to Markdown only¶
## Veridor access-matrix drift
**0 change(s), 0 that mean more access than the baseline.** A change is an observation, not a finding: …
This document does not record the `--fail-on-drift` policy or the exit code; the job's exit code is the gate.
…
drift.json came from two veridor map runs of fixtures/veridor.map-demo.json
against the demo target, the second with --baseline and --drift. Any other
format is refused, because the other four would present a drift as a finding:
veridor: a drift report renders to --format markdown only, not sarif: drift is an observation, never a finding, and SARIF, JUnit, GitLab SAST and Code Quality would all present it as one
Refusals¶
Each exits 2 and writes nothing:
| Command | Message |
|---|---|
report --from-run run.json |
report needs --format, one of sarif, junit, gitlab-sast, codequality, markdown |
report --format sarif |
report needs exactly one input: --from-run RUN.json (the run JSON …) or --from-drift DRIFT.json |
report --from-run run.json --format junit --output run.json |
--output must not overwrite the input run |
report --from-run run.json --sarif x.sarif --format sarif |
--sarif PATH is the older spelling of --format sarif --output PATH; pass one form or the other, not both |
A file that is not a Veridor run, or one with a field of the wrong type, is also refused; see rendering them later.
What it does not do¶
- It does not repeat a probe or change the exit code the run produced. It renders what the document records.
- It does not render a drift as a finding, and it renders nothing other than a run or a drift document.
veridor serve¶
serve opens a local web viewer over the run history directory: runs, maps
(with drift when there was a baseline) and mutation reports, each in its own
tab. What it guards against is on
safety posture.
Flags¶
| Flag | Default | Does |
|---|---|---|
--output-dir DIR |
.veridor |
the run history directory to read |
--host HOST |
127.0.0.1 |
the address to bind. Anything other than 127.0.0.1, localhost or ::1 is refused without the next flag |
--i-understand-this-is-unauthenticated |
off | required to bind any other address |
--port PORT |
8787 |
the port to listen on |
Run it¶
It runs until stopped. Stopped with SIGTERM, it printed
veridor: stopped by SIGTERM before the command finished (exit 143).
Read-only¶
The viewer answers GET only, and only for its own pages and these JSON
endpoints: /api/runs, /api/runs/<id>, /api/maps, /api/maps/<id>,
/api/mutations and /api/mutations/<id>. Each reads one kind of document
from fixed directories under --output-dir (runs/ for runs; matrix/,
blast-radius/, candidates/ and drift/ for maps; mutation/ for
mutation reports), so the runs endpoint can never return a map. It writes
nothing. Measured against the server above:
| Request | Status |
|---|---|
GET /api/runs |
200, a JSON object whose runs key holds the list of run summaries |
POST /api/runs |
501 |
GET /api/runs with Host: evil.example |
421 |
GET /api/runs/..%2f..%2fveridor.json |
400 |
Every response carries Content-Security-Policy: default-src 'self';
frame-ancestors 'none', Referrer-Policy: no-referrer,
X-Content-Type-Options: nosniff and Cache-Control: no-store. The pages and
scripts are served from the installed package, never from the history
directory.
No authentication¶
The viewer has no login. Binding anything but loopback is refused:
veridor: --host 0.0.0.0 binds an address other than loopback, and the viewer has no authentication: every run document it serves -- target URLs, finding messages, config paths -- becomes readable by anything that can reach that address. Pass --i-understand-this-is-unauthenticated if that is what you want, or leave --host at 127.0.0.1 and use an SSH tunnel.
Exit code 2. To read the history from another machine, leave --host at
127.0.0.1 and use an SSH tunnel.
What it does not do¶
- It does not run probes, write files, or change a run document.
- It does not authenticate anyone, and it is not a shared run history for a team.
- It does not load anything from another origin: no web font, CDN or tracker.
veridor new-marker¶
new-marker prints one fresh marker and exits 0. It takes no flags.
Each call prints a new value: vdr- followed by 24 random URL-safe
characters, checked against the same validation a configured marker must pass.
Plant it in data that belongs to one identity, then declare it as that
identity's marker. The rules, and what a marker does and does not prove,
are in marker.
It does not plant the marker anywhere, and it does not check that the value is unique to one identity's data. Both are up to you.
Exit codes¶
| Command | 0 |
2 |
|---|---|---|
report |
the report was written | refused, or the input did not load |
serve |
the server returned normally | refused before binding, for example a non-loopback --host |
new-marker |
a marker was printed | not used |
70, 130 and 143 mean the same as for
every command. serve runs until
stopped, so Ctrl-C ends it with 130 and SIGTERM with 143.