Repository: traefik/traefik
File: pkg/api/dashboard/dashboard.go (Go)

Code before:
			http.Redirect(resp, req, safePrefix(req)+dashboardPath, http.StatusFound)
		})

	router.Methods(http.MethodGet).
		Path(dashboardPath).
		HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// allow iframes from our domains only
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
			w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;")

			// The content type must be guessed by the file server.
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
			w.Header().Del("Content-Type")

			apiPath := strings.TrimSuffix(basePath, "/") + "/api/"
			if err = indexTemplate.Execute(w, indexTemplateData{APIUrl: apiPath}); err != nil {
				log.Error().Err(err).Msg("Unable to render index template")
				http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
				return
			}
		})

	router.Methods(http.MethodGet).
		PathPrefix(dashboardPath).
		HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// allow iframes from our domains only
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
			w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;")

			// The content type must be guessed by the file server.
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
			w.Header().Del("Content-Type")

			http.StripPrefix(dashboardPath, http.FileServerFS(assets)).ServeHTTP(w, r)
		})
	return nil
}

func safePrefix(req *http.Request) string {
	prefix := req.Header.Get("X-Forwarded-Prefix")
	if prefix == "" {
		return ""
	}

	parse, err := url.Parse(prefix)
	if err != nil {
		return ""
	}

	if parse.Host != "" {
		return ""

Review comment (suggestion):
```suggestion
			// allow iframes from traefik domains only
```

Code after:
			http.Redirect(resp, req, prefix+dashboardPath, http.StatusFound)
		})

	router.Methods(http.MethodGet).
		Path(dashboardPath).
		HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// allow iframes from our domains only
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
			w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;")

			// The content type must be guessed by the file server.
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
			w.Header().Del("Content-Type")

			apiPath := strings.TrimSuffix(basePath, "/") + "/api/"
			if err = indexTemplate.Execute(w, indexTemplateData{APIUrl: apiPath}); err != nil {
				log.Error().Err(err).Msg("Unable to render index template")
				http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
				return
			}
		})

	router.Methods(http.MethodGet).
		PathPrefix(dashboardPath).
		HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// allow iframes from traefik domains only
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
			w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;")

			// The content type must be guessed by the file server.
			// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
			w.Header().Del("Content-Type")

			http.StripPrefix(dashboardPath, http.FileServerFS(assets)).ServeHTTP(w, r)
		})
	return nil
}