Round-5 audit verdict: SHIP. Zero new CRIT/HIGH after the round-7
honesty check confirmed diminishing returns. Only follow-up was a
stale manifest comment pointing at YT_HOSTS (collapsed to util.YtUrl
in vc=42); rewritten to point at util/YtUrl.kt's ALLOWED_YT_HOSTS.
The 5-round audit loop (rounds 4-8 overall, after vc=38's prior
3 rounds): 18 HIGH + 28 MED + handfuls of LOW landed across vc=39
through vc=43. Most material fixes:
* Rust runtime ensure_initialized wired into every extractor
entry, mutex-first then try_lock (no UI freeze on slow init)
* VideoDetail / Channel / Search VM in-flight cancel + fence
pattern; runCatchingCancellable to defeat the runCatching-eats-
cancellation hazard at every coroutine boundary
* Allowlist gate on every extractor entry point (not just
persistence) — util/YtUrl with scheme + trailing-dot defenses
* Bulk-import write-storm collapse on every store + return-real-
added-count so the import summary doesn't lie at saturation
* SponsorBlock skip-loop pause-skip + 50ms-exclusion drop
* Recapcha URL strip-continue-param in Rust before propagation
* SettingsStore truly atomic+idempotent; PlaylistsStore bulk
* Hostile-zip duplicate-entry rejection + playlist LIMITs
91 lines
4.7 KiB
XML
91 lines
4.7 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
<!-- Background audio playback -->
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
|
<!-- Android 13+ runtime notification permission for media controls -->
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
<!-- Wake while audio plays -->
|
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
|
|
<!-- DownloadManager Request.setNotificationVisibility(HIDDEN) requires
|
|
this permission. Used by Downloader so signed googlevideo URLs
|
|
don't surface in the system notification shade. -->
|
|
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
|
|
|
|
<application
|
|
android:name=".StrawApp"
|
|
android:label="@string/app_name"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:roundIcon="@mipmap/ic_launcher_round"
|
|
android:supportsRtl="true"
|
|
android:allowBackup="false"
|
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
|
android:fullBackupContent="false"
|
|
android:networkSecurityConfig="@xml/network_security_config"
|
|
android:theme="@android:style/Theme.Material.Light.NoActionBar">
|
|
<activity
|
|
android:name=".StrawActivity"
|
|
android:exported="true"
|
|
android:launchMode="singleTask"
|
|
android:supportsPictureInPicture="true"
|
|
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboardHidden">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
</intent-filter>
|
|
<!-- Open YouTube URLs with Straw. Hosts here must stay in sync
|
|
with ALLOWED_YT_HOSTS in util/YtUrl.kt (canonical home as
|
|
of vc=42 — was previously inlined in StrawActivity.kt
|
|
under YT_HOSTS; drift was caught in the vc=34 function
|
|
audit, music.youtube.com etc. were accepted by code but
|
|
never offered by the launcher disambig). -->
|
|
<intent-filter android:autoVerify="false">
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data android:scheme="https" />
|
|
<data android:host="www.youtube.com" />
|
|
<data android:host="m.youtube.com" />
|
|
<data android:host="youtube.com" />
|
|
<data android:host="youtu.be" />
|
|
<data android:host="music.youtube.com" />
|
|
<data android:host="youtube-nocookie.com" />
|
|
<data android:host="www.youtube-nocookie.com" />
|
|
</intent-filter>
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.SEND" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<data android:mimeType="text/plain" />
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<!-- Phase M-2 / S: MediaSessionService for background audio + notification + lock-screen
|
|
controls. Marked NOT exported (audit CRIT-2): any installed app can otherwise
|
|
craft an Intent with the MediaSessionService action and drive playback from
|
|
attacker-controlled URLs. The intent-filter stays so the Media3 session router
|
|
can find the service within our own process. -->
|
|
<service
|
|
android:name=".feature.player.PlaybackService"
|
|
android:exported="false"
|
|
android:foregroundServiceType="mediaPlayback">
|
|
<intent-filter>
|
|
<action android:name="androidx.media3.session.MediaSessionService" />
|
|
</intent-filter>
|
|
</service>
|
|
|
|
<!-- FileProvider for sharing log dumps from Settings → Export logs. -->
|
|
<provider
|
|
android:name="androidx.core.content.FileProvider"
|
|
android:authorities="${applicationId}.fileprovider"
|
|
android:exported="false"
|
|
android:grantUriPermissions="true">
|
|
<meta-data
|
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
android:resource="@xml/file_paths" />
|
|
</provider>
|
|
</application>
|
|
</manifest>
|