Penjester beta

Burp Suite extension · access control

Manual pentesting in the AI era
needs an upgrade.

No more four browser windows. No more swapping sessions by hand to check who can read what.

Browse as each of your accounts and Penjester replays everything you did as everyone else, then proves what came back that should not have. It runs inside Burp Suite, opens to your own local AI model over MCP, and no model ever sends a request.

A personal tool, built to speed up manual access-control testing and do in one workbench what otherwise takes a stack of single-purpose extensions.

IDOR · privilege escalation · tenant isolation 51 tools over MCP Any OpenAI-compatible local model, or Claude 0 requests composed by a model

What it prints

The output is a board, so this page is one too

Endpoint Run 14 · as bob · org acme
GET /api/teams/{id}/details object id taken from alice's own traffic, never generated aliceowner bobactor got through
POST /privileges/userRoles write, confirmed by reading the role back as the owner aliceowner bobactor got through
GET /org/billing/invoices 403, and the denial fingerprint matches the one you declared aliceowner bobactor blocked
GET /zm/mail/{id} 200, but it returned bob's own mail, so the query is scoped aliceowner bobactor own data
GET /reports/export?range=90d bodies differ by 31%, and this endpoint's own noise floor is 29% aliceowner bobactor unclear
POST /org/members/remove path denylist: automation may not call it, you still can aliceowner — not sent
The verdicts, in the words Burp shows them in got through the other account's data came back blocked refused, so the control held own data its own data came back, so the query is scoped unclear unresolved, needs a human already had access it could reach the object anyway, so the test proves nothing ignores the id the same reply whatever the identifier is not sent no comparison was possible. A guardrail stopped it, so there is no verdict to give
389 of 412 endpoints replayed  ·  23 refused, each with its reason  ·  the twenty-three are in the report, because a findings list that hides them reads as an all-clear

The problem

Authorization is the bug class every tool skips

SQL injection and XSS have good scanners, because a payload either reflects or it does not, and one session is enough to tell. Authorization is different. To know that /invoices/4471 is alice's and that bob should not have it, a tool needs bob's session, alice's session, and some notion of who owns what.

That is the entire gap. It is also why broken access control sits at the top of the OWASP Top 10 and still gets found by hand, one identifier at a time, by somebody with four browser containers open.

GET /api/teams/32567000000022002/details
owner  alice   200  59,534 bytes
actor  bob     200  57,021 bytes

93% alike, 4% apart, so a scanner stops here and
calls it a finding.


owner-identifying values returned 0 of 20
so it is not one. bob got its own page.

Method

Six steps, and none of them guess

01 · Watch

Whose session was that

Browse normally, as each account. Penjester attributes every request to the session that carried it, including when two accounts use cookies with different names, which is the usual case.

02 · Replay

As everybody else

Every recorded request goes out again as every other account, with the whole credential set exchanged: cookies, auth headers, body tokens, and all three anti-forgery carriers.

03 · Prove

A 200 is not a finding

Penjester sends an identifier belonging to nobody, repeats the request, and strips every credential, then asks whether the account was already entitled to the object before any of this ran.

04 · Account

Say what was skipped

Every refusal, skip and guardrail is recorded with its reason. A findings list that does not say what was never reached reads as an all-clear, and an all-clear nobody earned is the most expensive thing a security tool produces.

05 · Disprove

Could you have known the id

An IDOR on a UUID nobody can obtain is not a finding. Penjester searches every response your account genuinely received for that identifier and records how many it read. A searched silence, not an assumed one.

06 · Hand over

With the request behind it

Findings arrive in Repeater with the numbers that settled them. Right-click any row to reproduce it by hand, swap an identifier, or send it as somebody else.

Evidence

A finding that cites its own numbers

“Similar in shape and length” is the sentence that gets a report sent back. Penjester carries every number it measured all the way to the write-up: the size gap, the threshold it was weighed against, where that threshold came from, and how many of the owner's identifying values came back out of how many existed.

The noise floor is learned per endpoint from its own repeated reads, so an endpoint that swings 19 % between two identical requests is not judged by the same bar as one that is byte-stable. Shape is never decisive on its own. That rule is a line of code, not a guideline.

F-014  Cross-account read

What settles it
owner-identifying values returned 3 of 20
  present in alice's reply, absent from bob's own

Measurements
body similarity 93%
size gap 4%, against 19% measured from
  this endpoint's own repeat reads
this reply 57,021 bytes, owner's 59,534

Probes
✓ nonexistent identifier → 404
✓ repeated → identical
✓ no credentials → 401

In Burp

One extension, not a drawer of them

Penjester is a Burp extension, not a separate console. Your proxy, your browser, your Repeater, your project file. One workbench in place of a stack of extensions.

The Knowledge tab, the application as a tree with one endpoint's attack vectors
assets/img/knowledge.png
Burp → Penjester → Knowledge, a host expanded · 1400×950
Knowledge. What the application is and what has not been checked, pinned to endpoints and saved in the project file. Here, one endpoint's nature, its attack vectors, and the personal data it returned.
The Map tab, the application collapsed into endpoint templates
assets/img/tab-map.png
Burp → Penjester → Map, a host expanded · 1200×760
Map. Thousands of requests collapsed into endpoint templates, the interesting ones flagged.
The History tab, every request with the account that carried it
assets/img/tab-history.png
Burp → Penjester → History, mixed identities · 1200×760
History. Every request with whose session carried it, and each cross-account replay's result.

What it will not do

The limits are the product

Most of what makes Penjester trustworthy is what it refuses to do. These are not roadmap items, and none of them is a setting.

  • — No model composes a request A language model chooses which feature to look at and which result to write up. It never builds a request, never picks a payload, never gets a shell. One function sends everything, and it is not reachable from a prompt.
  • — Nothing runs on its own A run starts because somebody typed the command. There is no daemon, no schedule, and no “it was already scanning when I opened it”.
  • — No credential reaches a prompt The model is told cookie names. It is never handed a value, and the tool API has no shape that could return one.
  • — No payload scanner SQLi and XSS already have good tools. Access control does not. Penjester stays on the ground nothing else covers, and points Burp's own Scanner at the rest when you ask it to.
  • — No severity score Severity is demonstrated impact, and only somebody who knows what the data is can say it. Penjester suggests a starting point and never a number.

Get started

It is one jar.

Build it, point Burp at it, save two sessions, and browse. The first cross-account result usually arrives before you have finished logging in as the second account.