Skip to content

feat(workflows): add api_discover workflow and api scan#1268

Open
Naboot42 wants to merge 3 commits into
mainfrom
workflow-api
Open

feat(workflows): add api_discover workflow and api scan#1268
Naboot42 wants to merge 3 commits into
mainfrom
workflow-api

Conversation

@Naboot42

@Naboot42 Naboot42 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an API-focused discovery workflow and a composed API security scan, reusing existing workflows rather than duplicating logic (per secator's design philosophy).

What's included

  • secator/configs/workflows/api_discover.yaml — API endpoint discovery only:
    • katana (crawl, JS-aware) discovers referenced endpoints.
    • ffuf (opt-in via --fuzz) brute-forces API routes using the apiroutes wordlist.
    • wafw00f (opt-in via --waf) fingerprints the WAF.
    • httpx probes discovered endpoints to verify they're live and fingerprint tech.
  • secator/configs/scans/api.yaml — chains api_discoverurl_params_fuzzurl_vuln, mirroring the existing url scan. Parameter fuzzing, vulnerability scanning and secrets hunting are handled by the existing workflows — no duplication.
  • config.py — new apiroutes wordlist template pointing at Assetnote's HTTP Archive API routes dataset, regenerated monthly (the same real-world route data kiterunner's -A apiroutes relied on).
  • testsapi_discover / api entries in integration inputs.py / outputs.py.

Design notes

  • Why not kiterunner? An earlier iteration added kiterunner for contextual API route discovery, but it fails secator's design principle Fix issue with parsing nmap XML #1 ("Tools integrated to secator MUST be [...] well-maintained") — unmaintained since 2021. That PR was closed. Its real value — the Assetnote apiroutes dataset — is preserved here as a maintained plaintext wordlist fed to ffuf.
  • Why not coffinxp wordlists? Redundant: their httparchive_apiroutes file is just a stale 2022 copy of the Assetnote dataset we now use fresh; their param/payload lists belong to the downstream url_params_fuzz / url_vuln stages which already have curated sources.
  • Complements PR feat(tasks): apifuzzer and openapi-fuzzer integration #160 (apifuzzer/openapi-fuzzer, spec-driven): api_discover finds exposed OpenAPI/Swagger specs that a spec-driven fuzzer could later consume.

Testing

  • Configs load and resolve (api_discover tasks: katana, ffuf, wafw00f, httpx; api scan workflows: api_discover, url_params_fuzz, url_vuln).
  • Workflow/Scan objects build without error.
  • flake8 secator/config.py clean.
  • Integration tests (--workflows api_discover, --scans api) require the live lab + tools (run in CI).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an API discovery workflow and a new API scan option for finding and checking API endpoints.
    • Included support for an additional route wordlist to improve endpoint discovery.
    • Expanded integration test coverage for the new workflow and scan.
  • Bug Fixes

    • Improved handling of verified URLs so scan stages run only on trusted targets.

Add an API-focused discovery workflow and a composed API security scan,
reusing existing workflows rather than duplicating their logic.

- secator/configs/workflows/api_discover.yaml: API endpoint discovery via
  katana (crawl) + optional ffuf route brute-forcing, then httpx to verify
  discovered endpoints. Endpoint discovery only.
- secator/configs/scans/api.yaml: chains api_discover -> url_params_fuzz ->
  url_vuln (param fuzzing + vuln/secrets scanning), mirroring the url scan.
