Skip to content

fix(nova_file_controller): prevent path traversal in static file routes#383

Open
Taure wants to merge 2 commits into
novaframework:masterfrom
Taure:fix/static-file-path-traversal
Open

fix(nova_file_controller): prevent path traversal in static file routes#383
Taure wants to merge 2 commits into
novaframework:masterfrom
Taure:fix/static-file-path-traversal

Conversation

@Taure
Copy link
Copy Markdown
Collaborator

@Taure Taure commented May 11, 2026

Fixes a path-traversal weakness in nova_file_controller:get_dir/1: user-supplied URL segments were joined onto the served root without canonicalisation, so a request containing .. (or %2E%2E once decoded) could escape the served directory.

The controller now:

  • Decodes each pathinfo segment.
  • Rejects absolute segments and decode failures.
  • Walks ./.. against a zero-depth floor; anything climbing above the root returns 403.

This also unblocks safe URL-decoding of segments, so UTF-8 filenames served from a wildcard route work as expected (which addresses the legitimate part of #381 — that PR can rebase on this and drop the hand-rolled decode in get_dir, leaving only the mime / file_info fixes).

Eight new EUnit tests cover:

  • Normal file serve.
  • 404 for missing file.
  • Literal .. traversal -> 403.
  • URL-encoded %2E%2E traversal -> 403.
  • Mixed-case %2e%2E -> 403.
  • URL-encoded slash %2E%2E%2F... -> 403.
  • Absolute path segment -> 403.
  • URL-encoded UTF-8 filename serves correctly.

Test plan

  • rebar3 eunit (390 tests, 0 failures)
  • rebar3 dialyzer (clean)
  • rebar3 xref (clean)
  • ~/bin/elp eqwalize nova_file_controller (no new errors)

Taure added 2 commits May 11, 2026 20:43
User-supplied path segments were joined onto the served root without
canonicalisation, so a request containing .. (or %2E%2E once decoded)
could escape the served directory. The controller now decodes each
segment, rejects absolute paths, and resolves . and .. against a
zero-depth floor; any attempt to climb above the root returns 403.

Also unblocks safe URL-decoding of segments, so UTF-8 filenames
served from a wildcard route work as expected.
Adds 13 tests covering depth-counting edge cases (chained .., mixed
subdir/.., long traversal chains, going below root after descending),
common bypass attempts (double URL encoding, backslash, empty segment,
'...', NUL byte), and previously-untested positive paths (subdirectory
serve, '.' segments, .. that resolves back inside root).
@Taure Taure requested a review from burbas May 11, 2026 18:49
@burbas burbas self-assigned this May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants