Skip to content

IBX-11181: Trusted Proxies is not set on Ibexa Cloud - #699

Open
vidarl wants to merge 3 commits into
4.6from
IBX-11181-Trusted_Proxies_is_not_set_on_Ibexa_Cloud
Open

IBX-11181: Trusted Proxies is not set on Ibexa Cloud#699
vidarl wants to merge 3 commits into
4.6from
IBX-11181-Trusted_Proxies_is_not_set_on_Ibexa_Cloud

Conversation

@vidarl

@vidarl vidarl commented Jan 14, 2026

Copy link
Copy Markdown
Contributor
🎫 Issue IBX-11181

Related PRs:

  • PR for filtering X-Forward-For in varnish and fastly VCLs are comming

Description:

Trusted proxies are not set on Ibexa Cloud when using Fastly. We document (via Upsun,) that user must disable TRUSTED_PROXIES: "REMOTE_ADDR" in .platform.app.yaml (which is correct), but we don’t say or specify how to configure TRUSTED_PROXIES correctly.

And frankly, it is not easy/possible to do via static config given how the Upsun router behaves:

Upsun router behavior:

  • Will not filter X-FORWARD-FOR sent by malicious client
  • It will add client's IP to X-FORWARD-FOR, appending header if already set ( "1.1.1.1" => "1.1.1.1, 2.2.2.2")
  • It will always set a X-Client-IP header ( value is IP of client). Value is also end-user's IP if request is received via Fastly ( doc )
  • Will filter Client-Cdn if request is not originating from any supported CDN ( doc )
    • When received from Fastly, value of header will be fastly
  • $_SERVER['REMOTE_ADDR'] will be spoofed, will have same value as X-Client-IP

So there is no static IP or IP range you can set as trusted proxies when using Fastly on Upsun. For instance, setting trusted hosts to Fasty's public IP list will not do any good. Thus, Ibexa DXP should automatically detect on Ibexa Cloud if request is received via Fastly

Next, I really doesn't understand the original purpose of TrustedHeaderClientIpEventSubscriber. It basically does this:

  • If running on Upsun (formerly known as Platform.sh), the request header X_FORWARDED_FOR will be set (value will be copied from the X-Client-IP request header) and X_FORWARDED_FOR will be set as trusted_headers
  • However, this header will still be ignored unless devs somehow also sets trusted_proxies correctly.
  • Also, the subscriber can be configured to use some other header than X-Client-IP as source

My next doubt is why there was some need for this in relation to IBX-4046
FYI : Original PR : https://github.com/ibexa/core/pull/165/files

As the Upsun router anyway sets the X-Forward-For header, and devs still needed to set trusted_proxies in config ( which IMO is impossible), the old implementation in TrustedHeaderClientIpEventSubscriber is void.
But it certainly may be that I am missing something important....?

What the new implementation of TrustedHeaderClientIpEventSubscriber does:

  • If we are on Ibexa Cloud and request is coming from Fastly, then we declare that the request is received via trusted proxy

For QA:

Maybe do sanity checks with "create Applications for Customer portal" feature, as original implementation of TrustedHeaderClientIpEventSubscriber was implemented in relation to that.

Documentation:

@vidarl
vidarl changed the base branch from main to 4.6 January 14, 2026 13:57
@vidarl
vidarl force-pushed the IBX-11181-Trusted_Proxies_is_not_set_on_Ibexa_Cloud branch from 38c87b6 to 17e4096 Compare January 14, 2026 14:00
@@ -15,16 +15,6 @@

final class TrustedHeaderClientIpEventSubscriber implements EventSubscriberInterface

@vidarl vidarl Jan 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
final class TrustedHeaderClientIpEventSubscriber implements EventSubscriberInterface
final class IbexaCloudTrustedProxiesEventSubscriber implements EventSubscriberInterface

Or this is considered a BC ? Class is final though, so maybe not a problem?

@barw4 barw4 Jul 30, 2026

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.

We don't care

@ViniTou ViniTou Jul 31, 2026

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.

isnt IbexaCloud too generic tho? this whole class is about Upsun & Fastly, right?

@vidarl
vidarl force-pushed the IBX-11181-Trusted_Proxies_is_not_set_on_Ibexa_Cloud branch from 17e4096 to b1a199d Compare January 14, 2026 14:37
@sonarqubecloud

