11package com.csguard
22
3- /* *
4- * Known ad-network / popunder domains used by malicious CloudStream extensions.
5- *
6- * This list is seeded from a real-world analysis of
7- * malicious extensions, where the constant
8- *
9- * OMG10 = "aHR0cHM6Ly9vbWcxMC5jb20vNC8xMTEwNDQ4OQ=="
10- *
11- * base64-decodes to `https://omg10.com/4/11104489` — an OMG/PropellerAds-style
12- * popunder ad-network URL fired via raw `Intent.ACTION_VIEW` from inside
13- * `MainAPI.loadLinks()` on every Play tap.
14- *
15- * The list is intentionally broad: extensions like this rotate ad networks, so
16- * we block by category rather than just by the single observed domain.
17- */
183object AdBlockList {
194
20- // ---- Hard-blocked hosts (known ad networks / popunders / redirectors) ----
215 val BLOCKED_HOSTS : Set <String > = setOf (
22- // Observed in CNCVerse repo
6+
237 " omg10.com" ,
248 " omg1.com" , " omg2.com" , " omg3.com" , " omg4.com" , " omg5.com" ,
259 " omg6.com" , " omg7.com" , " omg8.com" , " omg9.com" ,
2610
27- // PropellerAds / Monetag family
2811 " propellerads.com" , " propeller-tracking.com" ,
2912 " monetag.com" , " monetag-handhub.com" ,
3013
31- // Adsterra
3214 " adsterra.com" , " adsterra.network" , " prohitshere.com" ,
3315
34- // HilltopAds
3516 " hilltopads.com" , " hilltopads.net" , " hilltopads-delivery.com" ,
3617
37- // PopAds / PopCash
3818 " popads.net" , " popcash.net" , " popmyads.com" ,
3919
40- // Ad-Maven / Maven
4120 " ad-maven.com" , " a-mo.net" , " mvn.link" ,
4221
43- // Shortcutters commonly used by ad-redirect layers
4422 " bit.ly" , " t.ly" , " cutt.ly" , " shorturl.at" , " tinyurl.com" ,
4523 " shrtco.de" , " soo.gd" , " s.id" , " is.gd" , " v.gd" ,
4624 " linkvertise.com" , " linkvertise.net" ,
4725
48- // Generic popunder / malvertising CDNs
4926 " onclickperformance.com" , " onclickprediction.com" ,
5027 " onclickscript.com" , " highperformanceformat.com" ,
5128 " pushmonetization.com" , " realtimepush.com" ,
@@ -56,38 +33,24 @@ object AdBlockList {
5633 " trackings.selfpublishing.com" ,
5734 " xl-trail.com" , " trail_trk.com" ,
5835
59- // Suspicious TLD patterns commonly abused
60- // (will be matched more carefully in code — see isBlocked())
61- )
36+ )
37+
38+ val SAFE_HOSTS : Set < String > = setOf (
6239
63- // ---- Hosts that are explicitly ALLOWED to open externally ----
64- //
65- // CloudStream itself opens these for repo install / legal / community
66- // purposes, and they are user-initiated actions — not silent ad redirects.
67- val SAFE_HOSTS : Set <String > = setOf (
68- // CloudStream infra
6940 " cs.repo" , " cloudstream.on.fleek.co" ,
7041 " recloudstream.github.io" , " github.com" , " raw.githubusercontent.com" ,
7142
72- // Self-promo (user-initiated, in the form of a dialog with a button)
7343 " t.me" , " telegram.me" ,
7444
75- // Common legitimate support sites
7645 " discord.com" , " discord.gg" , " patreon.com" , " ko-fi.com" ,
7746 " buymeacoffee.com" ,
7847
79- // Search/lookup that user might legitimately want
8048 " www.google.com" , " duckduckgo.com" ,
8149
82- // Wikipedia / IMDB for metadata
8350 " wikipedia.org" , " imdb.com"
8451 )
8552
86- // ---- URL patterns that are NEVER media stream URLs ----
87- //
88- // If an ExtractorLink or PlayInBrowser target matches one of these
89- // patterns, it's almost certainly an ad/redirect, not a real video.
90- val NON_MEDIA_PATH_PATTERNS : List <Regex > = listOf (
53+ val NON_MEDIA_PATH_PATTERNS : List <Regex > = listOf (
9154 Regex (" /\\ d+/(\\ d{6,})" ), // /4/11104489 style ad zone IDs
9255 Regex (" /(popunder|popunderinit)" ),
9356 Regex (" /(redirect|go|visit|jump)/[a-zA-Z0-9]+" ),
@@ -96,54 +59,36 @@ object AdBlockList {
9659 Regex (" /aff(_)?id=" )
9760 )
9861
99- /* *
100- * Returns true if the host (or any of its parent domains) is on the
101- * hard-block list.
102- */
103- fun isHostBlocked (host : String? ): Boolean {
62+ fun isHostBlocked (host : String? ): Boolean {
10463 if (host.isNullOrBlank()) return false
10564 val h = host.lowercase().trim()
106- // exact match
65+
10766 if (h in BLOCKED_HOSTS ) return true
108- // suffix match (handles subdomains like ads.omg10.com)
67+
10968 for (blocked in BLOCKED_HOSTS ) {
11069 if (h == blocked || h.endsWith(" .$blocked " )) return true
11170 }
11271 return false
11372 }
11473
115- /* *
116- * Returns true if the host is explicitly allowed to open externally.
117- *
118- * Combines three sources:
119- * 1. [SAFE_HOSTS] — static baseline of CloudStream-essential hosts
120- * 2. [AllowlistStore.alwaysAllow] — persistent user-approved hosts
121- * 3. [AllowlistStore] session allow-once — process-scoped one-shot approvals
122- *
123- * Always called from the [GuardPolicy.shouldBlock] hot path, so it must be fast.
124- */
125- fun isHostSafe (host : String? ): Boolean {
74+ fun isHostSafe (host : String? ): Boolean {
12675 if (host.isNullOrBlank()) return false
12776 val h = host.lowercase().trim()
128- // 1. Static baseline
77+
12978 if (h in SAFE_HOSTS ) return true
13079 for (safe in SAFE_HOSTS ) {
13180 if (h == safe || h.endsWith(" .$safe " )) return true
13281 }
133- // 2 & 3. User-managed allowlist (persistent + session)
82+
13483 return try {
13584 AllowlistStore .isAllowed(h)
13685 } catch (_: Throwable ) {
137- // AllowlistStore not initialized yet — be safe, fall back to baseline
86+
13887 false
13988 }
14089 }
14190
142- /* *
143- * Heuristic: does the URL path look like an ad-redirect path
144- * rather than a real media file?
145- */
146- fun looksLikeAdPath (url : String? ): Boolean {
91+ fun looksLikeAdPath (url : String? ): Boolean {
14792 if (url.isNullOrBlank()) return false
14893 return NON_MEDIA_PATH_PATTERNS .any { it.containsMatchIn(url) }
14994 }
0 commit comments