Changing X-Frame-Options to allow-from doesn't succeed in .toml file

Hi!

XY: I’m running Laravel application, it’s used to be integrated into external webpages as a widget through using HTML tag. This requires replacing X-Frame-Options header’s value from SAMEORIGIN to allow-from https://my-domain.com. Also, I’m using Cloudflare as my DNS manager, but it looks like headers are still received from Fly.io, as via headers value equals 1.1 fly.io.

Question: I tried to replace X-Frame-Options value through providing next lines in my projects fly.toml file:

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [services.ports.http_options.response.headers]
    X-Frame-Options = "allow-from https://my-domain.com"

But it doesn’t succeed as still get SAMEORIGIN in page headers after app deploy for Fly.

Is there any idea how I could overcome this issue and set own X-Frame-Options value?

EDIT: I’ve also tried to change X-Frame-Options via Transform Rules for Cloudflare, but doesn’t seem that it can override Fly.io settings here. Proxy status for all DNS records set to “DNS only” according to this docs.

Hi!

Note:

Most importantly, the allow-from value for that header doesn’t appear to be widely supported (see here)

I think omitting the header, or using a CSP header’s frame-ancestors is your best bet.


Testing it Out

Testing this out myself, I set:

  [services.ports.http_options.response.headers]
  X-Frame-Options = "DENY"

Chrome seems to keep responding with the SAMEORIGIN response (not sure if that’s cached or something?)

But curl showed the updated header value (I suggest you test with curl as well!)

Note that is says DENY now:


What To Do

:point_right::point_right::point_right: Overall I think the most important thing to find here is that allow-from isn’t going to work in modern browsers. You should check out CSP headers, or try to get Fly to remove the x-frame-options header.

@fideloper-fly thanks for answering my questions! Unfortunately, your solution haven’t succeeded for me. Here’s some background of what I’ve done:

  • I switched from Cloudflare so my DNS are now directly pointed to Fly.io from my domain provider’s settings. All header settings should now be delivered directly from Fly.io.
  • I have multiple .toml files as I use same application for 3 different Fly.io instances (actually 3 domain for 3 countries and requires different set of capabilities). All other settings were working well before, but might this be a problem this time?
  • Tried to add X-Frame-Options with frame-ancestors included – didn’t worked, tried to disable X-Frame-Options through removing header using this line:
    http_options = { response = { headers = { via = false } } } – didn’t worked too.


Address that I’m trying to reach through is Support Donationbox.ee | Pavel Fleišer | DonationBox.ee. Here’s the code snippet for the widget:

<embed src='https://donationbox.lv/embed?campaign_title=Support%20Donationbox.ee&detail=Donation%20donationbox.ee&payee=Pavel%20Flei%C5%A1er&pp=pfleiser&rev=pavelvtd' width='100%' height='900' style='border:none;overflow:hidden'></embed>

What might be wrong here? I would appreciate if you can help me to investigate this issue, as I’m out of ideas what I’m doing wrong now :smiley:

Few things here:

  1. I’m not sure if your response was a bad copy/paste, but the snippet you had there was removing the via header instead of x-frame-options
  2. The frame-ancestors options is actually part of the newer CSP header, rather than the X-Frame-Options header

This is what I got working for me:

   [services.ports.http_options.response.headers]
     X-Frame-Options = false
     Content-Security-Policy = "frame-ancestors https://dumptests.fly.dev"

After deploying that change, I saw this:

2 Likes

@fideloper-fly thanks for replying! Yes, my bad, I was using X-Frame-Options for removing header before, of course.

I tried your solution

[services.ports.http_options.response.headers]
X-Frame-Options = false
Content-Security-Policy = "frame-ancestors https://donationbox.lv"

, added to my fly.donationbox.lv.toml file, depolyed fixes, and still can’t see any changes while sending CURL request.