- config.py: add the "apiroutes" wordlist template pointing at Assetnote's
  maintained HTTP Archive API routes dataset (the same real-world route data
  kiterunner's -A apiroutes relied on), used by ffuf.
- tests: add api_discover/api entries to integration inputs and outputs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7ef5f5e3-bad1-4024-a428-30518a9be310

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds a new apiroutes wordlist default, a new api_discover workflow (katana, ffuf, wafw00f, httpx tasks), a new api scan chaining discovery with URL param fuzzing and vulnerability scanning, and integration test fixtures for both.

Changes

API Discovery Feature

Layer / File(s) Summary
Apiroutes wordlist default
secator/config.py
Adds apiroutes dataset URL entry to Wordlists.templates defaults.
api_discover workflow
secator/configs/workflows/api_discover.yaml
New workflow with url input, redirect-following, opt-in waf/fuzz flags, and a task pipeline of katana, conditional ffuf (using apiroutes), conditional wafw00f, and httpx.
api scan definition
secator/configs/scans/api.yaml
New scan chaining api_discover into url_params_fuzz and url_vuln, restricting the latter two to verified URLs.
Integration test fixtures
tests/integration/inputs.py, tests/integration/outputs.py
Adds api_discover and api entries to input targets and expected outputs.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Scanner as "api scan"
    participant Discover as "api_discover workflow"
    participant Katana
    participant Ffuf
    participant Wafw00f
    participant Httpx
    participant Fuzz as "url_params_fuzz"
    participant Vuln as "url_vuln"

    Scanner->>Discover: run(url)
    Discover->>Katana: crawl endpoints
    Discover->>Ffuf: brute-force routes (apiroutes, if fuzz)
    Discover->>Wafw00f: fingerprint WAF (if waf)
    Discover->>Httpx: probe endpoints (unverified urls)
    Discover-->>Scanner: verified urls
    Scanner->>Fuzz: target verified urls
    Scanner->>Vuln: target verified urls
Loading

Poem

A rabbit hops through routes anew,
Katana crawls, ffuf digs too,
WAF is sniffed, httpx checks true,
Verified URLs pass on through 🐇
Discover, fuzz, and vuln in queue!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding the api_discover workflow and api scan.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch workflow-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
secator/config.py (1)

171-172: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded dated URL will never actually refresh monthly.

Assetnote regenerates and publishes a new dated file each month, but the old dated files stay live indefinitely on the CDN rather than being replaced. Pinning to httparchive_apiroutes_2026_06_27.txt means this wordlist is frozen at that exact snapshot forever — it won't 404, but it also won't ever pick up new data despite the "regenerated monthly" comment implying freshness.

Consider tracking this with a periodic bump reminder/CI check, or investigating whether Assetnote exposes a stable "latest" alias.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@secator/config.py` around lines 171 - 172, The apiroutes entry in config is
pinned to a dated Assetnote CDN file, so it will never auto-refresh despite the
monthly-regenerated comment. Update the config handling around the apiroutes
constant to avoid hardcoding a snapshot URL; either switch to a stable “latest”
alias if one exists or add a clear periodic update mechanism/check tied to the
apiroutes source so the dataset stays current. Use the apiroutes key in
secator/config.py to locate the mapping.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@secator/config.py`:
- Around line 171-172: The apiroutes entry in config is pinned to a dated
Assetnote CDN file, so it will never auto-refresh despite the
monthly-regenerated comment. Update the config handling around the apiroutes
constant to avoid hardcoding a snapshot URL; either switch to a stable “latest”
alias if one exists or add a clear periodic update mechanism/check tied to the
apiroutes source so the dataset stays current. Use the apiroutes key in
secator/config.py to locate the mapping.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea243ad9-a428-4ef0-bba2-4509cf7a054b

📥 Commits

Reviewing files that changed from the base of the PR and between 2c6d2e8 and e792f26.

📒 Files selected for processing (5)
  • secator/config.py
  • secator/configs/scans/api.yaml
  • secator/configs/workflows/api_discover.yaml
  • tests/integration/inputs.py
  • tests/integration/outputs.py

When api_discover finds an exposed OpenAPI/Swagger spec, the new --spec option
routes it to nuclei with input-mode=openapi + DAST fuzzing, which parses the
spec and fuzzes every documented endpoint with the correct method/parameters.
This recovers the contextual API testing kiterunner used to provide, using a
maintained tool already integrated in secator (no new dependency).

- nuclei task: add a `dast` flag (-dast) to enable fuzzing templates.
- api_discover.yaml: add --spec option and a nuclei step targeting discovered
  spec URLs (openapi/swagger/api-docs), gated behind --spec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary

Adds the **OpenAPI-spec handoff** to `api_discover`: when discovery
finds an exposed OpenAPI/Swagger spec, hand it off to **nuclei**
(already integrated) to parse the spec and DAST-fuzz every documented
endpoint.

This recovers the *contextual* API testing that kiterunner used to
provide (correct method + parameters per route) — but with a
**maintained tool already in secator**, so **no new dependency**.

> Stacked on #1268 (`workflow-api`). Base will be retargeted to `main`
once #1268 merges.

## What's included

- **`secator/tasks/nuclei.py`** — new `dast` flag (`-dast`) to enable
nuclei's fuzzing templates (required to fuzz OpenAPI endpoints).
Defaults to off; no change to existing behavior.
- **`secator/configs/workflows/api_discover.yaml`** — new `--spec`
option and a `nuclei` step that targets discovered spec URLs (`openapi`
/ `swagger` / `api-docs`) with `input_mode=openapi` + `dast`. Gated
behind `--spec` (off by default), so pure discovery is unchanged.

## How it works

```
api_discover finds /openapi.json  ──(--spec)──►  nuclei -u <spec-url> -input-mode openapi -dast
(katana / ffuf --fuzz)                            parses the spec, fuzzes every documented endpoint
```

Typical usage: `secator w api_discover <url> --fuzz --spec` (fuzz
surfaces the spec, --spec scans it).

## Design notes

- **Why nuclei and not a new tool?** nuclei natively supports
OpenAPI/Swagger input (`-input-mode openapi`, its SpecDownloader fetches
a remote spec URL) and DAST fuzzing (`-dast`). Adding
schemathesis/CATS/apifuzzer would either duplicate this or drag in an
unmaintained tool / Java runtime — against secator's design principle
#1.
- **Separation of concerns:** the step is optional and flag-gated,
consistent with how `url_crawl` gates its optional trufflehog step.

## Testing

- Command generation verified: `nuclei ... -input-mode openapi -dast`
emitted correctly.
- `api_discover` loads and builds with `--spec` (tasks: katana, ffuf,
wafw00f, httpx, nuclei).
- nuclei unit test passes (no regression from the `dast` flag).
- `flake8 secator/tasks/nuclei.py` clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant