ankos drift
Detect PCI posture drift by comparing the current state against a previously collected evidence baseline. Works across every provider, CI/CD-friendly, with severity-based exit codes.
ankos drift compares the current state of your environment against
a baseline directory produced by an earlier ankos scan
and reports what changed — new resources, removed resources, security
posture degradations, and improvements.
The intended use is scheduled execution: run it nightly or weekly in CI, fail the build when something drifts in a critical direction, and catch PCI regressions between assessments instead of at them.
Works for every provider. drift infers the provider from the
baseline you point it at — an AWS baseline re-scans AWS (honoring
--profile / --region), and GCP, GitHub, Okta, Entra, and Kubernetes
baselines re-scan their provider using the same scope and your
environment-based credentials (GOOGLE_*, GITHUB_TOKEN, OKTA_*,
ENTRA_*, KUBECONFIG). No extra flags — just pass the baseline
directory from any ankos scan.
Synopsis
ankos drift <baseline-dir> [flags]Quick start
# Last week's scan is the baseline; compare current state against it
ankos drift ./ankos-evidence-baseline
# Save the drift report to a file
ankos drift ./ankos-evidence-baseline -o ./drift-report.json --format json
# CI gate: fail the build if any critical-severity drift appeared
ankos drift ./ankos-evidence-baseline --fail-on critical
# Update the baseline in place after the comparison (start of new week)
ankos drift ./ankos-evidence-baseline --baseline-update
# Post a Slack/webhook alert when posture regresses
ankos drift ./ankos-evidence-baseline --webhook "$SLACK_WEBHOOK_URL" --fail-on anyPoint drift at a baseline from any provider — an AWS, GCP, GitHub, Okta, Entra, or Kubernetes scan — and it re-scans that provider automatically:
# A GCP baseline re-scans GCP; a GitHub baseline re-scans GitHub, etc.
ankos drift ./gcp-evidence-baseline
ankos drift ./github-evidence-baselineFlags
| Flag | Default | Description |
|---|---|---|
--region | (from baseline) | Region to check (AWS baselines). Defaults to the region recorded in the baseline. |
--profile | (none) | AWS profile to use (AWS baselines). |
--collectors | (from baseline) | Subset of collectors to compare. Default uses everything in the baseline. |
--format | text | Output format: text or json. |
--output / -o | (stdout) | Save drift report to file. |
--fail-on | (none) | Exit non-zero on drift: any, critical, or high. |
--baseline-update | false | Overwrite the baseline with the current state after comparing. Use to "roll forward" the baseline at the start of each comparison window. |
--webhook | (none) | Webhook URL to alert on a posture regression. A Slack incoming-webhook URL is posted as a Slack message; any other URL receives a generic JSON payload. |
--notify | (none) | Alias for --webhook. |
--upload | false | Upload the live scan's evidence to the Ankos Ledger, so a scheduled drift run doubles as continuous evidence collection. |
CI exit codes
Pair --fail-on with your build's failure threshold:
| Setting | Exits non-zero when… |
|---|---|
--fail-on any | Any drift detected (degradation / improvement / change) |
--fail-on critical | At least one critical-severity drift |
--fail-on high | At least one high-severity or above |
Typical pattern: weekly cron in CI with --fail-on critical, so the
build only breaks on serious regressions. High-severity changes get
filed as work; low-severity churn (new tags, capacity changes) stays
informational.
Baseline lifecycle
The baseline is just an evidence directory from ankos scan. Common
patterns:
- Weekly window. Scan on Sunday → that's the baseline for the week. Daily drift checks reference it. The next Sunday's scan replaces the baseline.
- Quarterly window. Use last quarter's evidence package as the baseline; daily drift checks surface anything that drifted since the last QSA review.
- Rolling. Run
ankos drift ./baseline --baseline-updatedaily; the baseline always represents "yesterday."
For options 1 and 2, store the baseline in S3 or your CI artifact storage and pull it before each drift run. For option 3, the baseline is local to the runner.
Output
In text format, drift opens with a Direction line (↓ Degrading, ↑ Improving, or → Stable) summarizing the overall posture move, then groups changes into three sections:
- Degradations — PCI posture worsened (encryption disabled, public access enabled, MFA removed, a new public bucket, etc.)
- Improvements — PCI posture improved since the baseline
- Changes — informational infrastructure changes that don't move posture in either direction
In JSON format, the same data is structured per-collector (with a
posture_direction summary field) for easy machine processing.
What drift catches
A non-exhaustive list of common drift events you'll see flagged:
- A new public S3 bucket appears
- CloudTrail logging is disabled in a region
- An IAM user is granted administrative permissions
- An EC2 security group adds 0.0.0.0/0 ingress on a CDE port
- KMS key rotation is disabled
- A WAF rule is deleted
- A new EKS cluster appears that wasn't covered by the baseline
Limitations
- Read-only. Like all Ankos commands, drift never modifies your environment. It re-scans read-only, reports, and your team remediates.
- Single baseline at a time. Multi-baseline comparison (3-way diff)
isn't supported; combine
ankos report --diffif you need that shape.
Alerting on regressions
Pass --webhook (alias --notify) to post an alert whenever posture
regresses — a new degradation or lost coverage. A Slack incoming-webhook
URL (hooks.slack.com/...) is rendered as a Slack message; any other URL
receives the same alert as a generic JSON payload, so it works with a
custom endpoint or a relay. Nothing is sent unless a webhook is configured,
and a delivery failure never changes the exit code — CI gating still works.
# Nightly cron: fail CI on regression AND post to Slack
ankos drift ./ankos-evidence-baseline \
--webhook "$SLACK_WEBHOOK_URL" \
--fail-on any
# Refresh the Ledger with the live scan's evidence in the same run
ankos drift ./ankos-evidence-baseline \
--upload \
--webhook "$SLACK_WEBHOOK_URL" \
--fail-on anyThe alert states evidence-readiness signal ("N items need attention"),
never a pass/fail verdict — the determination stays with your QSA. For a
long-running local daemon instead of a CI scheduler, see
ankos watch.
ankos report
Generate a PCI DSS evidence-readiness report from a collected evidence directory. Text, JSON, CSV, HTML, or GitHub-summary output with an at-a-glance score, score-over-time trend, and CI-friendly exit codes.
ankos watch
Continuously re-scan your environment on a schedule and post an alert when PCI posture drifts. A long-running local daemon — the non-CI counterpart to ankos drift.

