Skip to content

fix(ip): use RFC 7239 for forwarded header#5409

Closed
wooorm-arcjet wants to merge 3 commits intomainfrom
wooorm/ip-rfc-7239
Closed

fix(ip): use RFC 7239 for forwarded header#5409
wooorm-arcjet wants to merge 3 commits intomainfrom
wooorm/ip-rfc-7239

Conversation

@wooorm-arcjet
Copy link
Copy Markdown
Contributor

@arcjet/ip reads from a forwarded header. That header is the standard alternative to x-forwarded-for, for passing several IPs from different services through to an application. However, @arcjet/ip does not support any valid values of that header. Values are a list of elements, each element consisting of key-value pairs.

This PR implements RFC 7239 to support valid values. As this header is intended to include several IPs, of which the right-most IPs could be trusted IPs from proxies, this PR supports that too.

While this adds a bit of code to parse things correctly, I believe it to be worth it, because finding the correct IP is tough, trusted proxies are a bottleneck, and standards are important.

An alternative is to stop reading from forwarded altogether. I think standards are too important though.

@wooorm-arcjet wooorm-arcjet requested a review from a team as a code owner November 11, 2025 13:01
@trunk-io
Copy link
Copy Markdown

trunk-io Bot commented Nov 11, 2025

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

Copy link
Copy Markdown
Contributor

@blaine-arcjet blaine-arcjet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should figure out what platforms support this. It may be better to just drop it.

Comment thread ip/index.ts
const forwarded = getHeader(request.headers, "forwarded");
if (isGlobalIp(forwarded, proxies)) {
return forwarded;
const forwardedElements = forwarded ? parseForwarded(forwarded) : undefined;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What platforms support this? I found a Caddy issue from 5 years ago and they have indicated it is not a high priority.

@wooorm-arcjet
Copy link
Copy Markdown
Contributor Author

I saw that vercel supports it correctly.
Yes, removing support for forwarded is also an option.
But it is a standard, and I can see CDNs that folks put in front of where they deploy, supporting these standards

@blaine-arcjet
Copy link
Copy Markdown
Contributor

Supposedly HAProxy supports the forwarded header. I couldn't find anything conclusive for nginx.

@wooorm-arcjet
Copy link
Copy Markdown
Contributor Author

wooorm-arcjet commented Nov 13, 2025

(see this at some point recommended nginx regex: https://redirect.github.com/golang/go/issues/30963#issuecomment-1085057745)

2 reasons not to do forwarded:

@blaine-arcjet
Copy link
Copy Markdown
Contributor

These are great points (thanks for including links!). I still have to read about the header sabotage, but I'd like to know your opinion based on this information. Should we remove the forwarded header detection?

@wooorm-arcjet
Copy link
Copy Markdown
Contributor Author

wooorm-arcjet commented Nov 13, 2025

I am quite okay with either but have a slight preference for being a good web citizen and supporting standards. On the other hand, it has no practical use yet (vercel also sets x-forwarded-for)

At some points in various conversations @davidmytton mentions that things can go in blog posts.
A bit esoteric but publishing a right-to-left forwarded parser may be a good candidate for that!

@blaine-arcjet
Copy link
Copy Markdown
Contributor

A bit esoteric but publishing a right-to-left forwarded parser may be a good candidate for that!

💪 Is the parser currently implemented a left-to-right parser with the problems surfaced in the header sabotage blog? What is the effort level of a right-to-left parser?

@wooorm-arcjet
Copy link
Copy Markdown
Contributor Author

Currently left-to-right parsing, so the whole thing stops on a syntax error.
I think it’s possible the other way around, it’s still a very strict grammar.
API has to be switched to a generator-like thing though, but that’s not difficult.

@blaine-arcjet
Copy link
Copy Markdown
Contributor

I propose we make a new (breaking) PR to remove forwarded since it is not handled correctly right now. I'll draft this PR until we have time to implement the right-to-left parser and write the blog post.

@blaine-arcjet blaine-arcjet marked this pull request as draft November 14, 2025 19:02
`@arcjet/ip` reads from a `forwarded` header.
That header is the standard alternative to `x-forwarded-for`,
for passing several IPs from different services through to an application.
However, `@arcjet/ip` does not support any valid values of that header.
Values are a list of elements, each element consisting of key-value pairs.

This PR implements RFC 7239 to support valid values.
As this header is intended to include *several* IPs,
of which the right-most IPs could be trusted IPs from proxies,
this PR supports that too.

While this adds a bit of code to parse things correctly,
I believe it to be worth it,
because finding the correct IP is tough,
trusted proxies are a bottleneck,
and standards are important.

An alternative is to stop reading from `forwarded` altogether.
I think standards are too important though.
@wooorm-arcjet wooorm-arcjet marked this pull request as ready for review February 2, 2026 15:02
@wooorm-arcjet wooorm-arcjet requested a review from qw-in February 2, 2026 15:02
@qw-in
Copy link
Copy Markdown
Member

qw-in commented Feb 17, 2026

I'm going to close this for now. We may come back to it if there is a customer request or we make a decision to do so and implement it across the sdks.

@qw-in qw-in closed this Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants