A server-side token handler holds the access token and gives the operations browser only a session reference — what does injected script get now?
answer
- theft becomes a ride
- portability removed, authority kept
- attacker confined to the open page
- you added a stateful hop
- proxy anything and the scope returns
basics
~20 sIt converts a credential theft into a session ride. Injected script can still act as the user while the page is open, but there is no portable token to carry away and replay later from elsewhere. The cost is a stateful hop in the request path.
solid answer
~50 sA component on your own origin keeps the long-lived credential and the browser is given only a reference to server-side state. Injected script cannot read that reference, so nothing exfiltratable exists in the page — and that is the whole gain. What the script *can* still do is make requests to your origin, which the browser will authenticate for it, so the attacker acts as the user for as long as the page is open. You have removed portability, not authority. The costs are real: a stateful component that must be as available as the API behind it, an extra network leg and failure domain, and a cookie that now owes a cross-site forgery defence. And if the handler proxies whatever upstream path it is asked to, the script reaches the token's entire scope through it anyway.
code
http · 10 linesPOST /bff/work-orders/4412/close HTTP/1.1
Host: scheduler.example
Cookie: sref=9f2c1ab4d0e7
Origin: https://scheduler.example
HTTP/1.1 204 No Content
POST /work-orders/4412/close HTTP/1.1
Host: api.scheduler.example
Authorization: Bearer eyJhbGciOi...Qssw5cgo deeper
Grasp the shape: the credential stays on a server you own and the browser only gets a reference to it. The memorable line is that a theft becomes a ride — the attacker can act, but cannot take anything away.
Explain why injected script can still make authenticated calls even though it cannot read the cookie, and name the forgery obligation the cookie creates. Be able to draw the two hops and say which one carries the token.
Argue it as a blast-radius control rather than a fix, price the stateful hop honestly, and identify the allowed-route list as the control that actually keeps the reduction in reach.
Weigh a new tier-one availability dependency on the sign-in path against a confinement guarantee, and decide whether your organisation can staff the route list for years. If it cannot, the design degrades quietly into an open proxy.
## The change, in one sentence Put a component of your own on the request path. It holds the long-lived credential for the operations-room browser and never sends it downstream to the page. The browser gets a reference to state that component keeps, in a cookie its script cannot read. Every call the page makes goes to that component, which attaches the real credential on the hop the browser cannot reach. The effect on a script-injection incident is precise and worth memorising: **an exfiltratable credential theft becomes a session ride.** ## What the attacker loses, and what they keep | | credential in the page | credential behind the handler | |---|---|---| | script reads the credential | yes | no | | attacker replays from their own machine | yes, until it expires | no | | attacker acts as the user | yes | yes, while the page is open | | the attack survives the tab closing | yes | no | | every action is a request you logged | not necessarily | yes | | the attacker's reach | the token's full scope | whatever the handler will proxy | Read the third row carefully, because it is the one candidates skip. Injected script does not need to read the cookie. The browser attaches it. Any request the script makes to your origin is authenticated, so for as long as the compromised page is open, the attacker does whatever the user could do. What you took away is the ability to carry a working credential off the machine and use it next week from somewhere else, against a user who has long since gone home. That is still a large win, and it is a win in two directions people undersell: the attacker is **confined to the victim's browser** and **confined to the window in which the page is open**, and every action they take is a request that hit your server, so it is logged, rate-limitable, and killable by ending the session. ## What it costs 1. **The stateful hop you were trying to avoid.** A self-contained credential was attractive partly because no component had to remember anything. The handler remembers, so its state is now a tier-one availability dependency: when it is down, nobody is signed in, and when its state is lost, everybody is signed out at once. 2. **A cookie obligation.** The browser now authenticates by a cookie it attaches automatically, so state-changing endpoints owe a defence against cross-site forged requests. Designing that defence is a separate piece of work; the point is that this custody choice is what creates the debt. 3. **Latency and a failure domain.** Every request takes an extra leg. Every deployment of the handler is an outage risk for a surface that previously had none. 4. **A confused-deputy surface.** The handler attaches a real credential to requests it is asked to make. Its list of permitted upstream routes is therefore an authorization surface in its own right, and a weak one is worse than no handler. ## Where it stops being a custody improvement If the handler is a general proxy — pass any path through, attach the credential — then injected script reaches the token's entire scope through it. The only thing that changed is that the attacker must stay inside the victim's browser to use it. That is not nothing, but it is a fraction of what the design was sold as. So the control that actually carries the value is the **allowed-route list**: the handler exposes the specific operations the operations-room surface needs, not the upstream API. If you are not prepared to maintain that list, you have bought a stateful dependency for a confinement guarantee and no reduction in reach. ## The honest summary for an interview Say the conversion out loud — *theft becomes a ride* — then immediately say what survives it: the attacker still acts as the user while the page is open. Then name the two costs a reviewer will ask about: you reintroduced state on the request path, and you took on a forgery obligation. Then name the condition under which the whole thing degrades: an open proxy hands back the scope you just removed. A candidate who describes this as "the fix for script injection" has overstated it. The fix for script injection is not running foreign script. This is a **blast-radius** control, and it should be argued as one.
- Injected script cannot read the session cookie. Why is that not the same as being safe?Because the browser attaches it regardless of who wrote the request. Any call the script makes to your origin is authenticated, so the attacker acts as the user for as long as the compromised page is open. What was removed is a credential they could copy out and replay later from their own machine against a user who has gone home.
- What is the strongest single argument against introducing a token handler?It reintroduces the stateful hop a self-contained credential was chosen to avoid. The component must be as available as the API behind it, its state becomes a tier-one dependency whose loss signs everybody out at once, and every request pays an extra leg and an extra failure domain. If your threat model does not genuinely include script reaching a credential, you bought a dependency for nothing.
- Where does a token handler stop being a custody improvement?When it proxies arbitrary upstream paths. Injected script then reaches the token's whole scope through it, and the only change is that the attacker must stay inside the victim's browser. The allowed-route list is the control doing the real work, so a handler nobody maintains that list for is a stateful dependency bought for confinement alone.
- What does this choice do to your logging?It improves it, and that is an underrated part of the argument. Every action the attacker takes is a request that reached a component you own, so it appears in your access log with the session reference attached, can be rate-limited, and stops the moment you end that session. A credential replayed from the attacker's own machine may produce nothing you can attribute.
saying these in an interview costs you the question
- Calling a token handler the fix for script injection
- Assuming an attacker can do nothing once the credential is server-side
- Forgetting the cookie now owes a cross-site forgery defence
- Proxying arbitrary upstream paths through the handler
- Treating the handler as stateless because the API behind it is
- Ignoring that the handler's availability is now the sign-in path