Skip to content

Conversation

@mpivchev
Copy link
Collaborator

@mpivchev mpivchev commented Sep 10, 2025

Resolves: https://github.com/nextcloud-gmbh/h1/issues/453

Prerequisite: nextcloud/NextcloudKit#185

This PR fixes the issue of maliciously spoof naming file names that can trick people into opening a file with a fake extension.

Android released a fix here: nextcloud/android#15388 and their approach is to use 2 text views to separate the string, so the extension part is not affected by the bidi chars.

On iOS however having 2 text views on so many old VCs and Storyboards will cause a lot of issues down the line, especially since now we have ~5 different layout styles for displaying files (list, icons, square grid, aspect ratio grid, recommended files). We also display file names in many other screens and views, and IMO handling all of them was not feasable.

Instead I use a way of clearing all previous bidi overrides and forcing LTR on the extension. This way the file name stays intact, but the extension is sanitized:

if isRTL {
    if containsBidi {
        return "\u{202C}\u{2066}.\(ext)\u{2069}" + base
    } else {
        return ".\(ext)" + base
    }
} else {
    if containsBidi {
        return base + "\u{202C}\u{2066}.\(ext)\u{2069}"
    } else {
        return base + "." + ext
    }
}

A few issues along the way that I fixed:

  • Regular iOS truncating of the text broke the way the text was sanitized, and causing Arabic to appear after the extension. I am guessing this was because some of the extension BIDI isolates were removed along with the truncation, as iOS/MacOS truncating does not take BIDI chars into account at all:
image

I added a custom truncator that splits the text down the middle but preservers the extension + its own BIDI isolates at the end. One of the main points of the original issue is that we should not modify the base name when sanitizing it. However truncating is an exception, as iOS already modifies it by removing parts of it. I do what is otherwise inevitable while still preserving the extension.

There are a few caveats + TODOs:

  • So far only single line UILabels are supported, which means all the gridviews must be quickly redone to display 1 line instead of 2. This also means that there will be less text shown, and font size must be reduced.

Important to note that this would have also been an issue if I used 2 text views, as I am not aware of any non-headache inducing way to align a multi-line text view with another one at the precise place where the extension must be shown.

  • Use the sanitizer in every other view that displays a file name.
  • Add missing docs

Comparisons to ensure it works the same:

LTR:

image

RTL:

image

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
@mpivchev
Copy link
Collaborator Author

@marinofaggiana what do you think about this?

@marinofaggiana
Copy link
Member

Changing the views (2 labels instead of one) is not a "simple" thing, unfortunately it would be necessary to review a few things, in my opinion it's fine like this.

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
@mpivchev mpivchev merged commit 8e0e2cb into master Sep 16, 2025
5 checks passed
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.

3 participants