curl -I https://donationbox.lv
HTTP/2 200 
server: Fly/620fe63b (2023-03-17)
content-type: text/html; charset=UTF-8
strict-transport-security: max-age=31536000; includeSubDomains
vary: Accept-Encoding
cache-control: no-cache, private
date: Wed, 22 Mar 2023 13:04:07 GMT
set-cookie: XSRF-TOKEN=eyJpdiI6Ilh0dXFQUmVKR1M4TUJIK0VRNmc5Y2c9PSIsInZhbHVlIjoiWUNNeDR6OVBaYlRXY0hWT1FRODFFVzVsTm9qS05Ub1k4b0FtaWk3Mm1NNFY4Y21yOEVqZUVLMVpqTUxLazR4YmxIS3pla3F3byt2dlJBaFdOcEpHcitpN2lsZ1ZtdnhRTk5qU2d0Tks5cDFJNjZxMW1XVWxoUkZlZWdCQklYWnciLCJtYWMiOiI3MjkxMTJjZmJiZjgwOGMwOTQyZjYwMTIyODJiZmYzYTIwNDM2ZmY5NjY4MzE2N2UwYjg1ZmIzNGM4NmZmMzA3IiwidGFnIjoiIn0%3D; expires=Wed, 22-Mar-2023 15:04:07 GMT; Max-Age=7200; path=/; samesite=lax
set-cookie: laravel_session=eyJpdiI6IjFVOHRKNGJQN2llR09jYjZqdTB4Qmc9PSIsInZhbHVlIjoiUUhZTCttMUFwRXl0RFo3b1dRZVppU2tuU2JmOFo1ZlNvZ2d2aVNqY3JIVXg1Z3pqbHBqUkVKNktnakh6MmpXTUlvR29aZXdXNDBKdGYwU1RXd3pHcG96aDc1bHB1MHBJalRSa3lzN1V5STc2bTI0RGdwaE9QdGdNWWU2NDhTNlIiLCJtYWMiOiJhNGUxODBhYzljNWJlNzMwNTQ3NWYzYjVjYjU4M2NmODZlZjA2Mjk4ZmY4NDc2ZThlNWZhOTYxNjE1N2QzNTAyIiwidGFnIjoiIn0%3D; expires=Wed, 22-Mar-2023 15:04:07 GMT; Max-Age=7200; path=/; httponly; samesite=lax
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
referrer-policy: no-referrer-when-downgrade
via: 2 fly.io
fly-request-id: 01GW4PPTXY2T85B1SHJMBYZAXN-fra

… anything else that might be missing here? [services.ports.http_options.response.headers] position in my .toml is right after [[services.ports]]. Here I share whole .toml file:

# fly.toml file generated for donationbox-lv on 2022-12-16T22:45:31+02:00

app = "donationbox-lv-1"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[build]
  [build.args]
    NODE_VERSION = "14"
    PHP_VERSION = "8.0"

[env]
  APP_ENV = "production"
  LOG_CHANNEL = "stderr"
  LOG_LEVEL = "info"
  LOG_STDERR_FORMATTER = "Monolog\\Formatter\\JsonFormatter"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  http_checks = []
  internal_port = 8080
  processes = ["app"]
  protocol = "tcp"
  script_checks = []
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

[services.ports.http_options.response.headers]
X-Frame-Options = false
Content-Security-Policy = "frame-ancestors https://donationbox.lv"

  [[services.tcp_checks]]
    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

Not sure what’s up there. If you have 3 apps, are you definitely deploying to the one you expect? Does fly status (pointing to the correct app) show you what you expect?

The other thing is to check your whitespace and maybe move those options to last.

I don’t really think this should matter, but maybe lets be sure! Here’s what works for me:

# fly.toml file generated for dumptests on 2023-03-17T15:11:40-04:00

app = "dumptests"
kill_signal = "SIGINT"
kill_timeout = 5
primary_region = "bos"
processes = []

[build]
  [build.args]
    NODE_VERSION = "14"
    PHP_VERSION = "8.2"

[env]
  APP_ENV = "production"
  LOG_CHANNEL = "stderr"
  LOG_LEVEL = "info"
  LOG_STDERR_FORMATTER = "Monolog\\Formatter\\JsonFormatter"

[experimental]
  auto_rollback = true

[[services]]
  http_checks = []
  internal_port = 8080
  processes = ["app"]
  protocol = "tcp"
  script_checks = []
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [[services.tcp_checks]]
    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

  [services.ports.http_options.response.headers]
    X-Frame-Options = false
    Content-Security-Policy = "frame-ancestors https://dumptests.fly.dev"

If you can’t get that working, try creating a new app to see if the same settings Just Work on that new application (you can destroy that new application later if you want). If the new application Just Works™, we can see if some issue is specific to that one app that’s not picking up those issues.

You were right, I needed to mention the config file as a parameter during the deployment. For others who would be looking for this information:

flyctl deploy --remote-only --config fly.[YOUR-APPLICATION-NAME].toml -a [YOUR-APPLICATION-NAME]

Actually, disabling X-Frame-Options helped me, now I will adjust Content-Security-Policy to make it work. Huge thanks to @fideloper-fly for helping to find the solution! Great job :raised_hands:

1 Like

Wew, great! Glad we got that working!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.