OSINT Portfolio / Case 003
Piracy + Backend Exposure + Covert Tracking — HAR + JS Bundle Analysis

Case 003: dulo.cx — Full Stack Exposure of a Streaming Piracy Operation

Passive browser analysis of an unauthorized movie streaming platform — no tools beyond Chrome DevTools and a HAR export. Findings: covert click-fraud tracker on every interaction, their Supabase project URL and anon key in the JS bundle (a public key, so the open question is whether row level security is configured, which was not tested), admin panel routes exposed, self-hosted analytics dashboard publicly accessible, 5 rotating Turnstile keys hardcoded, CORS failures on their own CDN, and zero-consent profiling of anonymous users.

Date: 2026-08-16 Analyst: Sergiu Vincze (SevinHub) Method: HAR file + DevTools JS bundle analysis Severity: P2 — IP Infringement + Backend Exposure + GDPR
Targetdulo.cx
Former Domaindulo.gd (Dulo TV)
Tracker Founday267.com (click-fraud)
BackendSupabase project identified (anon key, public by design)
Console Errors87 errors / 30 warnings
MethodDevTools only — passive
CF Worker ProxyOFFLINE (HTTP 404)
TypeP2 — IP + GDPR + Exposure

dulo.cx (formerly dulo.gd, branded "Dulo TV") is an unauthorized movie and TV streaming site. A passive investigation using only Chrome DevTools and a HAR export produced a complete technical breakdown of their entire operation — far beyond the core copyright violation.

Finding 1 — Critical
Covert click-fraud tracker (ay267.com) — fires on every interaction, zero consent
Finding 2 · Medium
A TMDB v3 API key sits in the JS bundle, visible to every visitor. Read-only metadata key, no private data behind it, but it is their account credential, so it is revocable by TMDB and that is what makes it useful here.
Finding 3 · Informational, not tested
Supabase project URL + anon key readable in the JS bundle. The anon key is public by design, so this is not itself a leak: it identifies the backend and raises the question of whether row level security is configured. We did not query their database, so there is no evidence either way.
Finding 4 — High
Admin panel route map exposed in JS source (/admin, /admin/users, etc.)
Finding 5 — High
Rybbit analytics at stats.dulo.gd — login page publicly accessible
Finding 6 · Informational
5 Cloudflare Turnstile sitekeys in the player bundle. A sitekey belongs in the page, so none of them is leaked; what is notable is that all five are reportable to Cloudflare at once.
Finding 7 — Medium
Video via Cloudflare Worker proxy with signed DASH tokens + alpha/beta tiers
Finding 8 — Medium
30-second session polling /api/access-check — server-side watch time tracking
Finding 9 — Medium
87 console errors — CORS failures on d.dulo.gd (their own video CDN broken)
Finding 10 — Critical
Confirmed: anonymous users profiled and sold to affiliate network with zero consent

Clicking anything on dulo.cx does not change the URL bar. This is intentional — the site is a SPA using query-string routing with history.pushState() deliberately disabled, to minimize URL exposure and frustrate DMCA crawlers.

JS
Global click interceptor
All click events intercepted — event.preventDefault() on everything. No traditional page loads. The browser never navigates.
?=
Query-string routing: /?info=movie:TMDBID
Content state lives in the query string. During playback, even the query string disappears — player state is held in JS memory only. No URL = no content mapping for takedown bots.
WHY
Anti-crawl design — deliberate
No URL = no scraping of content structure. No referrer header leaks to embedded players. DMCA automation that relies on URL patterns gets nothing to work with.
; Confirmed URL patterns from HAR dulo.cx/ ; homepage — also player state (no URL during playback) dulo.cx/?info=movie:284 ; film info page (The Apartment) dulo.cx/?info=movie:1315772 ; another film dulo.cx/?info=tv:ID:S:E ; TV episode dulo.cx/?info=anime:tv:ID:1:E ; anime — separate namespace

Every page interaction fires a silent POST to ay267.com. This is not an ad — it is an affiliate conversion beacon. It runs even when no ad is displayed. The userId is persistent across the entire session and assigned without login, without consent, without a cookie banner.