Copy link
Copy Markdown

@vidarl
vidarl requested a review from a team January 19, 2026 15:03
@vidarl
vidarl force-pushed the IBX-11181-Trusted_Proxies_is_not_set_on_Ibexa_Cloud branch from ec3cba0 to d53633c Compare July 30, 2026 07:31
$trustedHeaderName = $this->trustedHeaderName;
if (null === $trustedHeaderName && $this->isPlatformShProxy($request)) {
$trustedHeaderName = self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP;
if ($this->isPlatformShProxy($request) && $request->headers->get('Client-Cdn') === 'fastly') {

@barw4 barw4 Jul 30, 2026

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.

As discussed with Vidar Client-Cdn header is stripped by Upsun when request is not coming from trusted CDN (in case we care about security and we do)

@barw4 barw4 Jul 30, 2026

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.

Confirmed by Upsun (thanks Vidar for reaching out to them with this question): client can't spoof Client-Cdn header - it should arrive into their docs soon so we know for sure we can trust this header.

@sonarqubecloud

Copy link
Copy Markdown

@konradoboza konradoboza left a comment

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.

PR can be rebased as #794 got merged, it contains PHPStan issues fix.

A few questions:

PR for filtering X-Forward-For in varnish and fastly VCLs are comming

Do we have this PR already? It should most likely incorporate X-Forward-For and X-Forward-Host in our VCL, right?

Shouldn't this indeed belong to ibexa/fastly since it's covering this very case? It will also make more sense concerning merging up the changes.

In regards to:

As the Upsun router anyway sets the X-Forward-For header, and devs still needed to set trusted_proxies in config ( which IMO is impossible), the old implementation in TrustedHeaderClientIpEventSubscriber is void.
But it certainly may be that I am missing something important....?

https://github.com/ibexa/post-install/blob/4.6/resources/platformsh/ibexa-commerce/4.6/.platform.app.yaml#L65 I think this is where it can be omitted once projects are created from templates. This seems like potential security flaw where XFF remains untouched. The subscriber in question overwrites XFF (attacker-influenced?) with X-Client-IP (router-controlled) so that the processing reads a clean value.

It seems we need to do the following to summarize:

  • sunset ibexa/fastly-forwarded-host (archive),
  • make sure VCL is properly updated,
  • the combo mentioned below is verified not to fallback to the Symfony defaults.

if (null === $trustedHeaderName && $this->isPlatformShProxy($request)) {
$trustedHeaderName = self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP;
if ($this->isPlatformShProxy($request) && $request->headers->get('Client-Cdn') === 'fastly') {
Request::setTrustedProxies(['REMOTE_ADDR'], Request::getTrustedHeaderSet());

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.

Wouldn't that fallback to Symfony's default if framework.trusted_proxies was never set? Shouldn't we be more specific here by passing: HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PROTO | HEADER_X_FORWARDED_PORT combo?

@barw4 barw4 Jul 31, 2026

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.

Via Symfony's code:

$trustedHeaderSet = $trustedHeaders ?? (Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO);

Host and Prefix are omitted in this case but the question is - do we really need them? It's not like previous Subscriber added Host so imo this change is proper. Subscriber didn't pass Host and we aren't passing Host now.

Host has the following note in Symfony docs:

Enabling the Request::HEADER_X_FORWARDED_HOST option exposes the application to [HTTP Host header attacks](https://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html). Make sure the proxy really sends an x-forwarded-host header.

@barw4 barw4 Jul 31, 2026

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.

On the other hand, HOST was set manually in https://github.com/ibexa/fastly-forwarded-host/blob/main/src/bundle/EventSubscriber/KernelRequestSubscriber.php and if we are deprecating this bundle I would say we also need to pass X_FORWARDED_HOST explicitly? I believe we can pass it safely because proxy sends it safely and cannot be spoofed due to Client-Cdn existance that guarantess request is actually coming from proxy?

@barw4 barw4 Jul 31, 2026

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.

Additionally, if I understand correctly fastly-forwarded-host bundle was created some time ago because of the need to handle a lot of Upsun domains and overcome some routing (??) limitations. Perhaps the FORWARDED-HOST should be enabled explicitly in this subscriber via a dedicated config option if such a limitation occurs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants