Skip to content

pentest-ai

v0.11.0 Security

This release includes 3 security fixes for security teams reviewing exposed deployments.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 3 known CVEs

Topics

ai-security bug-bounty claude ctf security exploit
+12 more
exploit-chaining hacking-tools mcp model-context-protocol nmap offensive-security osint penetration-testing pentest-ai pentesting python vulnerability-scanning

Affected surfaces

auth rbac rce_ssrf

Summary

AI summary

Updates Added — Agent-loop foundation, Added — SPA-aware probes, and new across a mixed release.

Full changelog

Major release. New offensive-security probes, CVE intelligence, agent-loop scaffold, plus the launch-prep work staged on May 2.

Added — SPA-aware probes (14 deterministic checks)

  • JWT alg=none acceptance (agents/web/spa_probes.py:probe_jwt_alg_none). Two-step: anonymous GET, then GET with an unsigned JWT. If the second succeeds, the validator is honouring alg=none. On Juice Shop 19.2.1 this catches 8 separate critical bypasses across /api/Users, /api/SecurityAnswers, /api/PrivacyRequests, /api/BasketItems, /api/Complaints, /rest/admin/application-configuration, /rest/user/whoami, /api/Challenges.

  • JWT alg variants (probe_jwt_alg_variants). Tests case + whitespace + array + missing-alg variants. Reports only on endpoints where canonical lowercase 'none' was rejected, so the count is not inflated.

  • SQLi auth bypass on login (probe_login_sqli_bypass). POSTs a tautology payload in the email field. Detects the canonical Sequelize-bug shape that returns 200 + a token-shaped response.

  • GET-method SQLi on search (probe_search_sqli_get). Two-step response-size diff: baseline ?q=apple vs UNION payload. 3.0x size ratio with HTTP 200 = critical.

  • Path-filter bypass via poison null byte (probe_ftp_leak). Two-stage: direct GET to /ftp/<file> vs URL-encoded NUL bypass /ftp/<file>%2500.md. Catches the canonical Express serve-index filter defect. Pulls dependency manifests (package.json.bak) and other backup files.

  • Authenticated pivot (probe_authenticated_pivot). Captures an admin JWT from the SQLi login bypass, then re-tests every 401-anon endpoint with the captured token. The autonomous-agent move: a finding becomes the input to the next probe. On Juice Shop unlocks 9 protected endpoints.

  • Open redirect (probe_open_redirect). 10 redirect paths × 12 parameter names. Sentinel host with substring match on the Location header.

  • REST resource enumeration (probe_user_enum, probe_unauth_rest_leak). User-shape detection plus generic 200+JSON-without-auth detection across 19 Sequelize/Express scaffold paths.

  • Source-map disclosure, directory listing, dev/admin interface leak (probes 4 to 6).

Added — CVE intelligence

  • engine/cve_db.py: osv.dev batch API wrapper. Parses npm package.json and package-lock.json (v1, v2, v3 lockfiles) into (name, version) tuples and looks them up against the live osv.dev advisory database. When a leaked manifest comes through probe_ftp_leak, the engine auto-correlates and emits per-package Vulnerable dependency findings tagged with their GHSA identifiers.

Added — Agent-loop foundation (v0.11 autonomous-agent rebuild, phase 1 + 2)

  • engine/working_memory.py: per-engagement state object. Coverage matrix tracks (endpoint, bug-class) pairs the loop has tried. Captured-auth store for in-memory tokens. Pattern export refuses without explicit cross_engagement_share opt-in. Privacy-by-design enforced by tests.

  • engine/agent_loop.py: Action / Observation / LLMAgent protocol, handler registry, run_agent_loop driver. LoopConfig pins safety: max_iterations, coverage_threshold, min_iterations_before_finish.

  • engine/agents/anthropic_agent.py: LLMAgent backed by the Anthropic Messages API. Renders state + handler list, parses Claude's JSON action response, falls back to finish on malformed output.

  • engine/agents/handlers/web_probes.py: three SPA probes wrapped as agent-loop handlers (probe.jwt_alg_none, probe.sqli_login, probe.ftp_leak). Imported on agent-mode dispatch, registers automatically.

  • ptai start --agent-mode (cli/main.py). New flag routes the engagement through the agent loop instead of the legacy fixed pipeline. Default behaviour unchanged.

