Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: desync-validate description: build a validated proof of concept for a desync/response-poisoning vulnerability
Desync response poisoning
Response poisoning occurs when you smuggle an incomplete request prefix and the VICTIM receives a poisoned response containing attacker-controlled content.
Mechanism
Front-end servers match responses to requests in order. When you smuggle an incomplete request prefix:
- Attacker sends: [Trigger Request][Incomplete Smuggled Prefix]
- Front-end sees 1 request, back-end sees trigger + start of a second request
- Back-end waits for the second request to be completed
- Victim sends their request on the same connection
- Back-end appends victim's request data to complete the smuggled prefix
- Back-end processes the now-complete smuggled request and sends its response
- Victim receives the smuggled response instead of their own - THIS IS RESPONSE POISONING
Critical Direction
Response poisoning = Victim receives attacker's smuggled response
NOT: Attacker receives victim's response (that's victim response theft / VRT)
To demonstrate response poisoning, your VICTIM request must receive content from the ATTACKER's smuggled request (their fingerprint/canary).
Distinction from VRT
┌──────────────────────────────────┬─────────────────────────────────┐ │ Response Poisoning │ Victim Response Theft │ ├──────────────────────────────────┼─────────────────────────────────┤ │ Victim gets attacker's response │ Attacker gets victim's response │ ├──────────────────────────────────┼─────────────────────────────────┤ │ Proves attacker controls content │ Proves data theft possible │ ├──────────────────────────────────┼─────────────────────────────────┤ │ Smuggled prefix is INCOMPLETE │ Smuggled request is COMPLETE │ └──────────────────────────────────┴─────────────────────────────────┘
Impact
Poisoned responses can deliver XSS payloads, redirect victims to attacker-controlled domains, or serve arbitrary attacker-controlled content to arbitrary users.
Triggering response poisoning
- Retrieve the desync trigger request. Note that the body of the request is not relevant.
- Now we need to find an endpoint where the smuggled request's response will contain attacker-controlled content (a canary).
Use the turbo simulator MCP to run the micro-crawl.py example script (turbo://examples/micro-crawl) to find endpoints that reflect input.
- Next, using the desync-validated.py template as a starting point, create a script which provides:
- The CL.0 trigger. This should have no body data in the request itself (end with \r\n\r\n), but a Content-Length header so the back-end reads the start of the smuggled prefix as body data.
- The smuggled prefix - an INCOMPLETE request (no trailing \r\n\r\n). The victim's request will complete it.
- The victim request - a simple GET request.
- attacker_fingerprint - a string that uniquely identifies a poisoned response. If you have input reflection in the smuggled response, use $CANARY$.
- Launch the run with your turbo simulator MCP and wait patiently for completion.
- Check the run status with
turbo://runs/{run_id}?wait=true. If the status message contains 'poisoned!', find the response with that label using search_responses(run_id, query="poisoned!", search_in="labels") and review it.
a) If, based on the "poisoned!" response, you believe response poisoning succeeded, submit for validation (see below) b) If not, consider why it failed and retry. Analyze the script and refer to "Reporting progress" and "If there's no evidence of poisoning"
MANDATORY: You MUST use desync-validated.py as the base for your script
Reporting progress
If the script ran fine but there's no evidence of poisoning, output this:
DESYNC-SAVE-ID: <run-id>
If you see a highly anomalous response that may have been intended for a third party (not a simulated victim) at any point, save it to the organizer with the note ANOMALY.
Checking your results
Before claiming success, you MUST spawn a validation agent to verify:
Task(subagent_type="general-purpose",prompt="Use the desync-validate skill to validate run_id: {run_id}",description="Validate desync run")
The validator starts fresh with no knowledge of your reasoning and independently evaluates the evidence.
If validation fails, review the reason and adjust your approach. You can retry and re-validate. Only claim success after the validator confirms it.
Reporting final results
After your attempts are complete, you MUST end your response with exactly one of:
If poisoning succeeded (you have a run with "poisoned!" results):
DESYNC-RUN-ID: <run_id>
If poisoning failed despite multiple attempts:
DESYNC-OUTCOME: desync-fail
A separate external validator will handle organizer saves and provide the authoritative classification.
If there's no evidence of poisoning
On some servers, response poisoning is very easy to trigger using tens of requests per second. On others, it's hard.
To get a list of techniques/ideas that may help, run hypothesis_report.py