Authorized Engagements
0sec is built for authorized, announced testing. Its safety rails exist to make traffic identifiable rather than to hide it: attribution headers, per-engagement tokens, declared-scope enforcement, request counters. That is the opposite design goal from adversary emulation, and it is deliberate.
This page covers the surfaces that exist specifically for running inside a client engagement: controlling how loud the engine is, and producing evidence a client’s security team can act on.
Engagement profile
Section titled “Engagement profile”By default 0sec runs at 5 requests/second per host, without jitter, and escalates automatically when it detects a WAF block. That is appropriate for your own infrastructure. It is not appropriate for a monitored production estate where you have agreed to keep noise down.
--engagement-profile conservative applies a single auditable posture:
0sec scan --target https://app.example.com --mode web \ --scope ./engagement-scope.json \ --engagement-profile conservative| Behaviour | Default | Conservative |
|---|---|---|
| Request rate | 5 rps/host | 1 rps/host |
| Jitter | none (fixed interval) | full jitter, 0–750 ms |
| Reset-endpoint burst probe | 15 POSTs | disabled |
| Web-recon pre-pass | unthrottled | routed through the rate limiter |
| WAF-evasion ladder | auto-fires on block | disabled |
Jitter matters more than it looks. A perfectly periodic request train at 1 rps is arguably a stronger automation signal to a behavioural SOC than bursty traffic, so the profile paces the non-blocking path too, not just the rate-limited one.
The reset-endpoint probe is not silently dropped. It is converted into a lead so the finding surfaces as a manual test item for the client rather than disappearing.
Precedence and the standalone opt-out
Section titled “Precedence and the standalone opt-out”Configuration resolves scope file > environment > CLI flag. The scope file is the artifact that binds to the engagement, so an ad-hoc command-line flag cannot loosen a posture the scope file established. Rate is resolved by taking the minimum, so a profile can only ever make a scan quieter.
The WAF-evasion ladder can also be disabled independently:
0sec scan --target https://app.example.com --no-waf-evasion# or0SEC_WAF_EVASION=0 0sec scan --target https://app.example.comDisabling the ladder does not disable detection of a WAF block — the block is still detected and reported. Only the automatic escalation into encoding-mutated payload variants stops, since that is the behaviour that turns a WAF block into a SOC incident.
Environment variables: 0SEC_ENGAGEMENT_PROFILE, 0SEC_WAF_EVASION,
0SEC_ENGAGEMENT_RATE_RPS, 0SEC_ENGAGEMENT_JITTER_MS. A scope file may
carry an engagement block with the same fields.
The posture record
Section titled “The posture record”When a profile is active the report carries an engagementPosture record and
the run emits an engagement_posture_applied event. The record states the
posture as applied, not as requested — so a scope file asking for
conservative with 0SEC_WAF_EVASION=1 in the environment correctly reports
the ladder as enabled, and attributes that to the environment.
That distinction is the point: the record is evidence of how the scan actually ran, which is what a client asks for after the fact.
Reports from runs without a profile are unchanged.
Forensic timeline
Section titled “Forensic timeline”A client’s security team needs a chronological record of what you did and when,
to cross-reference against their own detections. 0sec timeline produces it
from the immutable pipeline-event audit trail:
0sec timeline <scanId> # markdown, for a report appendix0sec timeline <scanId> --format json # machine-readable0sec timeline <scanId> --format csv # for a spreadsheet or SIEM import0sec timeline <scanId> --attack-only # drop pipeline lifecycle noise0sec timeline <scanId> --since 2026-09-15T09:00:00Z --until 2026-09-15T17:00:00ZEvery row carries a UTC ISO-8601 timestamp, the stage, event type, agent role, a human-readable action summary, and its technique mappings. Epoch milliseconds never appear in output.
--attack-only filters to events carrying a technique mapping. The export
reports both the filtered and total event counts, so a filtered record always
states what it omitted rather than quietly presenting itself as complete.
Action-level detail
Section titled “Action-level detail”The durable audit trail records each tool invocation individually, with its own
start timestamp, duration, outcome, and redacted arguments. A correlationId
joins each logged call to the artifact carrying its full request detail, so the
timeline can state the actual URL, method and response status rather than only
the tool name.
Arguments are redacted before truncation. Truncating first would leave a usable secret prefix sitting in the log.
Technique mapping — two matrices
Section titled “Technique mapping — two matrices”Findings and actions are mapped against two separate MITRE matrices, carried as distinct fields:
- ATT&CK (Enterprise) — conventional behaviours. SQL injection, SSRF, command injection, memory-safety classes, credential access.
- ATLAS (AI systems) — AI-specific behaviours. Prompt injection, jailbreak, system-prompt extraction, multi-turn manipulation.
They are deliberately not merged. A row may carry either, both, or neither.
data-exfiltration, for example, legitimately carries ATT&CK T1567/T1041
and ATLAS AML.T0057/AML.T0024 — collapsing them into one column would
destroy that distinction.
Where a behaviour has no honest home in a matrix, the mapping is empty rather than approximated. An unmapped row is better than a wrong technique ID in a client deliverable.
Identity and token analysis
Section titled “Identity and token analysis”0sec identity assesses an Entra ID tenant read-only — 27 posture checks
across privileged roles, conditional access, app registrations, service
principals and federation. Read-only is structural: every Graph request
hard-codes GET, and there is no method parameter in the client.
Token analysis adds 26 further checks over JWTs and SAML assertions, offline and with no network calls:
- JWT —
alg:none, algorithm confusion, unsafe key identifiers (kidtraversal,jku/x5u/jwkinjection), missing or excessive expiry, weak audience, absent replay controls, sensitive claim data, overly-broad scope. - Entra — access-vs-ID token misuse, weak client binding, privileged
widsrole template IDs, multi-tenant issuer, long-lived session indicators (PRT, CAE). - SAML — XML Signature Wrapping exposure, unsigned assertions, weak conditions, missing audience restriction, NameID comment truncation, and Golden SAML preconditions.
Raw token material is never logged or persisted; findings carry a SHA-256 fingerprint and a redacted preview.
Attack paths — on-premises and cloud
Section titled “Attack paths — on-premises and cloud”Two commands, same shape: the client’s collector runs wherever the engagement puts it, and the analysis runs here. Both are offline by design — neither collects, authenticates, nor touches a network.
Active Directory
Section titled “Active Directory”0sec adgraph --input <path> computes attack paths from a BloodHound CE /
SharpHound JSON export. Coverage includes paths to Domain Admin, kerberoastable
principals, unconstrained delegation, DCSync rights, ACL abuse chains, and the
ADCS escalation set (ESC1, ESC3–ESC7, ESC9, ESC10, ESC13). Roughly 60 edge kinds
each carry a written abuse technique.
Entra ID
Section titled “Entra ID”0sec entragraph --input <path> does the equivalent over an AzureHound
export: paths to Global Administrator, service-principal escalation via added
secrets, consent-grant escalation through high-impact Graph permissions,
owner-chain abuse, and guest escalation.
0sec entragraph --input ./azurehound-export/0sec entragraph --input ./azurehound-export/ --json0sec entragraph --input ./export --owned <objectId>,<objectId> # start from known-compromised principals0sec entragraph --input ./export --max-depth 4What 0sec does not do
Section titled “What 0sec does not do”Stated plainly, because scoping an engagement on a wrong assumption is expensive:
- No network sweep, host discovery, or CIDR enumeration
- No non-HTTP service exploitation — no SMB, RDP, SSH, LDAP or SNMP clients
- No credential spraying or service brute force
- No foothold, persistence, implants, beacons, C2, or pivoting
- No detection evasion or adversary-emulation stealth
- No organisation-name-driven asset discovery — apex domains must be supplied
The engine stops at a proven vulnerability with benign impact demonstration
(id, whoami, /etc/hostname), then moves to documentation and remediation.
Post-exploitation belongs to human operators.
Data residency
Section titled “Data residency”For engagements that require target-derived data to stay inside a defined perimeter, 0sec routes all model traffic through a single configurable endpoint. Azure OpenAI is supported with no code change:
export AZURE_OPENAI_API_KEY=...export AZURE_OPENAI_BASE_URL=https://<resource>.openai.azure.comexport AZURE_OPENAI_MODEL=<deployment-name>At startup the engine probes the x-ms-region response header and reports the
physical region serving traffic, which doubles as an audit artifact.
Two caveats worth stating in a contract rather than discovering later:
- The defensible claim is “no target data leaves to third-party model providers.” Other enrichment paths still make outbound calls — GitHub API, OSV, package registries, Microsoft Graph, and OAST. Air-gapping those is a separate exercise.
- Pin
--runtime api. Theclaude,codexandgeminiruntimes shell out to third-party binaries whose egress 0sec does not control.
See API Keys for the full provider matrix.