Say the login redirect is looping. I export a HAR from DevTools in this walkthrough because I want a second look at the status codes, and the reflex I am blocking is the paste into a model. I do not paste it.
The export is a transcript of a private channel. Search for Set-Cookie, Authorization, and csrf before you admire the timing waterfall. A session cookie, a CSRF field, and a bearer token on the token endpoint do not explain a 302. Pasting them is the trust-boundary violation. I can reproduce that class of mistake with a fixture. I am not describing a dated incident, and I am not claiming a vulnerability in any browser.
Would you still paste the file if the only question was why this 302 points back at /login? If the answer is no, the rest of this is the gate that makes no enforceable.
Trust boundaries, in order
I split the path into four zones, and I keep them in order on purpose.
- The browser profile. Cookies, storage, and CSRF tokens live here.
- The HAR file on disk. That is a copy, not a view, and copies get attached to tickets.
- The redaction gate. It must fail closed.
- The model context. It may see a fixture. It does not get the raw export.
Skip zone 3 and you already crossed the boundary. A model on your laptop still counts. Local does not mean unlogged. Have you checked whether the client writes prompts to a history file?
DevTools can omit sensitive headers at export time. People still "sanitize" a capture by deleting the hostname and leaving Cookie intact. That is a rename, not a redaction. Why keep a header the model cannot safely use?
browser profile
|
v
HAR file on disk ---- raw volume, model cannot mount
|
v
deny gate (fail closed)
|
+-- fail --> stop, no model
|
v
redacted sibling or positive fixture
|
v
model context, and any prompt log that context writes
Logs sit on that last hop. If the review process logs prompts, the log is another copy. A debug flag that prints the model request body will undo the gate. I would rather have a missing explanation than a prompt log that still contains a session cookie.
Fixtures, negative then positive
This template is unexecuted. I have not run it against a production capture, and nothing in this draft is evidence that a bug was found. If you run it later, assume Python 3.12 and jq 1.7, and pin those yourself. The values are canaries, not secrets. Do not drop the negative fixture into a public sample repo without the canary prefix.
Negative fixture, fixtures/har-negative.json. It should always fail the gate:
{
"log": {
"version": "1.2",
"entries": [
{
"request": {
"method": "POST",
"url": "https://app.example.test/login",
"headers": [
{"name": "Cookie", "value": "session=CANARY_COOKIE_DO_NOT_SEND"},
{"name": "X-CSRF-Token", "value": "CANARY_CSRF_DO_NOT_SEND"}
],
"postData": {
"mimeType": "application/x-www-form-urlencoded",
"text": "password=CANARY_PASSWORD_DO_NOT_SEND"
}
},
"response": {
"status": 302,
"headers": [
{"name": "Set-Cookie", "value": "session=CANARY_SET_COOKIE_DO_NOT_SEND; HttpOnly"}
]
}
}
]
}
}
Positive fixture, fixtures/har-positive.json. Same redirect story, nothing a session could be reused from:
{
"log": {
"version": "1.2",
"entries": [
{
"request": {
"method": "POST",
"url": "https://app.example.test/login",
"headers": [
{"name": "Content-Type", "value": "application/json"}
],
"postData": {
"mimeType": "application/json",
"text": "username=ada"
}
},
"response": {
"status": 302,
"headers": [
{"name": "Location", "value": "/login?error=1"}
]
}
}
]
}
}
The positive file is the only shape I would hand a model. Method, path, status, one non-secret body field. That is enough to argue about a redirect loop. Need the cookie to reproduce the bug? Stay in a private debugger. Do not promote the cookie into a prompt so the model can "see what you see."
The gate, as numbered steps
Regex is a tripwire. It is not a proof that the file is clean. Say that out loud before you trust a pass.
- Deny headers by name, not by vibe. Block
Cookie,Set-Cookie,Authorization,Proxy-Authorization,X-CSRF-Token, andX-XSRF-TOKEN. - Scan
postData.textand the URL query forpassword,access_token,refresh_token,client_secret, and the prefixCANARY_. - Fail closed when the file is not valid JSON. A truncated export is not "probably fine."
- Write a redacted sibling. Never overwrite the source. You may still need the original offline, on a volume the model client cannot mount.
- Only then may a model process open the sibling. If step 1 or 2 fired, stop. Do not ask the model to ignore secrets. It will not enforce that sentence.
Unexecuted checker. A sketch, not a scan result:
#!/usr/bin/env python3
"""Unexecuted template. Assumes Python 3.12. Not a scan of a live HAR."""
import json
import sys
DENY_HEADERS = {
"cookie",
"set-cookie",
"authorization",
"proxy-authorization",
"x-csrf-token",
"x-xsrf-token",
}
CANARY = "CANARY_"
def walk(node, hits):
if isinstance(node, dict):
name = str(node.get("name", "")).lower()
if name in DENY_HEADERS:
hits.append("header:" + name)
for value in node.values():
walk(value, hits)
elif isinstance(node, list):
for value in node:
walk(value, hits)
elif isinstance(node, str) and CANARY in node:
hits.append("canary")
def main(path):
try:
data = json.loads(open(path, encoding="utf-8").read())
except (OSError, json.JSONDecodeError) as exc:
print("FAIL closed:", exc)
return 2
hits = []
walk(data, hits)
if hits:
print("FAIL", ",".join(hits))
return 1
print("PASS")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1]))
Expected evidence, once you actually run it: har-negative.json exits 1, and har-positive.json exits 0. I am not inventing a terminal transcript for a run I did not do. Keep the output beside the fixture version you pinned.
Pre-check I would run before the Python gate. Still not a substitute:
jq -r '.. | objects | .name? // empty' fixtures/har-negative.json | tr 'A-Z' 'a-z' | sort -u
If cookie or set-cookie shows up, stop. A second command, for the canary prefix:
rg -n "CANARY_|set-cookie|authorization" fixtures/har-negative.json
You want that search to hit on the negative fixture and miss on the positive one. If it misses on the negative fixture, your fixture is wrong, not clean. What were you about to send, exactly?
What I will not send
Even a box I administer does not get these raw values in a model prompt. Logs on that box are still a copy.
| Field | Send raw? | Why I refuse | What I send instead |
|---|---|---|---|
Cookie / Set-Cookie
|
No | Session material | Header name and value length |
Authorization |
No | Bearer or basic material | Scheme only, value removed |
| CSRF header or form field | No | Often paired with the cookie | Present or absent |
Password in postData
|
No | Credential | Key present, value dropped |
Query access_token
|
No | URLs leak into proxies and traces | Path only |
| Status, method, path, timing | Yes | Enough for a redirect question | Unchanged |
Content-Type, cache headers |
Usually | Low sensitivity | Keep, unless a token is embedded |
"The agent never left the browser" is not a privacy property. The moment you export a HAR, copy a console dump, or let a tool read storage, the data has left the cookie jar. Did the tool result get logged? That is the same boundary, just with a different file extension.
Application logs are a separate paste. I am not opening that file here. If a log line and a HAR are in the same prompt, the HAR gate does not cover the log line. Run the same deny list on both, or send neither.
Prevent, detect, recover
| Phase | Control | Failure you should expect |
|---|---|---|
| Prevent | Disable sensitive headers on export, then run the deny-header gate | Exit 1 on the negative fixture |
| Detect | CI on fixtures only; CANARY_ must never pass |
A green run on har-negative.json means the gate is broken |
| Recover | Rotate the session if a raw HAR was pasted; delete model history if the product allows it | An incident note with the time of the paste, not a second copy of the cookie |
Recovery is rotation and deletion. It is not a smarter prompt. If the cookie already crossed, the transcript is evidence. Pasting it again while you clean up is a second leak. How fast is your session revocation, really? Do not assume it is instant.
After the gate, a review step you control
I still want help reading a redacted redirect trace. That is a fair use of a model. An unredacted HAR is not.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode is an open-source AI development platform. I would use it for the review step after the gate, not as a place to drop the export and hope. The brief for this article states that free model access and a free server option are available, and it described the free token allowance as 10 million. I am not treating that figure as a verified live quota. No primary offer page was attached here, and allowances move. A stale number is worse than none. Confirm the live token cap, duration, model list, and server terms on the project page before you plan a workload around them.
What I care about is placement. Keep the pre-redaction HAR on a volume the model process cannot mount. Mount only the positive fixture or a redacted sibling. A free server does not relax that invariant. It only changes where the review process runs, which is useful if you do not want the redacted trace leaving a machine you administer. Free access is not a reason to skip the gate. If the current free path does not fit a security-review workload, use a path that does, or run the gate with no model at all. The gate is the article. The model is optional.
Who should not use this approach? If a tested DLP proxy already sits in front of every model route, do not replace it with a short script. If the capture holds regulated health or payment data, a canary gate is not a compliance program. If you need the raw Set-Cookie to debug, stay in a private debugger.
Limitations, so this cannot be quoted as a finding. I did not execute the checker in this draft. A header deny list misses tokens under custom names such as X-App-Session. Base64 and compressed bodies sail past a string search. I assumed HAR 1.2; other exports differ. A pass means these fixtures behaved as specified. It does not mean a live file is safe.
Which layer should enforce it?
Which invariant belongs in CI, and which layer should enforce the live block? I put the canary regression in the fixture repo, so a helpful redactor cannot silently start passing Cookie. I put the export block on the workstation, before any model client starts. The model host is the wrong place to discover that the cookie was still in the file.
Start the next HAR debugging session from the negative fixture. Did the gate fail closed? If it did not, you are not ready to ask a model anything.
Top comments (0)