Skip to content

fix(files): honour the escape flag in every filename validity message - #64374

Open
torvalstrom wants to merge 1 commit into
nextcloud:masterfrom
torvalstrom:fix/filename-validity-honour-escape
Open

torvalstrom wants to merge 1 commit into
nextcloud:masterfrom
torvalstrom:fix/filename-validity-honour-escape

Conversation

@torvalstrom

@torvalstrom torvalstrom commented Sep 15, 2026

Copy link
Copy Markdown

getFilenameValidity() documents its second parameter as

@param escape Escape the matched string in the error (only set when used in HTML)

but only the forbidden-character branch passes it on. The reserved-name and forbidden-extension branches hardcode escape: false, so a caller that asks for escaping — because it renders the result as HTML — gets the matched segment back raw.

Not a vulnerability, to be clear

The segments those two branches report come from server configuration (forbidden_filenames, forbidden_filename_extensions), not from anything an unprivileged user controls, and all three call sites in the tree pass escape = false today. So there is nothing to exploit. What is worth fixing is a documented parameter quietly not doing what it says, before a caller starts relying on it.

Why the existing tests could not catch it

The forbidden-character check runs first, so any name containing <, > or " is rejected there — in the one branch that already honoured the flag. That is why the escape option block only ever exercised that path.

The two new tests use & instead: the translation layer escapes it, but it is not a forbidden filename character, so validation falls through to the reserved-name and extension branches.

Before and after

Same tests, against the unmodified source:

Received: ""a&b" is a reserved name and not allowed for filenames."
Received: "".a&b" is not an allowed filetype."
Tests  2 failed | 16 passed (18)

and with the change:

Tests  18 passed (18)

npx vitest run apps/files/src/ is green overall — 27 files, 198 tests — and npx eslint is clean on both changed files.

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Written with Claude Code (claude-opus-5); every change was reviewed, built and tested by me before opening the PR, and the measurements quoted above are real command output rather than model claims. Commits carry Assisted-by: ClaudeCode:claude-opus-5.

@torvalstrom
torvalstrom requested review from a team and skjnldsv as code owners September 15, 2026 17:14
@torvalstrom
torvalstrom requested review from kristian-zendato and sorbaugh and removed request for a team September 15, 2026 17:14
@skjnldsv
skjnldsv force-pushed the fix/filename-validity-honour-escape branch from 51fd27f to d549b64 Compare September 15, 2026 18:55
@skjnldsv skjnldsv added bug 3. to review Waiting for reviews hotspot: filename handling Filenames - invalid, portable, blacklisting, etc. labels Sep 15, 2026
@skjnldsv

Copy link
Copy Markdown
Member

thanks @torvalstrom ! Quick note, you need to clarify whether you used AI or not in the OR bidy as well as the commit comment with an assisted-by line. See our github template

e.g: Assisted-by: ClaudeCode:claude-fable-5-1

getFilenameValidity() documents its second parameter as "Escape the
matched string in the error (only set when used in HTML)", but only the
forbidden-character branch passed it on. The reserved-name and
forbidden-extension branches hardcoded `escape: false`, so a caller that
asked for escaping because it renders the result as HTML got the matched
segment back raw.

The segments those two branches report come from server configuration -
forbidden_filenames and forbidden_filename_extensions - so this is not
reachable by an unprivileged user, and none of the three call sites in
the tree ask for escaping today. It is the parameter quietly not doing
what it says that is worth fixing, before a caller relies on it.

Note the forbidden-character check runs first, which is why the existing
escape tests could only ever cover that branch: any name containing <, >
or " is rejected there. The new tests use & instead, which is escaped by
the translation layer but is not a forbidden filename character, so it
reaches the other two branches.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Tor Valstrom <51440386+torvalstrom@users.noreply.github.com>
@torvalstrom
torvalstrom force-pushed the fix/filename-validity-honour-escape branch from d549b64 to 0b3dde1 Compare September 15, 2026 19:56
@torvalstrom

Copy link
Copy Markdown
Author

Thanks for the pointer — done, and applied to all five of my open PRs rather than just this one:

Each commit now carries Assisted-by: ClaudeCode:claude-opus-5 above the sign-off, and each PR body has the AI section from the template with the box ticked. DCO is green again after the amend.

Apologies for making you ask — I had read the template's checklist but skipped straight past the AI section at the bottom.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews bug hotspot: filename handling Filenames - invalid, portable, blacklisting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants