The vulnerabilities agents write fresh

Ask an agent for a login flow and you tend to get a ?next= parameter redirected to whatever it contains. It is the obvious implementation, it is an open redirect, and the remedy was documented years before the model was trained.

article By 6 min read

Ask a coding agent to add "return to the page you came from" to a login flow. Unless the framework hands it a guarded helper — Rails' redirect_back with a fallback_location is one — here is the shape it tends to produce:

const next = req.query.next || "/dashboard";
// ... authenticate ...
res.redirect(next);

That is a correct implementation of the feature as described. It is also an open redirect. A static analyser tuned for it — Semgrep, CodeQL — will say so, if you run one; a unit test of the login flow will not, because the flow works.

What the attack actually is

The vulnerability is not that a URL gets rewritten. It is that your domain becomes the first hop of somebody else's phishing link.

An attacker sends a mail containing https://yourbank.example/login?next=https://yourbank.example.attacker.com/login. Everything a cautious person is trained to check passes. The link is on your real domain. The TLS certificate is yours. The hostname in the address bar is correct at the moment of the click. The victim logs in — genuinely, on your site, against your real authentication — and is then bounced to a page that looks exactly like yours and asks them to log in again "because something went wrong". The second form is the attacker's.

The credibility comes from your domain, not from the destination, and every layer of defence that operates on the hostname is reading the first URL in the chain. Mail filters that score links by reputation see yours. Corporate proxies with an allowlist see yours. The first URL is legitimate, and it is the only one anything checks.

There is a second use that is quieter and often worse: the redirect is used as an OAuth or SSO callback target, and the authorisation code, token or session identifier travels in the query string or the Referer header to a host the attacker controls. That is not a phishing page any more. That is credential exfiltration with a valid signature on it.

This is also why "it's only a scanner finding" is the wrong reading. A scanner reports it as informational because the redirect on its own steals nothing. The severity lives in what it is combined with, and combining is the cheap part.

Why this class keeps coming back

Open redirect has been in the OWASP material for over a decade. The remedy is small, well documented, and in most stacks a helper somebody has already written. It has not been an interesting problem since about 2013. So why is it appearing in new code again, in volume?

A plausible reason is in what there is most of to imitate. The published writing on "redirect after login" is overwhelmingly tutorials and answers showing the form above, written to explain redirects rather than security. The writing on why that line put a company in an advisory is smaller and a different genre: post-mortems, CVE text, mailing list threads, none of it in the shape of a code example. The material available to imitate is lopsided, whatever a model does with it.

That points at where to look. The classes to worry about in generated code are not the exotic ones — a fast writer with a lot of examples is good at the common case. They are the solved ones, where the naive implementation is widely published, widely copied, and wrong.

The feature as asked for The obvious implementation The class
"Send them back where they came from" Redirect to a user-supplied parameter Open redirect
"Let users embed a profile image by URL" Server fetches the URL they give Server-side request forgery
"Show the user's name on the page" Interpolate it into the template Cross-site scripting
"Let them filter by column" Build the SQL from the parameter Injection
"Log them in and keep them logged in" Set the cookie, ship it Missing Secure, HttpOnly, SameSite

Every row has a documented remedy that predates the model, and every row is what a fluent, fast, unbothered writer produces first.

The fix, and why nobody writes it first

The correct version of the login redirect is boring:

  • Accept only a path, never a full URL. If it does not start with a single /, discard it. Reject //evil.example and /\evil.example, which are protocol-relative and resolve off-site.
  • Or better, do not take a URL at all. Take a key — next=billing — and look up the destination in a table you control.
  • If you genuinely must allow external destinations, match the parsed host against an allowlist. Not a prefix check on the string: https://yoursite.com.attacker.com starts with https://yoursite.com.

That version is rarely what gets written first, because the requirement never said any of it. The requirement said "return to the page you came from", and the extra lines serve a threat the ticket did not mention. Output that satisfies the stated requirement is exactly what was asked for.

Verification has to be automatic, because the writing already is

Here is the part that has actually changed. Human security review is built around a volume of code a person can read, and that is the assumption now under pressure. If a process catches this reliably at ten pull requests a week, it is worth asking honestly what it does at ten an hour. The likely answer is not that reviewers get worse. It is that they start sampling, and nothing records which files were skipped.

So the check has to run without being asked for, from outside, against the deployed thing.

HarpyWatch has a check called open-redirect. You give it the URLs you care about — the login endpoint, the logout endpoint, anything that takes a destination — and it requests them with the common redirect parameter names set to an off-site host, then reads the Location header and any meta-refresh in the body to see where a browser would be sent. If the answer is a host that is not yours, that is the finding. Alongside it, cookie-flags reads what your Set-Cookie headers actually carry, security-headers and csp-policy report what a browser is told about framing and script origins, and mixed-content finds the http subresource on the https page. None of that is clever. It is the old list, asked again every few minutes, against the URL a visitor uses.

The honest limit: an external check tests the surface a client can reach. It will find the redirect on your login endpoint. It will not read your source, and it cannot tell you that the same mistake exists on an internal admin route nobody links to. It is a smoke alarm, not an audit.

But the cheapest moment to find this is before the traffic arrives. Point the checks at the staging URL, before DNS moves. A redirect parameter that bounces to somebody else's host is a thirty-second fix in a branch and a disclosure email in production.

Cite this

The HarpyWatch team. “The vulnerabilities agents write fresh”. The Nest, HarpyWatch, 29 October 2026 UTC. https://harpywatch.com/blog/the-vulnerabilities-agents-write-fresh

More from The Nest

What thirty seconds of checking would have caught

A catalogue of small, boring, real failures — a www that resolves nowhere, a redirect that drops to http, a response that is not actually compressed — each one cheap to see from outside.

article 6 min read

The debt you take on when a customer tells you first

An outage costs what it costs. Being informed of it by the person it happened to costs something separate, it accrues, and it is charged against the next incident rather than this one.

article 5 min read