Subtitle auto-detection bypasses the access-rules checker, disclosing hidden/deny-ruled file paths
low Fully Valid high confidence
Status
Fully Valid
Confirmed information disclosure of file paths that HideDotfiles/deny-rules should hide; the control bypass is complete in source. Low severity as it is path/existence disclosure, not content.
Repository / Component
Plain-English Description
When the app lists a folder that contains a video, it automatically looks for matching subtitle files and returns their names — even for files that the folder's own visibility rules were supposed to hide. Someone browsing the folder can therefore learn that hidden files exist and see their names.
Description of the Underlying Issue
detectSubtitles/loadSubtitles (files/file.go:331-378) enumerate subtitle files adjacent to a video and attach them to the video's FileInfo, but they never receive or consult the rules.Checker that enforces HideDotfiles and the deny/allow rules. The child FileInfo's currentDir is populated from the full, unfiltered ReadDir result (files/file.go:437), and Check() is applied only to the listing's Items (files/file.go:410), not to subtitle detection. For a 'subs/' directory, loadSubtitles is called with an empty base name and adds any .vtt/.srt/.ass/.ssa entry regardless of name. The result is that paths the Checker (http/data.go:29-47) would suppress are serialized into the Subtitles field of the response JSON (files/file.go:48).
Potential Attack
An authenticated user with listing access to a directory requests a normal directory listing (or a single-file GET) for a folder that contains a visible video alongside a subtitle file that HideDotfiles or a deny rule was meant to hide (a dotfile subtitle matching the video basename, or any subtitle placed in a 'subs/' subdirectory). The subtitle enumeration ignores the Checker and returns the hidden path.
Outcomes of Potential Attack
The attacker obtains the names and existence of files that the configured visibility rules were intended to conceal. This is path/existence disclosure only; it reveals naming, structure, and the presence of otherwise-hidden files, which can aid reconnaissance, but it does not return the hidden file's contents.
Affected Scope
FileInfo.detectSubtitles / loadSubtitles (files/file.go:331-378); Subtitles field serialized in GET/listing JSON (files/file.go:48)
Suggested Fix (plain english)
Make the subtitle finder obey the same visibility rules the rest of the file listing uses, so hidden and blocked files are skipped instead of returned.
Suggested Fix (detailed)
Thread the rules.Checker into detectSubtitles and loadSubtitles (files/file.go:331-378) and skip any entry that fails Check(), mirroring the filtering already applied to listing Items at files/file.go:410. Verify by listing a directory with a hidden/deny-ruled subtitle matching a visible video (and a subtitle inside a 'subs/' subdir) and confirming the denied paths no longer appear in the Subtitles[] array. Thread the rules.Checker into detectSubtitles/loadSubtitles and skip entries that fail Check().
Validation
Confirmed information disclosure of file paths that HideDotfiles/deny-rules should hide; the control bypass is complete in source. Low severity as it is path/existence disclosure, not content.
Full Evidence
files/file.go:331-378 detectSubtitles/loadSubtitles take no rules.Checker and call addSubtitle for any matching entry
files/file.go:437 the child FileInfo's currentDir is set to the FULL unfiltered ReadDir result; file.go:410 Check() is applied only to listing Items, not to subtitle detection
files/file.go:366-375 loadSubtitles with baseName '' (subs/ dirs) adds ANY .vtt/.srt/.ass/.ssa file regardless of name
http/data.go:29-47 Check() enforces HideDotfiles + deny/allow rules that this path never consults
Proven fact: Subtitle auto-detection never consults the rules Checker, so hidden-dotfile and deny-ruled subtitle paths adjacent to a visible video (or any subtitle inside a subs/ directory) are enumerated and returned in the response JSON
Unvalidated fact: This leaks path/existence only: fetching a rule-denied subtitle's CONTENT is still blocked because subtitleHandler (http/subtitle.go:24) and rawHandler apply the Checker
files/file.go:331-378 — detectSubtitles/loadSubtitles take no rules.Checker and call addSubtitle for any matching entry
files/file.go:437 — the child FileInfo's currentDir is set from the FULL unfiltered ReadDir result
files/file.go:410 — Check() is applied only to listing Items, not to subtitle detection
files/file.go:366-375 — loadSubtitles with an empty base name (subs/ directories) adds ANY .vtt/.srt/.ass/.ssa file regardless of name
files/file.go:48 — the Subtitles field is serialized into the response JSON
http/data.go:29-47 — Check() enforces HideDotfiles plus deny/allow rules that the subtitle path never consults
Proven fact: Subtitle auto-detection never consults the rules Checker, so hidden-dotfile and deny-ruled subtitle paths adjacent to a visible video, or any subtitle inside a subs/ directory, are enumerated and returned in the response JSON.
Unvalidated fact: This leaks path/existence only; fetching a rule-denied subtitle's content is still blocked because subtitleHandler (http/subtitle.go:24) and the raw handler apply the Checker.
files/file.go:331-364 detectSubtitles: no checker parameter; iterates i.currentDir (raw dir) and path.Join(parentDir, f.Name()) via addSubtitle
files/file.go:366-378 loadSubtitles: no checker; recurses subs dirs and addSubtitle for any IsSupportedSubtitle file
files/file.go:437 currentDir is the unfiltered ReadDir result (per-entry Check at file.go:410 is applied only to the listing items, not to subtitle detection)
files/file.go:48 Subtitles is serialized in the response JSON
http/data.go:29-47 Check enforces HideDotfiles + deny/allow rules that this path never consults
grep confirms detectSubtitles/loadSubtitles are never passed a rules.Checker