Imported from gandli/burpsuite-extension-skill (
SKILL.md). Install upstream withnpx skills add gandli/burpsuite-extension-skill. Copyright stays with the author (MIT).
Burp Suite Extension Development Skill
Develop Burp Suite extensions in Java (Montoya API) or Python (Jython).
Quick Start
When to Use This Skill
Use this skill when you need to:
- Create a new Burp Suite extension from scratch
- Implement HTTP traffic interception or modification
- Build custom vulnerability scanner checks
- Generate custom intruder payloads
- Add UI tabs or context menus to Burp Suite
What This Skill Provides
- Project Templates: Ready-to-use Java and Python templates
- Multi-Platform Setup: macOS, Windows, and Linux guides
- Best Practices: Error handling, performance, and security
- Official Resources: Links to PortSwigger documentation
Choose Your Language
| Feature | Java (Montoya API) | Python (Jython) |
|---|---|---|
| API Version | Montoya API (New) | Extender API (Legacy) |
| Java Version | JDK 21+ | JDK 17+ |
| Performance | Best | Slower |
| Setup Complexity | Medium | Simple |
| Best For | Production extensions | Quick scripts/prototypes |
Recommendation: Use Java for production extensions. Use Python for rapid prototyping.
Environment Setup
macOS
# Install Java 21
brew install openjdk@21
echo 'export PATH="/opt/homebrew/opt/openjdk@21/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# Verify installation
java -version
# Install IntelliJ IDEA (optional)
brew install --cask intellij-idea-ce
Windows
# Install Java 21
winget install EclipseAdoptium.Temurin.21.JDK
# Set environment variables
$env:JAVA_HOME = "C:\Program Files\Eclipse Adoptium\jdk-21"
$env:Path += ";$env:JAVA_HOME\bin"
# Verify installation
java -version
Linux (Ubuntu/Debian)
# Install Java 21
sudo apt-get update
sudo apt-get install temurin-21-jdk
# Verify installation
java -version
# Install IntelliJ IDEA (optional)
sudo snap install intellij-idea-community --classic
Path A: Java Development (Recommended)
Prerequisites
- Burp Suite - Download Community Edition
- Java JDK 21+ - Download from Adoptium
- IntelliJ IDEA (Optional) - Download
Quick Start with Starter Project
# Clone the official starter project
git clone https://github.com/PortSwigger/burp-extensions-montoya-api-starter.git my-extension
cd my-extension
# Build
./gradlew build # macOS/Linux
gradlew.bat build # Windows
# Output: build/libs/my-extension.jar
Load Extension in Burp Suite
- Open Burp Suite
- Go to Extensions → Installed
- Click Add
- Select Java as extension type
- Browse to
build/libs/my-extension.jar - Click Next
Key Interfaces
Extension Entry Point
package burp.extension;
import burp.api.montoya.BurpExtension;
import burp.api.montoya.MontoyaApi;
public class MyExtension implements BurpExtension {
@Override
public void initialize(MontoyaApi api) {
api.extension().setName("My Extension");
api.logging().logToOutput("Extension loaded successfully!");
}
}
HTTP Proxy Handler
import burp.api.montoya.proxy.http.InterceptedRequest;
import burp.api.montoya.proxy.http.ProxyRequestHandler;
import burp.api.montoya.proxy.http.ProxyRequestReceivedAction;
import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction;
public class MyProxyHandler implements ProxyRequestHandler {
private final MontoyaApi api;
public MyProxyHandler(MontoyaApi api) {
this.api = api;
}
@Override
public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) {
api.logging().logToOutput("Request: " + interceptedRequest.url());
return ProxyRequestReceivedAction.continueWith(interceptedRequest);
}
@Override
public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) {
return ProxyRequestToBeSentAction.continueWith(interceptedRequest);
}
}
Scanner Check
import burp.api.montoya.scanner.AuditResult;
import burp.api.montoya.scanner.ScanCheck;
import burp.api.montoya.http.message.HttpRequestResponse;
public class MyScanCheck implements ScanCheck {
private final MontoyaApi api;
public MyScanCheck(MontoyaApi api) {
this.api = api;
}
@Override
public AuditResult passiveAudit(HttpRequestResponse baseRequestResponse) {
// Implement passive scan logic
return null;
}
@Override
public AuditResult activeAudit(HttpRequestResponse baseRequestResponse,
AuditResult auditResult) {
// Implement active scan logic
return null;
}
}
Registering Components
public class MyExtension implements BurpExtension {
@Override
public void initialize(MontoyaApi api) {
api.extension().setName("My Extension");
// Register components
api.proxy().registerRequestHandler(new MyProxyHandler(api));
api.scanner().registerScanCheck(new MyScanCheck(api));
api.userInterface().registerSuiteTab("My Extension", new MyTab());
}
}
Project Structure
my-extension/
├── src/main/java/
│ └── burp/extension/
│ ├── MyExtension.java
│ ├── MyProxyHandler.java
│ └── MyScanCheck.java
├── build.gradle
├── settings.gradle
└── README.md
build.gradle
plugins {
id 'java'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'net.portswigger.burp.extensions:montoya-api:2.3.+'
}
tasks.named('jar') {
manifest {
attributes 'Extension-ClassName': 'burp.extension.MyExtension'
}
}
Path B: Python Development (Jython)
Prerequisites
- Burp Suite - Download Community Edition
- Jython - Download Standalone JAR
Setup Jython in Burp Suite
- Open Burp Suite
- Go to Settings → Extensions → Python Environment
- Set path to Jython JAR file
Python Extension Template
# burp_extender.py
from burp import IBurpExtender
from burp import IHttpListener
from java.io import PrintWriter
class BurpExtender(IBurpExtender):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("My Python Extension")
# Setup output streams
self._stdout = PrintWriter(callbacks.getStdout(), True)
self._stderr = PrintWriter(callbacks.getStderr(), True)
self._stdout.println("Extension loaded!")
# Register listeners
callbacks.registerHttpListener(HttpListener(self))
class HttpListener(IHttpListener):
def __init__(self, extender):
self._extender = extender
self._callbacks = extender._callbacks
self._helpers = extender._helpers
def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
try:
if messageIsRequest:
requestInfo = self._helpers.analyzeRequest(messageInfo)
url = str(requestInfo.getUrl())
self._extender._stdout.println("Request: " + url)
except Exception as e:
self._extender._stderr.println("Error: " + str(e))
Load Python Extension
- Open Burp Suite
- Go to Extensions → Installed → Add
- Select Python as extension type
- Browse to
burp_extender.py - Click Next
Best Practices
1. Error Handling
Always wrap your code in try-catch blocks to prevent extension crashes:
Java:
@Override
public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) {
try {
// Your logic here
return ProxyRequestReceivedAction.continueWith(interceptedRequest);
} catch (Exception e) {
api.logging().logToError("Error: " + e.getMessage());
return ProxyRequestReceivedAction.continueWith(interceptedRequest);
}
}
Python:
def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
try:
# Your logic here
except Exception as e:
self._extender._stderr.println("Error: " + str(e))
2. Performance
- Never block in HTTP listeners - use async processing
- Cache results for repeated operations
- Limit scope - check
isInScope()before heavy processing
3. Logging
Use Burp's logging API instead of System.out:
Java:
api.logging().logToOutput("Info message");
api.logging().logToError("Error message");
Python:
self._stdout.println("Info message")
self._stderr.println("Error message")
4. Scope Checking
Only process in-scope requests to improve performance:
Java:
if (api.scope().isInScope(request.url())) {
// Process request
}
Python:
if self._callbacks.isInScope(requestInfo.getUrl()):
# Process request
5. Resource Cleanup
Register unload handlers to clean up resources:
api.extension().registerUnloadHandler(() -> {
api.logging().logToOutput("Extension unloading...");
// Cleanup resources
});
Debugging
Java (IntelliJ)
- Add JVM argument to Burp Suite:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 - In IntelliJ: Run → Edit Configurations → Remote JVM Debug
- Set port to 5005
- Start Burp Suite with JVM argument
- Attach debugger in IntelliJ
Python
- Use
self._stdout.println()for logging - Check Extensions → Output tab in Burp Suite
Common Issues
| Issue | Solution |
|---|---|
| Extension won't load | Check Java version (21+ required for Montoya API) |
| ClassNotFoundException | Verify Montoya API dependency in build.gradle |
| Python import errors | Check Jython version and path configuration |
| No HTTP traffic | Ensure listener is registered in initialize() |
| Performance issues | Use async processing, limit scope with isInScope() |
| OutOfMemoryError | Increase JVM heap size: -Xmx1g |
Limitations
- Java Extensions: Require JDK 21+ for Montoya API
- Python Extensions: Use Jython (Python 2.7 compatible), not Python 3
- Network: Some features require Burp Suite Professional
- Platform: Extensions run inside Burp Suite JVM
Official Resources
Documentation
API References
Community
Examples
Example 1: Simple Request Logger
Log all HTTP requests passing through Burp Proxy:
public class RequestLogger implements ProxyRequestHandler {
private final MontoyaApi api;
public RequestLogger(MontoyaApi api) {
this.api = api;
}
@Override
public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) {
api.logging().logToOutput("[" + interceptedRequest.httpService().host() + "] " +
interceptedRequest.method() + " " + interceptedRequest.url());
return ProxyRequestReceivedAction.continueWith(interceptedRequest);
}
@Override
public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) {
return ProxyRequestToBeSentAction.continueWith(interceptedRequest);
}
}
Example 2: Custom Header Check
Detect missing security headers:
public class SecurityHeaderCheck implements ScanCheck {
private final MontoyaApi api;
public SecurityHeaderCheck(MontoyaApi api) {
this.api = api;
}
@Override
public AuditResult passiveAudit(HttpRequestResponse baseRequestResponse) {
HttpResponse response = baseRequestResponse.response();
if (response != null) {
List<String> headers = response.headers();
boolean hasXFrameOptions = headers.stream()
.anyMatch(h -> h.toLowerCase().contains("x-frame-options"));
if (!hasXFrameOptions) {
// Report issue
}
}
return null;
}
@Override
public AuditResult activeAudit(HttpRequestResponse baseRequestResponse,
AuditResult auditResult) {
return null;
}
}
FAQ
Q: Which language should I choose? A: Use Java for production extensions (better performance, newer API). Use Python for quick scripts and prototyping.
Q: Can I use Python 3? A: No, Burp Suite uses Jython which supports Python 2.7 syntax only.
Q: Do I need Burp Suite Professional? A: Community Edition works for most extensions. Some features (like scanner) require Professional.
Q: How do I debug my extension? A: Use IntelliJ remote debugging for Java. Use print statements and Burp's Output tab for Python.