; HAR — POST to affiliate tracker on every click/navigation POST https://ay267.com/track Content-Type: application/x-www-form-urlencoded rb=[obfuscated token] ; deliberately obfuscated — evades ad-fraud detection tools userId=a94f3b... ; persistent across session, set without any consent zoneid=11545831 ; dulo.cx's publisher affiliate slot event=pageview ref=dulo.cx ; localStorage entries proving tracker integration (Application tab): __BI_SESSION_11545831 = e7fed428-e0a2-4d1f-b389-988ba48b87ef __DL_SESSION_11545831 = 1786875127759 __PPU_SESSION_1_11545831_false = 1786874947759|4|1786875075622|14|6 syncDate = 1786874875306 syncId = 080394e216e0444ef1aa8f36b09a7813 syncOrigin = gidrator ; affiliate sub-network codename
What this means: ay267.com is a click-fraud/affiliate monetization network. zoneid=11545831 is dulo.cx's publisher slot — they earn per session tracked. The rb= obfuscated payload is specifically designed to avoid anti-fraud detection. syncOrigin=gidrator is the sub-network routing their traffic. Together: behavioral data from every visitor is sold without their knowledge.
GDPR violation confirmed: Setting a persistent userId and firing conversion events on anonymous users without any consent mechanism violates GDPR Article 6 (lawful basis) and Article 13 (transparency). Confirmed by IndexedDB check — zero auth token present, yet profiling is active from the very first page load.
; Hardcoded in JS bundle — plain text GET https://api.themoviedb.org/3/movie/284?api_key=0fd8ade0f772180c8f8d651787c35e14 GET https://api.themoviedb.org/3/search/movie?api_key=0fd8ade0f772180c8f8d651787c35e14&query=... GET https://api.themoviedb.org/3/trending/all/week?api_key=0fd8ade0f772180c8f8d651787c35e14 ; Also cached in localStorage (confirmed from Application tab): tmdb:/genre/movie/list?api_key=0fd8ade0f772180c8f8d651787c35e14 ; [full cached JSON]
Impact: a TMDB v3 key in a browser bundle is normal practice for client-side apps and gives read access to public film metadata only, so no private data is behind it. It is still their account's key, and it was reported to TMDB for revocation: if TMDB revokes it, metadata, posters and search stop working, which is a takedown lever that costs nothing. Nothing was requested with the key in the course of this investigation.

The JS bundle contains their Supabase project URL and the anon key in plain text, in supabase-G_Sidcym.js, readable by any visitor in DevTools, Sources. This is how Supabase is meant to work. The anon key is a publishable key: it is shipped to every browser on purpose, and what it can actually read or write is decided entirely by row level security policies on the server. So the finding here is not "a secret leaked", it is "the backend is now identified, and whether it is safe depends on configuration we cannot see from outside".

; From supabase-G_Sidcym.js (Sources tab) supabaseUrl: "https://wsudbodtjjfenprwsagd.supabase.co" supabaseKey: "eyJhbGc..." ; full JWT anon key — exposed in plain text ; Auth token location (standard Supabase): IndexedDB: sb-wsudbodtjjfenprwsagd-auth-token ; empty for anonymous users ; What the anon key enables (standard Supabase anon scope): GET /rest/v1/[table] ; read any table where Row Level Security allows public reads POST /auth/v1/signup ; create accounts programmatically POST /auth/v1/token ; authenticate via API
What this does and does not show. The key plus the project URL means anyone can address their REST endpoint. If row level security is configured correctly, those requests return nothing and there is no problem at all. If any table allows public reads, a common misconfiguration, then user records, subscription data and watch history would be readable without authentication. We did not test it: querying their tables would be unauthorised access, so no read was attempted and no data was retrieved. This finding is the open question, not a demonstrated exposure, and it is listed as informational for that reason.
; From index-rp6KJ5Wk.js (main bundle) — complete route map ; Public: / ; home / player /?info=movie:ID ; movie info ; Internal admin routes exposed in client-side JS: /admin ; admin dashboard /admin/users ; user management /admin/content ; content library management /admin/reports ; DMCA reports tracker /admin/sources ; video backend source management /admin/subscriptions ; revenue / subscription view
OPSEC failure: Admin routes in client-side code are a fundamental mistake. The routes don't grant access — but they confirm the admin panel exists at a known path, which makes targeted credential attacks significantly more feasible. Security through obscurity requires actual obscurity.

Their analytics runs on Rybbit (open-source, same tool used on SevinHub) hosted at stats.dulo.gd. The login page is publicly reachable with no IP restrictions — only the password protects their full traffic dashboard.

; Analytics instance — public login page https://stats.dulo.gd/login ; no IP restriction, reachable by anyone ; Inside the dashboard (standard Rybbit): - Real-time visitor count and active sessions - Per-page traffic breakdown - Referrer and traffic source breakdown - Geographic distribution of their entire user base - Device and browser fingerprint summary
Stack insight: Their entire operation is self-hosted open-source: Rybbit for analytics, Supabase for auth/database, Cloudflare Workers for video proxy, TMDB for metadata. The full operation likely costs under €50/month to run. The only real cost is domain registration — which they rotate when suspended. This explains dulo.gd becoming dulo.cx.

Cloudflare Turnstile is their anti-bot layer. A Turnstile sitekey is public by design: it has to be in the page for the widget to render, and it is useless without the secret key, which stays on their server and was never visible to us. So none of these five is a leaked credential. What is worth noting is that they ship five sitekeys instead of one, which is a rotation set: when one gets blocked they move to the next. All five are readable in plain text in PlayerV2Modal-DUGIKnTl.js.

; From PlayerV2Modal-DUGIKnTl.js — 5 Turnstile site keys hardcoded turnstileSiteKeys: [ "0x4AAAAAAAxxxxxxxxxxxxxxxxx1", "0x4AAAAAAAxxxxxxxxxxxxxxxxx2", "0x4AAAAAAAxxxxxxxxxxxxxxxxx3", "0x4AAAAAAAxxxxxxxxxxxxxxxxx4", "0x4AAAAAAAxxxxxxxxxxxxxxxxx5" ] ; Error strings baked into the player logic (proof of anti-bot integration): "turnstile_required" ; Turnstile challenge not yet completed "turnstile_invalid" ; challenge response rejected "forbidden_origin" ; request from unauthorized domain "provider_rate_limit" ; multiple video backends — rate limited "session_required" ; free-tier watch limit enforced
Why it still matters: not as a leak, but as reporting leverage. All 5 sitekeys can be handed to Cloudflare in one abuse report, where a rotation strategy that assumes keys are blocked one at a time has nothing left to rotate to. Whether Cloudflare acts on them is their decision, not something this report can claim.
; HAR — all video goes through Cloudflare Worker signing proxy GET https://vidapi-sabrina-proxy.vidsuper1.workers.dev/v/[signed token] ; Token = base64url(source_url + expiry_timestamp + HMAC_sig) ; URL expires within minutes — cannot be extracted or reshared ; From PlayerV2Modal-DUGIKnTl.js: localStorage.getItem("amri-source-worked") ; "amri" = internal codename for their video source routing system ; Tracks which sources worked per user locally, prioritizes them next session ; DASH streaming support (adaptive bitrate): return "dash" === t ? `${e.replace(/#.*$/, "")}#dash` : e ; Provider tier sorting (from ve() function): providers.sort((a, b) => a.beta - b.beta || a.alpha - b.alpha) ; beta=0=stable, alpha=1=experimental — multiple live providers simultaneously
; HAR — GET every ~30 seconds during playback GET https://dulo.cx/api/access-check Cookie: session=[token] X-Requested-With: XMLHttpRequest HTTP/1.1 200 OK {"status":"ok","tier":"free","remaining_watch":1800} ; Server tracks cumulative watch time — free tier = 30min then paywalled

Chrome console shows 87 errors and 30 warnings — almost all CORS failures from d.dulo.gd, their old-domain video CDN, being rejected by the browser when called from the new domain dulo.cx. A post-migration misconfiguration they haven't fixed.

; Console — CORS failure pattern Access to fetch at 'https://d.dulo.gd/stream/...' from origin 'https://dulo.cx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header. ; Root cause: migrated to dulo.cx but forgot to add it to CORS allow-list on the CDN ; Error count rose from 67 to 87 during 20-minute session — grows with browsing ; Real user impact: significant portion of their video library silently broken
; Browser storage audit — completely anonymous session: IndexedDB: EMPTY ; no Supabase auth — confirmed not logged in Session Storage: EMPTY ; no session data Cookies: session cookie only ; server-side free-tier watch counter ; ay267.com tracker entries — set immediately on first page load, no login required: localStorage.__BI_SESSION_11545831 = [persistent UUID — cross-session] localStorage.syncId = [persistent ID] ; Result: behavioral data sold to affiliate network before user sees a single frame ; No cookie banner. No privacy policy reference. No opt-out. Pure GDPR Article 6 violation.
TypeValueContext
Domaindulo.cxActive unauthorized streaming site
Domaindulo.gdFormer domain — still active as CDN origin (d.dulo.gd)
Trackeray267.comCovert click-fraud tracker — fires on every interaction without consent
Zone ID11545831dulo.cx's affiliate publisher slot at ay267.com
Storage__BI_SESSION_11545831Persistent UUID assigned to all visitors without consent
StoragesyncOrigin = gidratorAffiliate sub-network routing dulo.cx traffic
API Key0fd8ade0f772180c8f8d651787c35e14TMDB API key — hardcoded in JS, abused for commercial piracy
Backendwsudbodtjjfenprwsagd.supabase.coSupabase project URL — exposed in supabase-G_Sidcym.js
Anon KeyeyJhbGc... (JWT)Supabase publishable key, public by design, listed to identify the project not as a leak
Analyticsstats.dulo.gd/loginSelf-hosted Rybbit — login publicly accessible, no IP restriction
Proxyvidapi-sabrina-proxy.vidsuper1.workers.devCloudflare Worker video signing proxy
Storageamri-source-workedInternal codename for video source routing system
Endpointdulo.cx/api/access-checkSession validator — 30s polling, enforces free-tier limits
Admin Routes/admin /admin/users /admin/content /admin/sourcesFull admin route map exposed in JS bundle
Turnstile Sitekeys5x 0x4AAAAAAA... (in page)Public sitekeys, not secrets; the full rotation set, all reportable at once
CDN Failured.dulo.gd CORS (87 errors)Old-domain CDN not updated — significant video library broken

EUIPO — EU Intellectual Property Office

Reported dulo.cx for commercial unauthorized streaming. Evidence: domain history, video proxy infrastructure, TMDB API abuse, admin route structure, affiliate monetization proof. EUIPO coordinates with registrars and national IP authorities across EU member states. Contact: infringement@euipo.europa.eu — Online Infringement Reporting Portal.

APD / GBA — Belgian Data Protection Authority

Reported for GDPR violations under Article 6 (lawful basis) and Article 13 (transparency): persistent anonymous profiling via ay267.com, no consent mechanism, no cookie banner, behavioral data sold to affiliate network. APD can impose fines up to 4% global turnover. Contact: contact@apd-gba.be — complaint.apd-gba.be

TMDB — API Key Abuse

Reported key 0fd8ade0f772180c8f8d651787c35e14 for revocation. Removes all metadata, poster images, and search functionality. Contact: api@themoviedb.org — TMDB API Abuse.

Cloudflare — Workers Abuse + Turnstile Key Revocation

Reported vidsuper1.workers.dev for proxying pirated content. Reported all 5 Turnstile sitekeys together, so a rotation strategy that assumes one key at a time has nothing to fall back to if Cloudflare acts on them. Contact: abuse@cloudflare.com — cloudflare.com/abuse/form

FCCU Belgium — Federal Computer Crime Unit

Reported specifically for the unauthorized tracking of Belgian residents: ay267.com installs persistent identifiers on Belgian users' devices without consent from the first page load — this constitutes unauthorized computer-based collection of personal data under Belgian criminal law, separate from the GDPR civil case filed with APD/GBA. Contact: fccu@police.belgium.eu

EC3 / Europol — European Cybercrime Centre

Reported the organized cross-border piracy operation to ec3@europol.europa.eu. The operation's low-cost self-hosted architecture (Rybbit + Supabase + Cloudflare Workers), deliberate DMCA-evasion design, and domain rotation pattern indicate a professional repeat operator. EC3 scope: cross-border IP crime + unauthorized tracking of EU users at scale.

This investigation used only Chrome DevTools. No external tools, no exploitation, no unauthorized access. Every finding was data the site transmitted to the browser or embedded in its own code.

Phase 1 — HAR analysis: Exported the HTTP Archive from the Network tab. Mapped tracker behavior, API endpoints, and video delivery architecture from raw request/response pairs.

Phase 2 — JS bundle analysis: Sources tab → located named JS chunks. Read plain-text source directly in the browser. Extracted hardcoded keys, admin routes, internal codenames, Turnstile keys, and provider tier logic. No decompiler needed.

Phase 3 — Storage forensics: Application tab → confirmed anonymous profiling by verifying absence of auth tokens alongside presence of persistent tracker identifiers in localStorage.

Skill demonstrated: A site's JS bundle is its confession. Minified is compressed, not encrypted. Any site you can browse, you can fully reverse-engineer from the client side in under two hours with nothing but a browser. This is the first phase of every professional web security assessment.
Live Evidence — Screenshot Captured 2026-08-16

Headless browser screenshot of dulo.cx captured during investigation. Unauthorized streaming site serving copyrighted content while running covert click-fraud tracker, Supabase backend exposure, and zero-consent user profiling.

●●● dulo.cx — PIRACY + TRACKING SITE ⚠ GDPR VIOLATION
Screenshot: dulo.cx piracy streaming site

Evidence captured passively. Site has no content licensing, no cookie consent, and runs covert tracking on all visitors.

Live Infrastructure Status
Loading status…
Previous: Case 002 — ClickFix RAT Next: Case 004 — PigButcher Network All Cases
SevinOS Invisible Atlas