CONTROLLED SYNTHETIC EXPERIMENT · 17 OCTOBER 2026
Let AI suggest.
Make every test accountable.
An endpoint is a service's doorway. A scanner tries suspicious requests; a fuzzer tries unusual inputs. A useful planner also asks: Which related endpoint, user, and object should we test next?
This small experiment freezes a rules-based plan, runs it against two in-process fixture modes, and checks the exact recorded evidence again. No real service was scanned. No AI model was called.
2 synthetic findings before repair0 after repairOffline replay verified
The ownership test
Alice and Bob each have one private object. First confirm their own objects are readable. Then ask whether Bob can read Alice's object and vice versa. A successful HTTP 200 is the bug here—not a server crash. After the fixture's owner check is enabled, both cross-user requests are denied.
If Bob's cross-user read fails the security check, the frozen plan makes one confirmation request. After repair it skips that branch: the vulnerable run uses 14 fixture requests; the fixed run uses 13. Negative, zero, valid, maximum, excessive and string limits are checked too.
Recorded before / after
| Step | Identity | Endpoint | Vulnerable | Fixed |
|---|---|---|---|---|
| alice-list | alice | /objects | pass | pass |
| bob-list | bob | /objects | pass | pass |
| alice-own | alice | /objects/$alice_id | pass | pass |
| bob-own | bob | /objects/$bob_id | pass | pass |
| bob-reads-alice | bob | /objects/$alice_id | fail | pass |
| confirm-bob-reads-alice | bob | /objects/$alice_id | fail | skipped |
| alice-reads-bob | alice | /objects/$bob_id | fail | pass |
| anonymous-read | anonymous | /objects/$alice_id | pass | pass |
| limit-negative | alice | /objects | pass | pass |
| limit-zero | alice | /objects | pass | pass |
| limit-one | alice | /objects | pass | pass |
| limit-max | alice | /objects | pass | pass |
| limit-over | alice | /objects | pass | pass |
| limit-string | alice | /objects | pass | pass |
What is frozen?
Template versions, policy, inputs, selection scores, branch predicates, source and spec digests, Python version, and request budget. The source snapshot includes both fixture modes; each run identifies which mode it used.
Plan SHA-256: 6f809bacc12b1e04e3e361e99ffbbcddde25c047efd463257dcade1bc13a687d
Inspect the frozen plan
{
"sha256": "6f809bacc12b1e04e3e361e99ffbbcddde25c047efd463257dcade1bc13a687d",
"plan": {
"schema": 1,
"target": "fixture://ownership-lab",
"budget": 14,
"history": [],
"proposal": null,
"policy": {
"max_requests": 14,
"max_seconds": 2,
"methods": [
"GET"
],
"oracle_version": 1,
"redirects": "deny",
"seed": 0,
"target": "fixture://ownership-lab",
"version": 1
},
"decisions": [
{
"template_id": "ownership",
"score": 107,
"cost_upper_bound": 8,
"selected": true
},
{
"template_id": "boundaries",
"score": 74,
"cost_upper_bound": 6,
"selected": true
}
],
"steps": [
{
"id": "alice-list",
"role": "alice",
"path": "/objects",
"query": {},
"oracle": "own-list",
"when": null,
"template_id": "ownership",
"method": "GET"
},
{
"id": "bob-list",
"role": "bob",
"path": "/objects",
"query": {},
"oracle": "own-list",
"when": null,
"template_id": "ownership",
"method": "GET"
},
{
"id": "alice-own",
"role": "alice",
"path": "/objects/$alice_id",
"query": {},
"oracle": "owner-read",
"when": {
"step": "alice-list",
"outcome": "pass"
},
"template_id": "ownership",
"method": "GET"
},
{
"id": "bob-own",
"role": "bob",
"path": "/objects/$bob_id",
"query": {},
"oracle": "owner-read",
"when": {
"step": "bob-list",
"outcome": "pass"
},
"template_id": "ownership",
"method": "GET"
},
{
"id": "bob-reads-alice",
"role": "bob",
"path": "/objects/$alice_id",
"query": {},
"oracle": "private-object",
"when": {
"step": "alice-own",
"outcome": "pass"
},
"template_id": "ownership",
"method": "GET"
},
{
"id": "confirm-bob-reads-alice",
"role": "bob",
"path": "/objects/$alice_id",
"query": {},
"oracle": "private-object",
"when": {
"step": "bob-reads-alice",
"outcome": "fail"
},
"template_id": "ownership",
"method": "GET"
},
{
"id": "alice-reads-bob",
"role": "alice",
"path": "/objects/$bob_id",
"query": {},
"oracle": "private-object",
"when": {
"step": "bob-own",
"outcome": "pass"
},
"template_id": "ownership",
"method": "GET"
},
{
"id": "anonymous-read",
"role": "anonymous",
"path": "/objects/$alice_id",
"query": {},
"oracle": "requires-auth",
"when": {
"step": "alice-own",
"outcome": "pass"
},
"template_id": "ownership",
"method": "GET"
},
{
"id": "limit-negative",
"role": "alice",
"path": "/objects",
"query": {
"limit": -1
},
"oracle": "reject-input",
"when": null,
"template_id": "boundaries",
"method": "GET"
},
{
"id": "limit-zero",
"role": "alice",
"path": "/objects",
"query": {
"limit": 0
},
"oracle": "reject-input",
"when": null,
"template_id": "boundaries",
"method": "GET"
},
{
"id": "limit-one",
"role": "alice",
"path": "/objects",
"query": {
"limit": 1
},
"oracle": "own-list",
"when": null,
"template_id": "boundaries",
"method": "GET"
},
{
"id": "limit-max",
"role": "alice",
"path": "/objects",
"query": {
"limit": 100
},
"oracle": "own-list",
"when": null,
"template_id": "boundaries",
"method": "GET"
},
{
"id": "limit-over",
"role": "alice",
"path": "/objects",
"query": {
"limit": 101
},
"oracle": "reject-input",
"when": null,
"template_id": "boundaries",
"method": "GET"
},
{
"id": "limit-string",
"role": "alice",
"path": "/objects",
"query": {
"limit": "abc"
},
"oracle": "reject-input",
"when": null,
"template_id": "boundaries",
"method": "GET"
}
],
"provenance": {
"templates_sha256": "290617431a680cad3a759cf4a5573c91be47bde0e0537861afab92e556c11384",
"spec_sha256": "ecd978d5cc458da1cf59339fe5e584ccc6331713790cfee1138d6274fcfed9cf",
"fixture_data_sha256": "2f3f55e74d2a8b38cc6bfcc6d91a9b73c4c1437648977ca6b10c1aa89b7daab7",
"executor_sha256": "1a9ba85800d9cf685591556f32861dd230d4f4a960ef9c16c119483079880e81",
"python": "3.14.6",
"model": null,
"prompt": null,
"corpus": "explicit-boundaries-v1"
}
}
}Three different meanings of replay
- Plan re-execution: evaluate the same plan against a reset fixture; branch outcomes may change after repair.
- Offline evidence replay: feed recorded responses through the same request checks and oracles without contacting the fixture. Verified here.
- Live trace replay: resend a recorded sequence to a real authorized service. Not implemented; expired credentials and changed state make this different.
Safety and limits
This page is a static evidence viewer. It has no scan button, target input, server-side function, outgoing scan, or vulnerable public API. The local executor only accepts its exact synthetic fixture URI, uses GET-only fixed paths, caps work at 14 requests and two seconds, rejects unknown proposal fields and redirects, and includes a kill switch.
This is a small architecture proof, not a production security product or evidence that any real endpoints are secure. ZAP, Schemathesis, Nuclei, RESTler, Burp and LLM adapters are research recommendations—not connected integrations.
Recommended next step
Use existing scanners rather than rebuilding them. Start with an approved staging API, explicit two-user authorization expectations, Schemathesis for API tests and ZAP for web checks. Keep a thin, versioned policy and evidence layer. Add an LLM only if a controlled comparison finds more verified bugs at the same budget.
Primary references: Schemathesis authorization testing · ZAP automation · OSS-Fuzz LLM evaluation · OWASP object authorization