diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8eca9ed..bc7abc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,13 +27,13 @@ jobs: - name: Confirm fat JAR run: | set -e - test -f target/burp-api-scanner-2.1.0.jar - ls -lh target/burp-api-scanner-2.1.0.jar + test -f target/burp-api-scanner-2.1.1.jar + ls -lh target/burp-api-scanner-2.1.1.jar - name: Upload JAR uses: actions/upload-artifact@v4 with: name: burp-api-scanner-${{ github.sha }} - path: target/burp-api-scanner-2.1.0.jar + path: target/burp-api-scanner-2.1.1.jar if-no-files-found: error retention-days: 30 diff --git a/BURP_DAST_GUIDE.md b/BURP_DAST_GUIDE.md index 010b947..4e13b51 100644 --- a/BURP_DAST_GUIDE.md +++ b/BURP_DAST_GUIDE.md @@ -16,12 +16,12 @@ The extension is shipped as a single fat JAR. Build with: mvn clean package -DskipTests ``` -Output: `target/burp-api-scanner-2.1.0.jar`. +Output: `target/burp-api-scanner-2.1.1.jar`. In DAST: 1. **Settings → Extensions → Add extension** -2. Upload `burp-api-scanner-2.1.0.jar` +2. Upload `burp-api-scanner-2.1.1.jar` 3. Enable the extension There is no per-DAST configuration — once loaded and enabled, the @@ -35,7 +35,7 @@ healthy load it reads: ``` ==================================== -Advanced API Security Scanner v2.1.0 +Advanced API Security Scanner v2.1.1 OWASP API Security Top 10 (2023) coverage Edition: Burp Suite DAST AI features: enabled (or "disabled" if Burp AI is off) @@ -101,7 +101,7 @@ Kill switches (JVM system properties on the DAST process): Before running production scans: - [ ] Extension JAR loaded and enabled in Settings → Extensions -- [ ] Banner shows `v2.1.0`, the correct `Edition:`, and the expected +- [ ] Banner shows `v2.1.1`, the correct `Edition:`, and the expected `AI features:` state - [ ] Scan configuration includes Active + Passive audit (passive-only will not surface any API5/API7 findings) diff --git a/CLAUDE.md b/CLAUDE.md index d2fc761..2bfe8dd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,7 +13,7 @@ src/main/java/com/security/burp/ ├── BurpExtender.java # Entry point. Declares EnhancedCapability.AI_FEATURES, │ # registers checks, wires the unloading handler. ├── ai/ # AI integration layer (optional, gates on api.ai().isEnabled()) -│ ├── AiClient.java # wrapper around api.ai() with executor + 2s timeout + cache +│ ├── AiClient.java # wrapper around api.ai(): bounded thread pool + 2s timeout + cache │ ├── AiTriage.java # passive-finding KEEP/SUPPRESS filter │ └── AiFieldDiscovery.java # contextual privileged-field suggestions for mass assignment ├── checks/ @@ -44,7 +44,7 @@ export PATH="$JAVA_HOME/bin:$PATH" mvn clean package -DskipTests ``` -Output: `target/burp-api-scanner-2.1.0.jar` (~370 KB fat JAR). +Output: `target/burp-api-scanner-2.1.1.jar` (~370 KB fat JAR). Load in Burp via **Extensions → Installed → Add → Java**. @@ -88,10 +88,13 @@ v2 rewrite, and breaking these breaks the property she cared about headers EXCEPT Host. See `BrokenObjectAuthCheck.sendWithReplacedId` and `DeprecatedVersionProbeCheck.rebuildAtVersion` for the right shape. -3. **AI calls must time out.** `api.ai().prompt().execute(...)` is - synchronous and can block indefinitely. `AiClient` runs prompts on a - dedicated daemon executor with a 2s hard timeout, so one stuck - prompt cannot block a scan thread. PortSwigger BApp criterion #5. +3. **AI calls must time out AND run on a multi-worker pool.** + `api.ai().prompt().execute(...)` is synchronous and can block + indefinitely. `AiClient` runs prompts on a bounded daemon thread + pool (4 workers) with a 2s hard timeout. The pool must have several + workers, not one: with a single worker, concurrent scan threads + queue and can time out while still *waiting in the queue* rather + than during the actual call. PortSwigger BApp criterion #5. 4. **Use `edition.displayName()`, not the raw enum.** The Montoya enum constant is `BurpSuiteEdition.ENTERPRISE_EDITION` for backward diff --git a/README.md b/README.md index 84ad10f..8964e9b 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ registered only under Professional. mvn clean package -DskipTests ``` -Produces `target/burp-api-scanner-2.1.0.jar`. Load via **Extensions → +Produces `target/burp-api-scanner-2.1.1.jar`. Load via **Extensions → Installed → Add → Java**. Requires JDK 17+ (Montoya API requirement) and Maven 3.6+. @@ -25,7 +25,7 @@ The banner in the extension's Output tab will look like: ``` ==================================== -Advanced API Security Scanner v2.1.0 +Advanced API Security Scanner v2.1.1 OWASP API Security Top 10 (2023) coverage Edition: Burp Suite Professional AI features: enabled diff --git a/pom.xml b/pom.xml index 875fc87..54d5099 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.security burp-api-scanner - 2.1.0 + 2.1.1 jar Advanced API Security Scanner diff --git a/src/main/java/com/security/burp/BurpExtender.java b/src/main/java/com/security/burp/BurpExtender.java index cc79902..6905e81 100644 --- a/src/main/java/com/security/burp/BurpExtender.java +++ b/src/main/java/com/security/burp/BurpExtender.java @@ -156,7 +156,7 @@ private void registerUnloadingHandler(MontoyaApi api, private void logBanner(MontoyaApi api, BurpSuiteEdition edition, boolean aiAvailable) { api.logging().logToOutput("===================================="); - api.logging().logToOutput(EXTENSION_NAME + " v2.1.0"); + api.logging().logToOutput(EXTENSION_NAME + " v2.1.1"); api.logging().logToOutput("OWASP API Security Top 10 (2023) coverage"); api.logging().logToOutput("Edition: " + edition.displayName()); api.logging().logToOutput("AI features: " + (aiAvailable ? "enabled" : "disabled")); diff --git a/src/main/java/com/security/burp/ai/AiClient.java b/src/main/java/com/security/burp/ai/AiClient.java index c5616e3..f1a6ce2 100644 --- a/src/main/java/com/security/burp/ai/AiClient.java +++ b/src/main/java/com/security/burp/ai/AiClient.java @@ -12,17 +12,22 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; /** * Thin wrapper around {@code api.ai()}. * *

Three responsibilities: *