Added — earlier launch-prep work (May 2 staging)

  • PTAI_PRICE_LIMIT hard budget cap (engine/llm/cost.py, engine/orchestrator.py). Set PTAI_PRICE_LIMIT=5.00 (or any float in USD) and the orchestrator raises CostLimitError mid-run as soon as accumulated LLM spend crosses the threshold. The cap is enforced inside CostTracker.add() so it fires even on cached responses. If no limit is set the engine runs uncapped as before.

  • Process registry with ptai ps and ptai kill (engine/process_registry.py, cli/main.py, mcp_server/server.py). Every tool process spawned through ToolRunner is registered in an in-memory table keyed on PID with command, start time, and engagement context. ptai ps prints a formatted table. ptai kill <pid> terminates the process and removes it from the registry. Also exposed as list_processes and kill_process MCP tools so MCP clients can manage long-running scans from the tool-use layer.

  • SelectionAgent heuristic router (agents/selection/selection_agent.py, cli/main.py, mcp_server/server.py). Routes a target string to the best-fit agent without an LLM call. Heuristics run in order: intent keyword matching → URL/path pattern → file extension → cloud service indicators → AD/Kerberos keywords → IP/CIDR/domain regex → fallback to WebAgent. Returns {"target", "agent", "reason", "confidence"}. Exposed as ptai route <target> [--intent <hint>] [--json] and as the select_agent MCP tool.

  • Public legal documentation suite (docs/legal/). New or strengthened markdown that mirrors the live pages at pentestai.xyz/{privacy,terms,aup,cookies,subprocessors,security}:

    • PRIVACY.md — GDPR Article 6 legal bases, 72-hour breach notification SLA, CCPA/CPRA disclosures, 2021 EU SCCs Module 2 with UK Addendum and Swiss FDPIC supplements.
    • TERMS.md — liability cap, indemnification, dispute resolution options, sanctions and export controls, beta features clause.
    • AUP.md (new) — shifts authorization-to-test responsibility to the user; defines prohibited targets and conduct; abuse-handling SLA and indemnification position.
    • DPA.md (new) — GDPR Article 28 template with Annex I, II, III.
    • SUBPROCESSORS.md (new) — vendor table with 30-day change-notice mechanism.
    • COOKIES.md (new) — cookie inventory, banner consent flow, and GPC signal compliance.
    • RESPONSIBLE_DISCLOSURE.md (new) — public security policy with safe harbor.

Security

  • ProcessRegistry.kill() refuses unregistered PIDs. The original implementation fell through to os.kill(pid, signal.SIGTERM) for any live PID, even one not spawned by ptai. An attacker who could write a valid integer to the registry endpoint could have sent SIGTERM to arbitrary processes. Fixed by returning False immediately when registry.get(pid) is None. Test test_kill_refuses_unregistered_live_pid spawns a real sleep 30 without registering it and asserts both that kill() returns False and the process is still alive after the call.

  • Chain noise filter. The exploit chainer used to fabricate chains from any list of findings, including nikto error strings. Fixed: agents/exploit_chain/chain_agent.py now drops scanner-noise findings before chain generation and refuses to fire on fewer than 2 medium-or-higher findings.

  • Evidence-gated chain validation. agents/poc_validator/poc_agent.py now updates findings.poc_status and attack_chains.status based on whether each chain step has corroborating evidence on the finding row.

Changed

  • --no-llm is now an explicit opt-in. ptai start used to silently fall back to deterministic mode when no LLM provider was configured. Now non-interactive runs without --no-llm AND without an LLM provider exit with code 3 and a clear message. ptai is LLM-driven by default; the deterministic path is opt-in.

  • Tagline corrected on cli/main.py, docs/index.html, docs/index.md. The previous "Most autonomous pentesting AI on the market" claim was not defensible against CAI's HackTheBox CTF wins or HexStrike's adoption numbers. Replaced with concrete capability copy.

  • CostLimitExceededCostLimitError to comply with ruff rule N818 (exception class names must end in Error). Renamed across engine/llm/cost.py, engine/orchestrator.py, and tests/test_cost_tracker.py. Any code that caught CostLimitExceeded by name must be updated to CostLimitError.

Breaking Changes

  • --no-llm is now an explicit opt‑in; runs without LLM provider or the flag exit with code 3
  • CostLimitExceeded exception renamed to CostLimitError

Security Fixes

  • ProcessRegistry.kill() now refuses to terminate unregistered PIDs preventing arbitrary process termination
  • `agents/exploit_chain/chain_agent.py` drops scanner‑noise findings before chain generation
  • `agents/poc_validator/poc_agent.py` gates chain validation on corroborating evidence

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track pentest-ai

Get notified when new releases ship.

Sign up free

About pentest-ai

Offensive-security MCP server with 205 wrapped tools, 17 specialist agents, and 60 SPA-aware probes for OWASP Top 10. CLI + MCP, BYO LLM. No API key needed on MCP path.

All releases →

Related context

Beta — feedback welcome: [email protected]