* burpsuite-project-parser: fail rather than report an unverified search as clean
Burp ignores flags it does not recognise, so without the parser
extension it starts normally and drops the query. The script streamed
whatever came back and exited 0, so a missing extension was
indistinguishable from a search that matched nothing.
Output now streams through awk, which classifies it: non-JSON on the
first line means the flags were dropped (exit 4), and no output at all
means an empty result set and an unloaded extension cannot be told
apart (exit 3, stated plainly rather than reported as success). Burp's
own non-zero exits propagate instead of being masked. SIGPIPE from a
downstream head or jq is not a failure -- the documented workflows do
that deliberately.
set +e around the pipeline rather than '|| true', which is a command of
its own and resets PIPESTATUS before it can be read.
SKILL.md documents the exit codes, notes that '0 0' from the size check
is not a size to act on, and adds a rationalization for reading an
empty search as absence of traffic.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* burpsuite-project-parser: classify the whole stream, not the first line
Three defects in the first-line check, all in the same place.
The pattern accepted `{` or `[`, and `[main] INFO burp.StartBurp - ...`
is very common Java stdout. With the extension unloaded that first line
passed as JSON, awk exited 0, and the banner went to stdout as a
verified clean result -- the exact state this branch exists to prevent,
through a one-character widening.
The opposite direction was worse: a working install that prints a
licence or startup line before the JSON set not_json on line 1 and
exited 4, telling the agent the extension is missing and to install it
before trusting any result. Every documented workflow would have failed
on a setup that worked before this branch. A blank first line did the
same, with an empty string in the diagnostic.
Tightening to `{` trades one for the other, so the check is now over the
whole stream: count lines that are JSON objects, fail only when that
count is zero. A preamble is tolerated, a log line is not mistaken for
data, and only JSON objects reach stdout -- everything else goes to
stderr, so a downstream grep or jq cannot match a banner.
SKILL.md also now says the exit code is invisible through a pipe, since
nearly every documented example ends in | jq or | head and reports that
command's status. stderr is the reliable signal; pipefail and
PIPESTATUS are shown for reading the code itself.
Verified against the stub: JSON 0, empty 3, banner 4, [main] INFO log 4,
licence preamble then JSON 0, blank first line 0, Burp exit 7
propagated, SIGPIPE clean, banner text absent from stdout.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* burpsuite-project-parser: flush per line, and pin the classification with a suite
Two gaps in the previous commit, both found by testing rather than reading.
awk block-buffers when its stdout is a pipe, and every documented workflow
pipes. So the claim that streaming through awk keeps `| jq` and `| head`
unbuffered was wrong in its second half: a long search over a large project
printed nothing until Burp exited, where the bare `exec` this replaced
streamed line by line. `fflush()` after each emitted object restores that for
one write per line. The temp-file half of the claim was right and stands.
The change also shipped with no test, while arguing from the AGENTS.md rule
that a checker inspecting zero items must not pass -- the same paragraph asks
for a fixture proving the checker still detects its target. The suite supplies
it: 16 assertions over a stub standing in for Burp, covering the working case,
exit 3 on no output, exit 4 on a startup banner and on a `[main] INFO` line
that a leading-bracket check would have taken for JSON, a banner ahead of real
JSON still succeeding, Burp's own non-zero status propagating with and without
output, SIGPIPE from a downstream `head` producing no stderr noise, and the
streaming behaviour above.
Verified the suite bites by mutating the script three ways -- dropping
fflush(), turning exit 3 into exit 0, and letting non-JSON reach stdout. All
three turn it red. The assertion count is asserted for the same reason the
script refuses to report an unverified empty result.
Still not covered, and recorded at the foot of the suite: the stub proves the
classification, not Burp's behaviour with the extension missing. If Burp
launches and waits rather than exiting, neither 3 nor 4 fires and the script
blocks. Settling that needs Burp Pro and a renamed extension JAR.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* burpsuite-project-parser: cap the stderr mirror, and make exit 3 resolvable
Two problems with the previous commit, both in the case it exists to handle.
When no line is JSON -- the missing-extension case -- awk never writes to
stdout, so it never takes SIGPIPE, so a documented downstream `head -c 50000`
cannot close the pipeline early. It blocks to EOF while every line Burp
produced is mirrored to stderr, which the caller captures and which no
documented output limit covers. Measured on a 100k-line non-JSON stream behind
a `head -c 200` that could not terminate: 8,389,235 bytes across 100,005 lines.
Under the bare `exec` this replaced, those bytes went to stdout where `head`
truncated them, so this was a regression in the exact scenario the change
targets. Capped at 20 lines plus a suppressed count, the same stream now yields
2,014 bytes across 26 lines. Exit codes are unchanged.
Exit 3's remediation was not something the agent reading it could carry out.
`allowed-tools` is `Bash Read` and Burp runs headless, so "Check Burp Suite ->
Extensions" has no GUI to open, and re-running returns 3 again. That leaves
deciding the extension is loaded and reporting "nothing found" -- the false
negative this whole script exists to prevent, reached through its own
instructions, and reached often, since exit 3 is the common case for any
narrow regex. Both the script and SKILL.md now give a control query instead: a
selector broad enough that it must return rows if the parser works at all, run
against the same project. Rows mean the narrow query genuinely matched nothing;
exit 3 again means nothing comes back through the parser at all; exit 4 means
the flags were dropped. Asking the user to check the GUI is named as the
legitimate answer where the control is inconclusive -- guessing is not.
The suite gains two assertions for the cap, since an uncapped mirror looks
identical to a capped one on every stream the other 16 use. Verified by
removing the cap: the suite goes red.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* burpsuite-project-parser: bound the mirror by length, skip blank lines, fix the control query
Three fixes to the previous commit, all in the parts that commit added.
The control query it introduced for exit 3 told the agent to run bare
`proxyHistory | head -n 1` -- the one selector this skill bans outright.
SKILL.md calls it "NEVER DO THIS" (:125), "NEVER use this directly" (:183,
:191), notes it "can return gigabytes" (:100), and sets a hard rule that body
content over 1000 chars must never enter context (:140). `head -n 1` does not
soften that; it delivers exactly one complete record, request and response and
bodies, which the file's own table says can be megabytes. And exit 3 is the
common case, so the advice would have fired constantly.
`proxyHistory.request.headers` answers the same question -- does anything at
all come back through the parser -- at the under-1KB-per-record the file
documents at :106.
The stderr cap bounded how many lines were mirrored, not how long one could
be, so a single very long line passed the count check and was written in full.
SKILL.md:217 already records that shape ("A single 10MB response on one line
will show high byte count but only 1 line"), and those bytes are captured HTTP
traffic on a channel the documented `head -c` on stdout cannot reach. Lines are
now truncated at 500 characters with the original length reported.
A whitespace-only line was counted as non-JSON, so one trailing newline turned
an empty-but-correct result into exit 4 -- "the extension is not loaded",
wrongly, on a healthy install -- and mirrored a diagnostic with nothing after
the colon, which is the empty-diagnostic defect e3dd90c set out to remove.
Blank lines are now skipped before the count.
Three assertions added, taking the suite to 21. Both new guards are
mutation-checked: removing the length cap or the blank-line skip turns the
suite red.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Burp Suite Project Parser
Search and extract data from Burp Suite project files (.burp) for use in Claude
Author: Will Vandevanter
Prerequisites
- Burp Suite Professional - Required for project file support
- burpsuite-project-file-parser extension - Must be installed in Burp Suite (Available: https://github.com/BuffaloWill/burpsuite-project-file-parser)
- jq (optional) - Recommended for formatting/filtering JSON output
When to Use
Use this skill when you need to get the following from a Burp project:
- Search response headers or bodies using regex patterns
- Extract security audit findings and vulnerabilities
- Dump proxy history or site map data for analysis
- Programmatically analyze HTTP traffic captured by Burp Suite
Trigger phrases: "search the burp project", "find in burp file", "what vulnerabilities in the burp", "get audit items from burp"
What It Does
This skill provides CLI access to Burp Suite project files through the burpsuite-project-file-parser extension:
- Search headers/bodies - Find specific patterns in captured HTTP traffic using regex
- Extract audit items - Get all security findings with severity, confidence, and URLs
- Dump traffic data - Export proxy history and site map entries as JSON
- Filter output - Use sub-component filters to optimize performance on large projects
Installation
/plugin install trailofbits/skills/plugins/burpsuite-project-parser
Usage
Inside Claude Code, run /burpsuite-project-parser:burp-search — it takes the same
project path and flags as the script below.
Base command:
scripts/burp-search.sh /path/to/project.burp [FLAGS]
Available Commands
| Command | Description | Output |
|---|---|---|
auditItems |
Extract all security findings | JSON: name, severity, confidence, host, port, protocol, url |
proxyHistory |
Dump all captured HTTP traffic | Complete request/response data |
siteMap |
Dump all site map entries | Site structure |
responseHeader='.*regex.*' |
Search response headers | JSON: url, header |
responseBody='.*regex.*' |
Search response bodies | Matching content |
Sub-Component Filters
For large projects, filter to specific data to improve performance:
proxyHistory.request.headers # Only request headers
proxyHistory.request.body # Only request body
proxyHistory.response.headers # Only response headers
proxyHistory.response.body # Only response body
Same patterns work with siteMap.*
Examples
Search for CORS headers:
scripts/burp-search.sh project.burp "responseHeader='.*Access-Control.*'"
Get all high-severity findings:
scripts/burp-search.sh project.burp auditItems | jq 'select(.severity == "High")'
Find server signatures:
scripts/burp-search.sh project.burp "responseHeader='.*(nginx|Apache|Servlet).*'"
Extract request URLs from proxy history:
scripts/burp-search.sh project.burp proxyHistory.request.headers | jq -r '.request.url'
Search for HTML forms:
scripts/burp-search.sh project.burp "responseBody='.*<form.*action.*'"
Output Format
All output is JSON, one object per line. Pipe to jq for formatting or use grep for filtering:
scripts/burp-search.sh project.burp auditItems | jq .
scripts/burp-search.sh project.burp auditItems | grep -i "sql injection"