PeekList: How Brave's Playlist bypassed FaceID Protection for Private Tabs
Summary: Brave for iOS lets you lock Private Tabs behind Face ID or a device passcode. That protection can be completely bypassed using the built-in Brave Playlist feature. Adding any video or audio to your Playlist and then selecting "Open in a New Private Tab" from the long-press menu opens a Private Tab with zero authentication prompt even when Face ID/Passcode protection is enabled. This means an attacker with brief physical access to an unlocked device could view a victim's Private Tab content without ever being asked to authenticate. The issue was reported to Brave via HackerOne and has since been addressed.
The Discovery Process
Brave Playlist is a separate feature that lets a user save audio or video (for example, a YouTube link) for offline-style playback inside the browser. Playlist items support a long-press context menu with several actions, one of which is "Open in a New Private Tab." That action opens the link directly in a Private Tab, but it does so through a different code path than the normal Private Tab entry point, and that path does not check whether Face ID/Passcode protection is enabled.
Impact
An attacker with physical access to an unlocked iPhone running Brave may be able to use this Playlist bypass to gain access into the user’s Private Tabs, defeating the entire purpose of the Face ID/Passcode setting. This is exactly the kind of “shoulder surf” or “phone left on the table for thirty seconds” scenario the protection exists to prevent, and the Playlist menu quietly gives an attacker a way around it.The Fix
Brave's patch wraps the Playlist's "open in new tab" delegate so that, before a private tab is actually opened, it checks whether Private Tab lock is enabled and the user isn't already in a private session and if so, gates the tab open behind askForLocalAuthentication (Face ID/Passcode) before proceeding. The openTab() closure that actually dismisses the player and calls openURLInNewTab is no longer invoked directly. It's only reached through the conditional: if the destination tab is private, the browser isn't already in a private browsing session, and the user has privateBrowsingLock enabled, the tab open is deferred until askForLocalAuthentication returns success only then does openTab() fire. Previously, openURLInNewTab was called unconditionally from the Playlist delegate with no authentication gate at all, which is exactly the code path this report exploited.
player: player,
delegate: .init(
openTabURL: { [weak browserController] url, isPrivate in
guard let browserController else { return }
let isPrivate = Preferences.Privacy.privateBrowsingOnly.value ? true : isPrivate
let openTab: () -> Void = {
browserController.dismiss(animated: true)
browserController.openURLInNewTab(
url,
isPrivate: isPrivate,
isPrivileged: false
)
}
if isPrivate,
!browserController.privateBrowsingManager.isPrivateBrowsing,
Preferences.Privacy.privateBrowsingLock.value
{
browserController.askForLocalAuthentication { success, _ in
if success {
openTab()
}
}
} else {
openTab()
}
},
onDismissal: { [weak self, weak player] in
guard let self else { return }
Responsible Disclosure Timeline
- April 24th 2026: I submitted a detailed report of the bypass through Brave's HackerOne Program
- April 24th 2026: Brave's triage team confirms they could reproduce the bug
- April 27th 2026: Brave's Team pushes the fix into Brave Nightly
- April 27th 2026: Brave pays out the max medium severity bounty of $250 saying that the bug is medium as attack requires physical access
- April 27th 2026: I request public disclosure of this report
- April 27th 2026: Brave agrees to disclose once its in the release channel.
- April 28th 2026: I ask if my report will be assigned a CVE
- May 19th 2026: Follow up on a request for CVE for this report.
- May 25th 2026: I confirmed that the issue has been addressed in the 1.90 update and request disclosure
- May 28th 2026: My report is made public and no CVE is given. Vulnerability is confirmed fixed by Brave and is in stable release channel.
Final Thoughts
A protection setting is only as strong as its weakest entry point. Brave’s Face ID/Passcode lock for Private Tabs was solid when Private Tabs were opened normally, but a secondary feature Playlist offered a side door that skipped the check entirely. Brave fixed the issue by extending the same authentication requirement to the Playlist “Open in a New Private Tab” action closing the bypass. Big thank you to the Brave Team for taking my report seriously! :D Link to Report: https://hackerone.com/reports/3693295 info sec writeup: https://infosecwriteups.com/peeklist-how-braves-playlist-bypassed-faceid-protection-for-private-tabs-9d1691b077be