reliability + security fix sprint (vc=91)
Straw full-audit fix batch (2026-07-04). Confirmed HIGH/MED findings: - Updater self-brick: drop the fdroid.sulkta.com leaf+E7 SPKI pins (LE rotates the leaf every ~90d + intermediates from a pool → a routine renewal was guaranteed to miss both pins and silently kill the only in-app update path). System-CA validation + the install-time APK signature gate remain. Also distinguish "index unreachable" from "up to date", add a 30s callTimeout + bounded index read, guard the API-26 NotificationChannel, and setOnlyAlertOnce. - Request POST_NOTIFICATIONS at runtime so A13+ update/media notifications actually post (was declared but never requested → silent no-op). - isDebuggable=false on the shipped debug variant (closes ADB run-as dump of watch/search history + subs; no package-id cutover). - Crash fixes: distinctBy(url) on moreFromChannel + related (duplicate LazyColumn key); back-handling driven by live nav depth so it survives moveTaskToBack on A12+; PlaylistsStore per-store caps + off-main hydration (hostile import ANR); SponsorBlock staleness fence via NowPlaying.refreshIfCurrent. - CacheCap.nearest() snaps up to the nearest finite cap (defaults no longer resolve to Unlimited/100k on fresh installs). - RYD/SB FFI shims wrap the uniffi call (swallow a core panic per contract). - Rust wrapper: release panic="unwind" (was "abort", which defeated UniFFI catch_unwind → any core panic = whole-app SIGABRT) + a 60s wall-clock timeout on every blocking extractor call (unblocks the caller, bounds thread pileup). Pairs with the strawcore-core reliability fix.
This commit is contained in:
parent
410e44305e
commit
e4a8751942
18 changed files with 508 additions and 161 deletions
|
|
@ -9,6 +9,53 @@ const val STRAW_SDK_TARGET = 35
|
|||
|
||||
// Sulkta fork — Straw
|
||||
//
|
||||
// vc=91 / 0.1.0-CY — reliability + security fix sprint (straw audit 2026-07-04):
|
||||
// * The in-app updater no longer self-bricks on a routine cert renewal. It
|
||||
// used to pin the fdroid.sulkta.com leaf SPKI + the LE "E7" intermediate,
|
||||
// but the leaf rotates every ~90-day renewal and LE rotates intermediates
|
||||
// from a pool (they explicitly say don't pin them), so a normal renewal was
|
||||
// GUARANTEED to miss both pins — silently killing the ONLY update path,
|
||||
// with the fix reachable only through the channel the break just killed.
|
||||
// Dropped pinning: default system-CA validation still blocks a MITM, and a
|
||||
// swapped APK can't install over Straw anyway (the package installer
|
||||
// verifies it against our signing key). Also: the check now distinguishes
|
||||
// "couldn't reach the index" from "up to date" (no more "checked just now /
|
||||
// up to date" while actually blind), added a 30s call timeout + a bounded
|
||||
// index read, guarded the API-26 NotificationChannel (was a crash on 7.x),
|
||||
// and setOnlyAlertOnce so a pending update doesn't re-nag every tick.
|
||||
// * Android 13+ update/media notifications actually appear now:
|
||||
// POST_NOTIFICATIONS was manifest-declared but never requested at runtime,
|
||||
// so nm.notify() was a silent no-op on 13+. Requested once on cold start.
|
||||
// * The published APK is no longer debuggable (isDebuggable=false on the
|
||||
// shipped debug variant) — closes an ADB/USB `run-as` dump of watch/search
|
||||
// history + the subscription list. No package-id cutover; updates in place.
|
||||
// * Crash fixes: (a) opening a video whose channel repeats a videoId in its
|
||||
// first ~20 entries hard-crashed Compose on a duplicate LazyColumn key —
|
||||
// moreFromChannel + related now distinctBy url; (b) in-app back died
|
||||
// permanently after one back-to-Home on Android 12+ (moveTaskToBack doesn't
|
||||
// destroy the activity, so the disabled callback never re-enabled) — the
|
||||
// callback is now driven by live nav depth instead of disable-and-redispatch;
|
||||
// (c) the local-playlists store was uncapped, so a hostile NewPipe import
|
||||
// could persist a huge blob that ANR'd every cold start — added per-store
|
||||
// caps (playlists / items / string length) + off-main hydration like
|
||||
// ResumePositionsStore; (d) a SponsorBlock fetch that resolves after you
|
||||
// skip to another video no longer hijacks the now-playing item (staleness
|
||||
// fence).
|
||||
// * Cache-size caps that first-launch defaulted to "Unlimited" (100k rows,
|
||||
// because nearest() was exact-match-or-Unlimited over a set the defaults
|
||||
// weren't in) now snap up to the nearest finite cap.
|
||||
// * The RYD + SponsorBlock FFI shims wrap the uniffi call, so a core panic
|
||||
// (now catchable — see below) is swallowed to null/empty per their contract
|
||||
// instead of crashing video-detail load.
|
||||
// * Rust FFI wrapper: release profile is panic="unwind" (was "abort" — abort
|
||||
// defeated UniFFI's catch_unwind + tokio's spawn_blocking JoinError capture,
|
||||
// turning ANY panic in the extractor core into a whole-app SIGABRT), and
|
||||
// every blocking extractor call is wrapped in a 60s wall-clock timeout so a
|
||||
// wedged JS/HTTP path unblocks the caller instead of spinning forever and
|
||||
// piling detached threads toward tokio's 512 blocking-pool cap. Pairs with
|
||||
// the strawcore-core reliability fix (bounded rquickjs 64MiB/2MiB/5s +
|
||||
// invalidate-on-failure player.js self-heal).
|
||||
//
|
||||
// vc=90 / 0.1.0-CX — cold-start hydration + status-bar bleed fix + RYD FFI slim:
|
||||
// * ResumePositionsStore + EnrichmentStore no longer JSON-decode on the main
|
||||
// thread in Application.onCreate. Resume was the heaviest cold-start cost in
|
||||
|
|
@ -312,6 +359,6 @@ const val STRAW_SDK_TARGET = 35
|
|||
// vc=19 / 0.1.0-AE — rust pipeline cutover. Extraction via
|
||||
// strawcore-core (Sulkta-OSS/strawcore) via the UniFFI wrapper; no
|
||||
// NewPipeExtractor in the runtime path.
|
||||
const val STRAW_VERSION_CODE = 90
|
||||
const val STRAW_VERSION_NAME = "0.1.0-CX"
|
||||
const val STRAW_VERSION_CODE = 91
|
||||
const val STRAW_VERSION_NAME = "0.1.0-CY"
|
||||
const val STRAW_APPLICATION_ID = "com.sulkta.straw"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue