Unable to overwrite X-Frame-Options

Hello! Thanks for running this forum, it's been super useful in helping us run Traefik! Essentially, we are running a low-code self-hosted app builder called Budibase and using Traefik as the reverse proxy. Budibase sets the X-Frame-Option to SAMEORIGIN by default but we want to overwrite it to allow from any origin. Our docker compose currently looks like the below but the X-Frame-Option header is still SAMEORIGIN. Any help would be greatly appreciated!

version: "3"

# optional ports are specified throughout for more advanced use cases.

services:
  reverse-proxy:
    image: traefik:2.7
    command:
      - --providers.docker
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
      - --accessLog={}
      - --api.dashboard=true
      - --api.insecure=true
      - --certificatesResolvers.resolver.acme.email=admin@domain.com
      - --certificatesResolvers.resolver.acme.storage=acme.json
      - --certificatesResolvers.resolver.acme.httpChallenge.entryPoint=web
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/app/acme.json:/acme.json
    ports:
      - '80:80'
      - '443:443'
    restart: always
    labels:
      - traefik.enable=true
      - traefik.http.routers.http-catchall.rule=Host(`domain.com`)
      - traefik.http.routers.http-catchall.entrypoints=web
      - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
      - traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true
      - traefik.http.middlewares.x-frame-options.headers.customFrameOptionsValue="ALLOW-FROM *"
      - traefik.http.routers.http-catchall.middlewares=x-frame-options,redirect-to-https

  app-service:
    restart: unless-stopped
    image: budibase.docker.scarf.sh/budibase/apps
    container_name: bbapps
    environment:
      SELF_HOSTED: 1
      COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
      WORKER_URL: http://worker-service:4003
      MINIO_URL: http://minio-service:9000
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
      INTERNAL_API_KEY: ${INTERNAL_API_KEY}
      BUDIBASE_ENVIRONMENT: ${BUDIBASE_ENVIRONMENT}
      PORT: 4002
      API_ENCRYPTION_KEY: ${API_ENCRYPTION_KEY}
      JWT_SECRET: ${JWT_SECRET}
      LOG_LEVEL: info
      SENTRY_DSN: https://a34ae347621946bf8acded18e5b7d4b8@o420233.ingest.sentry.io/5338131
      ENABLE_ANALYTICS: "true"
      REDIS_URL: redis-service:6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}
      BB_ADMIN_USER_EMAIL: ${BB_ADMIN_USER_EMAIL}
      BB_ADMIN_USER_PASSWORD: ${BB_ADMIN_USER_PASSWORD}
      PLUGINS_DIR: ${PLUGINS_DIR}
    depends_on:
      - worker-service
      - redis-service
#    volumes:
#      - /some/path/to/plugins:/plugins

  worker-service:
    restart: unless-stopped
    image: budibase.docker.scarf.sh/budibase/worker
    container_name: bbworker
    environment:
      SELF_HOSTED: 1
      PORT: 4003
      CLUSTER_PORT: ${MAIN_PORT}
      API_ENCRYPTION_KEY: ${API_ENCRYPTION_KEY}
      JWT_SECRET: ${JWT_SECRET}
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
      MINIO_URL: http://minio-service:9000
      APPS_URL: http://app-service:4002
      COUCH_DB_USERNAME: ${COUCH_DB_USER}
      COUCH_DB_PASSWORD: ${COUCH_DB_PASSWORD}
      COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
      SENTRY_DSN: https://a34ae347621946bf8acded18e5b7d4b8@o420233.ingest.sentry.io/5338131
      INTERNAL_API_KEY: ${INTERNAL_API_KEY}
      REDIS_URL: redis-service:6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}
    depends_on:
      - redis-service
      - minio-service
      - couch-init

  minio-service:
    restart: unless-stopped
    image: minio/minio
    volumes:
      - minio_data:/data
    environment:
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
      MINIO_BROWSER: "off"
    command: server /data --console-address ":9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  proxy-service:
    restart: unless-stopped
    ports:
      - "${MAIN_PORT}:10000"
    container_name: bbproxy
    image: budibase/proxy
    environment:
      - PROXY_RATE_LIMIT_WEBHOOKS_PER_SECOND=10
      - PROXY_RATE_LIMIT_API_PER_SECOND=20
      - APPS_UPSTREAM_URL=http://app-service:4002
      - WORKER_UPSTREAM_URL=http://worker-service:4003
      - MINIO_UPSTREAM_URL=http://minio-service:9000
      - COUCHDB_UPSTREAM_URL=http://couchdb-service:5984
      - WATCHTOWER_UPSTREAM_URL=http://watchtower-service:8080
      - RESOLVER=127.0.0.11
    depends_on:
      - minio-service
      - worker-service
      - app-service
      - couchdb-service

  couchdb-service:
    restart: unless-stopped
    image: ibmcom/couchdb3
    environment:
      - COUCHDB_PASSWORD=${COUCH_DB_PASSWORD}
      - COUCHDB_USER=${COUCH_DB_USER}
    volumes:
      - couchdb3_data:/opt/couchdb/data

  couch-init:
    image: curlimages/curl
    environment:
      PUT_CALL: "curl -u ${COUCH_DB_USER}:${COUCH_DB_PASSWORD} -X PUT couchdb-service:5984"
    depends_on:
      - couchdb-service
    command: ["sh","-c","sleep 10 && $${PUT_CALL}/_users && $${PUT_CALL}/_replicator; fg;"]

  redis-service:
    restart: unless-stopped
    image: redis
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data

  watchtower-service:
    restart: always
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --debug --http-api-update bbapps bbworker bbproxy
    environment:
      - WATCHTOWER_HTTP_API=true
      - WATCHTOWER_HTTP_API_TOKEN=budibase
      - WATCHTOWER_CLEANUP=true
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

volumes:
  couchdb3_data:
    driver: local
  minio_data:
    driver: local
  redis_data:
    driver: local

Some browsers may be moving to a more modern approach by using the "Content-Security-Policy" (CSP) header with the frame-ancestors directive instead of "X-Frame-Options".
Maybe you can try:

middlewares
    x-frame-options:
          headers:
            contentSecurityPolicy: "frame-ancestors *;"

Therefore if you embeds iframe from your own domain/subdomains, it's more safe to use:

middlewares
    x-frame-options:
          headers:
            contentSecurityPolicy: "frame-ancestors 'self';

Thanks a lot for looking at this! Also, sorry for the delay in my response, I'm only just getting round to looking at this again. It worked when I applied this middleware option to the reverse-proxy and the Budibase proxy services!

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