-
Notifications
You must be signed in to change notification settings - Fork 0
configuration
Configuration is resolved in this order (first wins):
-
CLI flags (
--token,--json, etc.) -
Environment variables (
PURPLEMET_API_TOKEN, etc.) -
.envfile (auto-loaded from current directory) -
Project config (
.purplemet.yml— auto-discovered from CWD up to the project root) -
User config (
~/.purplemet/config.yml) - Defaults
| Variable | Description | Default |
|---|---|---|
PURPLEMET_API_TOKEN |
API authentication token | — |
PURPLEMET_BASE_URL |
API base URL | https://api.purplemet.com |
PURPLEMET_TIMEOUT |
Per-request HTTP timeout (ms) | 30000 |
PURPLEMET_WAIT_TIMEOUT |
Global polling timeout (ms) |
0 (unlimited) |
PURPLEMET_POLL_INTERVAL |
Polling interval (ms) | 10000 |
PURPLEMET_INSECURE |
Skip TLS verification (dev only) | false |
PURPLEMET_CONFIG |
Path to a project config file (default: auto-discover .purplemet.yml) |
— |
| Variable | Description | Default |
|---|---|---|
PURPLEMET_JSON |
JSON output mode | false |
PURPLEMET_VERBOSE |
Verbose logging to stderr | false |
PURPLEMET_NO_ADMIN_WARNING |
Suppress the warning shown when invoking admin-only commands (users, sessions, tokens) |
false |
PURPLEMET_NO_PAGER |
Disable the interactive paginator on list commands (TTY only) |
false |
| Variable | Description | Default |
|---|---|---|
PURPLEMET_FAIL_SEVERITY |
Severity gate: critical, high, medium, low, info
|
— (disabled) |
PURPLEMET_FAIL_RATING |
Rating gate: A, B, C, D, E, F
|
— (disabled) |
PURPLEMET_FAIL_CVSS |
Max CVSS score threshold (e.g. 9.0) |
0 (disabled) |
PURPLEMET_FAIL_ON_EOL |
Block on end-of-life components | false |
PURPLEMET_FAIL_ON_SSL |
Block on SSL/TLS protocol issues | false |
PURPLEMET_FAIL_ON_CERT |
Block on certificate issues | false |
PURPLEMET_FAIL_ON_HEADERS |
Block on HTTP security header issues (CSP, HSTS, X-Frame-Options) | false |
PURPLEMET_FAIL_ON_COOKIES |
Block on insecure cookies (HttpOnly, Secure, SameSite) | false |
PURPLEMET_FAIL_ON_UNSAFE |
Block on unsafe components | false |
PURPLEMET_FAIL_ON_KEV |
Block on CISA Known Exploited Vulnerabilities | false |
PURPLEMET_FAIL_ON_EPSS |
Max EPSS score threshold (e.g. 0.75, 0 = disabled) |
0 (disabled) |
PURPLEMET_FAIL_ON_ACTIVE_EXPLOITS |
Block on actively exploited vulnerabilities | false |
PURPLEMET_FAIL_ON_OSSF_SCORE |
Min OpenSSF Scorecard score (e.g. 5.0, 0 = disabled) |
0 (disabled) |
PURPLEMET_FAIL_ON_CERT_EXPIRY |
Block if certificate expires within N days |
0 (disabled) |
PURPLEMET_FAIL_ON_ISSUE_COUNT |
Block if total issues >= threshold |
0 (disabled) |
PURPLEMET_REQUIRE_WAF |
Block if no WAF detected | false |
PURPLEMET_FAIL_ON_SENSITIVE_SERVICES |
Block if sensitive services are exposed | false |
PURPLEMET_EXCLUDE_TECH |
Block if specified technologies detected (comma-separated) | — |
| Variable | Description |
|---|---|
PPM_CLOUD_UI_BASIC_USER |
Basic auth username (.dev. URLs only) |
PPM_CLOUD_UI_BASIC_PASS |
Basic auth password (.dev. URLs only) |
All list commands share the same set of pagination flags:
| Flag | Description | Default |
|---|---|---|
--limit |
Page size (1–1000) | 100 |
--offset |
Skip the first N items (mutually exclusive with --page) |
0 |
--page |
Page number, 1-indexed (mutually exclusive with --offset) |
0 (uses --offset) |
--all |
Fetch every page automatically (capped by --max) |
false |
--max |
Hard cap on the number of items fetched when --all is set |
10000 |
Default behavior depends on where the output goes:
-
Interactive terminal (TTY) with the pager enabled —
listcommands automatically fetch every page (capped by--max) so you can scroll through the entire result set with the pager's arrow keys. No need to pass--allmanually. -
Pipe / redirect /
--no-pager/--json/ CI — only the first page is fetched, exactly as you'd expect from a scriptable CLI. Use--all,--page N, or--offset Nto access more.
This split keeps both modes ergonomic: humans get effortless scrolling, scripts get predictable single-page output.
# In a terminal: auto-fetches everything, pager handles navigation
$ purplemet-cli sites list
…
Showing 142 of 142 site(s) — all pages fetched
# Piped: only the first page, with a hint to get more
$ purplemet-cli sites list | head
…
Showing 1-100 of 142 site(s) — page 1 of 2 (next: --page 2)
# Force the script behavior in a TTY
$ purplemet-cli sites list --no-pager
…
Showing 1-100 of 142 site(s) — page 1 of 2 (next: --page 2)
# Explicit page works the same in both modes
$ purplemet-cli sites list --page 2 --limit 20
…
Showing 21-40 of 142 site(s) — page 2 of 8 (next: --page 3)
# Cap the auto-fetch when you know the workspace is huge
$ purplemet-cli sites list --max 50
…
Showing 50 of 5000 site(s) — capped by --max, raise it to fetch more
--all cannot be combined with --page or --offset. Raise --max
when you legitimately need more than the default cap (every API call is
counted by the server, so a full fetch on a large workspace can be slow).
--query is evaluated across the whole result set, not just one page
(see Filtering with --query below), so you do
not need --all for a filter to find matches on later pages.
When stdout is an interactive terminal, list commands open a built-in
paginator that fetches one page at a time and lets you navigate
between pages with the keyboard. Each arrow-right keystroke triggers a
fresh API call for the next page — there is no pre-fetch, so a workspace
with thousands of items stays cheap to browse.
| Key | Action |
|---|---|
← / h / p
|
Previous page (refetched) |
→ / l / n
|
Next page (refetched) |
↑ / k
|
Scroll one line up within the current page |
↓ / j
|
Scroll one line down within the current page |
PgUp / b
|
Scroll one screen up within the current page |
PgDn / Space / f
|
Scroll one screen down within the current page |
g |
Jump to the top of page 1 |
G |
Jump to the bottom of the last page |
r |
Refetch the current page |
q / Esc / Ctrl+C
|
Quit |
The bottom status bar shows your position: page 3/8 rows 1-30/100 and
the available shortcuts. The terminal returns to its previous state on
exit (alternate screen buffer, like vim or less).
Auto-disables when:
-
--no-pageris set, orPURPLEMET_NO_PAGER=1 -
--jsonis set (machine output is never paginated) - stdout or stdin is not a TTY (pipe, redirect, CI logs)
-
--all,--page Nor--offset Nis set (those imply you want one specific result set, not interactive browsing)
Disable per-call or globally:
# One-off
purplemet-cli sites list --no-pager
# Globally (e.g. in CI)
export PURPLEMET_NO_PAGER=1--query is a global flag available on every list command (and any
command that returns a collection). It filters items client-side on
their JSON fields.
Syntax: key<op>value[,key<op>value,…] — multiple predicates are
AND-combined.
Operators:
| Op | Meaning | Example |
|---|---|---|
= |
Exact match (case-insensitive for strings) | severity=high |
!= |
Not equal | status!=IGNORED |
~= |
Contains (substring, case-insensitive) | url~=staging |
!~ |
Does not contain | name!~deprecated |
Keys are the JSON field names you see in --json output (e.g.
severity, status, url, role). Nested fields use the dotted form
exposed by the API (e.g. technology.name on issues).
--queryfilters across the whole account. Everylistcommand evaluates--queryover all items in the workspace, not just the page you land on, and reports the accurate filtered total — e.g.issues list --query "severity=high,status=OPEN"printsShowing 1-34 of 34 issue(s)even when those 34 are scattered across many pages. How it's resolved depends on what the API supports:
- Server-side push-down when the endpoint can filter on the field:
sites list --query "url~=staging"becomes a single/site?url=like(...)request, anddomains list --query "name~=corp"a single/domain?name=like(...)request. These are the only two server-side filterable fields (site.url,domain.name).- Client-side full scan for every other field/command: the CLI walks the pages and keeps the matches.
issues listalso folds its dedicated--severity/--statusflags into this scan.The exact total requires reading every page (the API can't count a filtered set it doesn't filter), so:
- One-shot output (piped, CI,
--no-pager) scans to completion and prints the exact total —Showing 1-100 of 1500 issue(s) — page 1 of 15. A sparse filter over a large account therefore costs more API calls; the scan is capped by--max(the footer says so when it hits the cap).- The interactive pager stays lazy — it fetches just enough to fill the screen and the total refines as you page, with a hint while it's still unknown. Press
→to keep going, or use--all/--no-pagerto force the exact count up front.
# Sites whose URL contains "staging"
purplemet-cli sites list --query "url~=staging"
# Open high-severity issues only
purplemet-cli issues list --query "severity=high,status=OPEN"
# All non-low issues mentioning a CVE in their name
purplemet-cli issues list --all --query "severity!=low,name~=CVE-2024"
# Admin tokens only
purplemet-cli tokens list --query "role=ADMIN"
# Active user accounts
purplemet-cli users list --query "status=ENABLED"
# Discoveries that succeeded
purplemet-cli discoveries list --query "status=DONE"
# Internal domains
purplemet-cli domains list --query "name~=internal"
# Sensitive services
purplemet-cli services list --query "sensitive=true"
# Filtering already spans the whole account; --all just disables the
# interactive pager and prints every match in one shot
purplemet-cli issues list --all --query "severity=critical,status=OPEN"Tip: unsure of the field names? Run the same command with --json
once — the keys you see in the output are the keys you can filter on.
The footer reports the filtered count, not the unfiltered total:
Showing 1-34 of 34 issue(s) — page 1 of 1
The users, sessions, and tokens command groups require an ADMIN token.
Calling them with an OPERATOR or READER token returns
403 API_METHOD_NOT_ALLOWED.
When invoked, these commands print a one-line warning to stderr. To suppress
it (e.g. in CI pipelines that legitimately use an ADMIN token), pass
--no-admin-warning or set PURPLEMET_NO_ADMIN_WARNING=1.
The CLI automatically loads a .env file from the current directory. Format:
PURPLEMET_API_TOKEN=your-token-here
PURPLEMET_BASE_URL=https://api.purplemet.com
PURPLEMET_FAIL_SEVERITY=high
PURPLEMET_FAIL_ON_EOL=trueRules:
- Lines starting with
#are comments - Empty lines are ignored
- Existing environment variables are not overwritten
- The
.envfile should be in.gitignore
Security: The CLI warns if the
.envfile is readable by group or others. Setchmod 600 .env.
A project-scoped YAML config lives at the root of your repository. It is auto-discovered by walking up from the current directory until the CLI finds either the file or a .git/ directory (the project boundary). Lookup order:
-
--config <path>flag (explicit; errors if missing) -
$PURPLEMET_CONFIGenv var -
.purplemet.yml/.purplemet.yaml, searched upward from CWD up to the nearest.git/
# Default target for `analyze` — accepts a siteId (UUID) or URL.
# `purplemet-cli analyze` can then run without any argument.
site: https://example.com
verbose: true
# Per-project security gates
fail_severity: high
fail_rating: C
fail_on_kev: true
fail_on_headers: true
exclude_tech:
- php
- javaSecurity — no secrets in project config. Because this file is meant to be committed alongside the code, secret fields (token, basic_user, basic_pass) are stripped at load time and a warning is emitted. Keep secrets in env vars or in the user-level config below.
Optional YAML configuration file for persistent user-level settings. Unlike the project config, this file can contain the API token — it is meant to stay on the user's machine, outside version control.
# Authentication
token: ppm_xxx
base_url: https://api.purplemet.com
# Timeouts
poll_interval_ms: 10000
timeout_ms: 30000
wait_timeout_ms: 300000
verbose: true
no_admin_warning: true # silence admin-only command warnings
# Security gates
fail_severity: high
fail_rating: C
fail_cvss: 9.0
fail_on_eol: true
fail_on_ssl: true
fail_on_cert: true
fail_on_headers: true
fail_on_cookies: true
fail_on_unsafe: true
fail_on_kev: true
fail_on_epss: 0.75
fail_on_active_exploits: true
fail_on_ossf_score: 5.0
fail_on_cert_expiry: 30
fail_on_issue_count: 50
require_waf: true
fail_on_sensitive_services: true
exclude_tech:
- php
- javaIssues explicitly ignored via
purplemet-cli issues ignoreare always excluded from gate evaluation.
Security: The CLI warns if config file permissions are broader than
0600. Setchmod 600 ~/.purplemet/config.yml.
For --fail-on-severity / PURPLEMET_FAIL_SEVERITY:
| Level | Weight | Blocks on |
|---|---|---|
critical |
4 | Critical only |
high |
3 | High + Critical |
medium |
2 | Medium + High + Critical |
low |
1 | Low + Medium + High + Critical |
info |
0 | All issues |
Default in CI templates: high (blocks on high and critical issues).
For --fail-on-rating / PURPLEMET_FAIL_RATING, accepted values are A, B, C, D, E, F (ordered from best to worst — A is the safest, F the most critical). The rating is computed by the Purplemet platform; see the official Purplemet documentation for the scoring rules.
The gate triggers if the analysis rating is at or worse than the threshold. Example: --fail-on-rating C fails on C, D, E, and F.