DOKIMASecurity review report

Overview

No X-Frame-Options or CSP frame-ancestors on any response leaves the authenticated UI fully framable (clickjacking)

low Fully Valid high confidence

DOK-100022-FILEBROWSER-HTTP-ROUTER-MIDDLE-AUTHENTICATED-SPA · filebrowser · http-router-middleware

Status

Fully Valid

The anti-framing control is concretely absent (verified in headers.go, http.go, mux source, and a repo-wide grep), so the security property 'the authenticated UI cannot be framed by a hostile origin' is violated — a genuine clickjacking exposure, fully_valid. Distinct from DOK-100004/100010 (script-injection CSP vs framing). Severity low because exploitation requires victim interaction with a hostile framing page.

Repository / Component

Repository
filebrowser
Component
http-router-middleware

Plain-English Description

The application never tells browsers it should not be embedded in a frame. A malicious site can load the logged-in interface inside a hidden frame and trick a user into clicking controls that perform real file actions without realizing it.

Description of the Underlying Issue

No response from the application sets an anti-framing control. globalHeaders contains only Cache-Control (http/headers.go:6-8) — no X-Frame-Options. The global CSP set by the r.Use middleware is default-src 'self'; style-src 'unsafe-inline'; (http/http.go:30-35) with no frame-ancestors directive, and that middleware does not even run for the index/NotFoundHandler (gorilla/mux v1.8.1 mux.go:159-163), so the main document gets no CSP at all. A repository-wide grep of *.go finds no X-Frame-Options and no frame-ancestors anywhere. Because the frontend authenticates mutations using an X-Auth token drawn from localStorage jwt (frontend/src/utils/auth.ts, api/utils.ts), a same-origin framed context retains that credential, so click-driven file operations remain reachable inside a frame. The security property 'the authenticated UI cannot be framed by a hostile origin' is therefore violated.

Potential Attack

An attacker hosts a cross-origin page that embeds the filebrowser app in a (possibly transparent/overlaid) iframe and uses UI-redressing to position bait elements over sensitive controls. A victim who is logged in (JWT in localStorage) and induced to interact with the attacker's page unknowingly clicks buttons in the framed authenticated UI, triggering real actions such as delete, share, or move. There is no client-side frame-busting to interrupt this.

Outcomes of Potential Attack

Successful clickjacking lets the attacker cause the victim to perform authenticated, state-changing file operations (delete/share/move and similar) without the victim's awareness, using the victim's own session. Impact is bounded by requiring victim interaction with the hostile framing page and the victim being logged in.

Affected Scope

The entire authenticated SPA (all documents/routes); clickjacking of authenticated file operations (delete/share/move) driven by localStorage JWT.

Suggested Fix (plain english)

Send an anti-framing header on every response so browsers refuse to embed the app in a frame from other sites.

Suggested Fix (detailed)

Add X-Frame-Options: DENY (or SAMEORIGIN if same-origin framing is required) to globalHeaders (http/headers.go:6-8) and/or add a CSP frame-ancestors 'none' directive (http/http.go:30-35). Because route middleware does not cover the index/NotFoundHandler in gorilla/mux v1.8.1 (mux.go:159-163), ensure the anti-framing header is applied to every response including the index handler (http/static.go index handler) — e.g. via globalHeaders, which is emitted unconditionally, or by wrapping NotFoundHandler. Verify by requesting GET / and an API route and confirming X-Frame-Options / frame-ancestors is present on both, then confirming the app refuses to render inside a cross-origin iframe. Distinct from DOK-100004/DOK-100010, which concern script-injection CSP coverage rather than framing. Add X-Frame-Options: DENY (or SAMEORIGIN) and/or a CSP frame-ancestors 'none' directive applied to every response including the index/NotFoundHandler.

Validation

The anti-framing control is concretely absent (verified in headers.go, http.go, mux source, and a repo-wide grep), so the security property 'the authenticated UI cannot be framed by a hostile origin' is violated — a genuine clickjacking exposure, fully_valid. Distinct from DOK-100004/100010 (script-injection CSP vs framing). Severity low because exploitation requires victim interaction with a hostile framing page.

first_opinion

Full Evidence

http/headers.go:6-8 globalHeaders contains only Cache-Control — no X-Frame-Options
http/http.go:30-35 global CSP is default-src 'self'; style-src 'unsafe-inline'; with no frame-ancestors
gorilla/mux@v1.8.1 mux.go:159-163 index/NotFoundHandler receives no CSP at all
grep across *.go: no X-Frame-Options and no frame-ancestors anywhere
frontend/src/utils/auth.ts / api/utils.ts: mutations send X-Auth from localStorage jwt, usable by a same-origin framed context
Proven fact: No X-Frame-Options header is set on any response
Proven fact: No CSP frame-ancestors directive exists; the index document gets no CSP at all
Proven fact: The application is therefore fully framable by any origin
Unvalidated fact: Real-world clickjacking impact depends on a victim being logged in and induced to interact with a hostile framing page; no frame-busting exists client-side to mitigate
http/headers.go:6-8 — globalHeaders contains only Cache-Control; no X-Frame-Options
http/http.go:30-35 — the global CSP is default-src 'self'; style-src 'unsafe-inline'; with no frame-ancestors directive
gorilla/mux@v1.8.1 mux.go:159-163 — the index/NotFoundHandler receives no CSP at all (middleware not applied)
repo-wide grep across *.go: no X-Frame-Options and no frame-ancestors present anywhere
frontend/src/utils/auth.ts, api/utils.ts — mutations send X-Auth from the localStorage jwt, usable by a same-origin framed context
Proven fact: No X-Frame-Options header is set on any response.
Proven fact: No CSP frame-ancestors directive exists, and the index document receives no CSP at all.
Proven fact: The application is therefore fully framable by any origin, with no client-side frame-busting present.
Unvalidated fact: Real-world clickjacking impact depends on a victim being logged in and induced to interact with a hostile framing page; no client-side frame-busting exists to mitigate.
http/http.go:30-35 CSP middleware sets default-src/style-src only, no frame-ancestors
http/headers.go:6-8 globalHeaders contains only Cache-Control
grep: no X-Frame-Options or frame-ancestors in any *.go; no top.location/frame-bust in frontend/src; index.html has no CSP/frame meta
http/http.go:44 NotFoundHandler=index serves the primary SPA document (and per the contradicted assumption router-csp-covers-index-notfound it receives no CSP at all)
frontend/src/utils/auth.ts:82 and frontend/src/api/utils.ts:32 mutations send X-Auth from localStorage jwt, readable by a same-origin framed context