Run your first automated pentest
Launch an autonomous web pentest, stream it end to end, and email the report.
What you’ll build
A complete automatic pentest against a single web target: you create it, let Rank auto-assign every default agent, stream the agents working in real time, and finish with a PDF report in your inbox. Automatic mode runs every phase end to end and processes the findings inside the same stream, so there is nothing to orchestrate by hand.
Prerequisites
- A Rank account and an API token (see Authentication).
- The Python SDK or CLI installed.
pip install rank-sdk
export RANK_API_KEY=rk_... npm install -g @aleex-rank/cli
rank auth set rk_... Steps
The same flow works from the CLI, the Python SDK, or the raw REST API. Pick a tab.
-
Create an automatic web pentest. Exactly one asset should be primary;
-usets it.rank pentest create -n "First automated pentest" -u https://example.com -t web -m automaticThe command prints the new pentest
id. Use it below. -
Run it. In automatic mode the default agents are auto-assigned and every phase streams to your terminal.
rank pentest run 42 -
List the findings once the run completes.
rank pentest vulns 42
-
Create a chat session and an automatic web pentest.
import rank client = rank.Rank() chat = client.chats.create(name="Automated pentest - example.com") pentest = client.pentests.create( name="First automated pentest", url="https://example.com", type="web", mode="automatic", assets=[ {"asset_type": "url", "asset_value": "https://example.com", "is_primary": True}, ], ) -
Auto-assign the default agents. For an automatic pentest, requesting the defaults assigns every phase.
defaults = client.pentests.agents.default(pentest.id) print(defaults.auto_assigned, defaults.assigned_count) -
Stream the execution. Only
contentevents build the answer;agent_eventitems are live activity.with client.ai.chat.stream( user_prompt="Start the pentest on the configured targets", pentest_id=pentest.id, mode="automatic", chat_id=chat.id, ) as stream: for event in stream: if event.type == "content": print(event.content, end="", flush=True) elif event.is_agent_event: ev = event.agent_event if ev and ev.event_type == rank.AgentEvent.TOOL_CALL: print(f"\n[tool] {ev.data.get('tool_name')}") elif event.type == "complete": print(event.metadata.get("vulnerabilities_stored", 0), "stored") -
Finish the pentest and list the stored vulnerabilities.
client.pentests.finish(pentest.id) vulns = client.pentests.vulnerabilities.list(pentest.id) for v in vulns.items: print(v.id, v.severity, v.vulnerability, v.status) -
Email a PDF report. Use
extended=1for the full report with evidence details.client.pentests.generate_report( pentest.id, recipient_email="you@example.com", extended=1, )
-
Create the pentest on the PHP API. The API key goes in the
X-API-Keyheader.curl https://api.aleex-rank.ai/api/v2/pentests \ -H "X-API-Key: $RANK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "First automated pentest", "type": "web", "mode": "automatic", "assets": [{"asset_type": "url", "asset_value": "https://example.com", "is_primary": true}] }' -
Auto-assign the default agents. For an automatic pentest this single call assigns every phase.
GET /api/v2/pentests/42/default-agents X-API-Key: rk_... -
Start execution on the Go backend, which streams progress over Server-Sent Events.
curl https://aleex.aleex-rank.ai/chat \ -H "X-API-Key: $RANK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_type": "pentest", "pentest_id": 42, "mode": "automatic", "user_message": "Start the pentest on the configured targets" }' -
Finish the pentest and read back the findings.
POST /api/v2/pentests/42/finish GET /api/v2/pentests/42/vulnerabilities X-API-Key: rk_... -
Email a report from the Go backend.
curl https://aleex.aleex-rank.ai/generate_report \ -H "X-API-Key: $RANK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"pentest_id": 42, "recipient_email": "you@example.com", "extended": 1}'
Run it
Save the following as first_automated_pentest.py, set RANK_API_KEY, then run
python first_automated_pentest.py.
"""Run your first automated pentest end to end with the Rank SDK.
What this script does:
1. Creates a chat session so the run has conversation context.
2. Creates an automatic web pentest against a single URL asset.
3. Auto-assigns the default agents for every phase.
4. Streams the execution, printing the assistant's answer and a compact
activity log of agent events as they happen.
5. Marks the pentest as finished and lists the stored vulnerabilities.
6. Emails a PDF report to the configured recipient.
In automatic mode the agents run every phase end to end and process the
findings inside the same stream, so by the time the `complete` event arrives
the vulnerabilities are already stored.
Run:
pip install rank-sdk
export RANK_API_KEY=rk_...
python first_automated_pentest.py
Optional environment variables:
RANK_TARGET_URL Target URL to scan (default: https://example.com).
RANK_REPORT_EMAIL Recipient for the PDF report (default: you@example.com).
"""
from __future__ import annotations
import os
import rank
TARGET_URL = os.environ.get("RANK_TARGET_URL", "https://example.com")
REPORT_EMAIL = os.environ.get("RANK_REPORT_EMAIL", "you@example.com")
def main() -> None:
# The client reads RANK_API_KEY from the environment automatically.
with rank.Rank() as client:
chat = client.chats.create(name=f"Automated pentest - {TARGET_URL}")
pentest = client.pentests.create(
name="First automated pentest",
url=TARGET_URL,
type="web",
mode="automatic",
assets=[
{"asset_type": "url", "asset_value": TARGET_URL, "is_primary": True},
],
)
print(f"Created pentest #{pentest.id} (status: {pentest.status})")
# Automatic pentests auto-assign every default agent on first access.
defaults = client.pentests.agents.default(pentest.id)
if defaults.auto_assigned:
print(f"Auto-assigned {defaults.assigned_count} agents across all phases")
# Stream the run. Only `content` events form the assistant's answer;
# `agent_event` items are live activity meant for a timeline view.
print("\n--- Live execution ---\n")
with client.ai.chat.stream(
user_prompt="Start the pentest on the configured targets",
pentest_id=pentest.id,
mode="automatic",
chat_id=chat.id,
) as stream:
for event in stream:
if event.type == "content":
print(event.content, end="", flush=True)
elif event.type == "phase_start":
print(f"\n=== Phase {event.metadata.get('phase_id')} ===")
elif event.is_agent_event:
ev = event.agent_event
if ev is not None and ev.event_type == rank.AgentEvent.TOOL_CALL:
print(f"\n [tool] {ev.data.get('tool_name')}")
elif event.type == "error":
print(f"\nERROR: {event.error}")
elif event.type == "complete":
stored = event.metadata.get("vulnerabilities_stored", 0)
print(f"\n\nExecution complete - {stored} vulnerabilities stored")
# Finalize the pentest and review the findings.
finished = client.pentests.finish(pentest.id)
print(f"\n{finished.message}")
vulns = client.pentests.vulnerabilities.list(pentest.id)
print(f"\nVulnerabilities ({len(vulns.items)} on this page):")
for v in vulns.items:
print(f" [{v.id}] {v.severity:>8} {v.vulnerability} ({v.status})")
# The pentest must be completed before a report can be generated.
report = client.pentests.generate_report(
pentest.id,
recipient_email=REPORT_EMAIL,
extended=1,
)
print(f"\n{report.message}")
if __name__ == "__main__":
try:
main()
except rank.AuthenticationError:
print("ERROR: invalid or missing API key. Set RANK_API_KEY.")
except rank.APIError as exc:
print(f"API error ({exc.status_code}): {exc.message}")
Next, try the guided pentest recipe to drive the run phase by phase, or dig into the streaming protocol.