Security Warning: High Security Risk
Extenssr
ID: camiehngogdpflplmapknnjkeeofhfop
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- Extenssr DevelopersView Profile
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
'Extenssr - A browser extension for Geoguessr'
This is an extension for the browser based geography game Geoguessr. Latest change log: https://gitlab.com/nonreviad/extenssr/-/blob/main/Changelog.md This is a browser extension for the browser based map game Geoguessr. Current functionality: - show exact locations for completed Battle Royale rounds - filter effects on the map - bookmark locations as you find them on the map - cursed game modes Complete features list: https://gitlab.com/nonreviad/extenssr/-/blob/main/Readme.md
The extension completely replaces the global `window.WebSocket` constructor with a subclass that intercepts every outgoing `send()` call and every incoming `message` event, re-dispatching the full parsed payloads as DOM CustomEvents. This gives the extension visibility into all WebSocket traffic on geoguessr.com — including live game state, round data, and any authentication tokens transmitted over the socket — before any existing page code sees it.
class s extends WebSocket { constructor(s, E) { super(s, E); const t = this.send; this.send = (...s) => { t.apply(this, s); const E = JSON.parse(s[0]); document.dispatchEvent(new CustomEvent(e.WEBSOCKET_MESSAGE, { detail: { type: e.WEBSOCKET_MESSAGE, wsMessage: E } })) }, this.addEventListener("message", (s => { const E = JSON.parse(s.data); document.dispatchEvent(new CustomEvent(e.WEBSOCKET_MESSAGE, { detail: { type: e.WEBSOCKET_MESSAGE, wsMessage: E } })) })) }}window.WebSocket = sA MutationObserver watches the entire document for new script elements whose `src` begins with `https://maps.googleapis.com/`. When the Maps API script is detected, the extension hijacks its `onload` handler to immediately replace `google.maps.StreetViewPanorama` with a subclass before any page code runs. This is a supply-chain style hook: the extension inserts itself between the Maps SDK initialization and the host page, guaranteeing it controls the class before the game registers any panoramas.
i = function(t) { t.maps.StreetViewPanorama = class extends t.maps.StreetViewPanorama { constructor(t, n) { super(t, n), e.reinit(this), s.reinit(this) } } }, new MutationObserver(((t, e) => { const s = function(t) { for (const e of t) for (const t of e.addedNodes) { const e = t; if (e && e.src && e.src.startsWith("https://maps.googleapis.com/")) return e } return null }(t); s && function(t, e, s) { const n = t.onload; t.onload = i => { const o = window.google; a && t.disconnect(), s(o), n && n.call(t, i) } }(s, e, i) })) .observe(document.documentElement, { childList: !0, subtree: !0 })The extension hooks `document.createElement` to intercept every canvas element created on the page, then forces `preserveDrawingBuffer = true` on all WebGL contexts. Enabling `preserveDrawingBuffer` prevents the GPU from discarding frame data after compositing, allowing pixel readback (e.g., via `readPixels`) at any time. Combined with the full wrapping of ~20 WebGL API methods (shaderSource, useProgram, all uniform setters), this gives the extension persistent access to the rendered frame buffer and deep control over the WebGL pipeline.
getContext: e => function(...o) { const c = o[0], d = c && c.startsWith("webgl") && "preserveDrawingBuffer" in o[1]; d && (o[1].preserveDrawingBuffer = !0); const s = e.apply(this, o); if (d) { let e = "default", o = !1; const c = {}; s.oldShaderSource = s.shaderSource, s.oldGetUniformLocation = s.getUniformLocation, s .oldAttachShader = s.attachShader, s.oldUniform1fv = s.uniform1fv, s.oldUniform2fv = s .uniform2fv, s.oldUniform3fv = s.uniform3fv; // ... wraps: attachShader, getUniformLocation, shaderSource, // uniform1f/fv/i/iv, uniform2f/fv/i/iv, uniform3f/fv/i/iv, // uniform4f/fv/i/iv, uniformMatrix2/3/4fv, useProgramAfter monkey-patching the Google Maps StreetViewPanorama class (by intercepting the Maps API script load via MutationObserver), the extension attaches a `position_changed` listener that fires on every Street View movement and captures the user's exact lat/lng coordinates. All position data is broadcast as DOM events consumed by content.bundle.js, which stores them for route replay. While used for in-game features, this constitutes continuous geographic tracking of every map position the user visits.
reinit(e) { this.deinit(), e && (this.streetView = e, this.moveListener = e.addListener("position_changed", (() => { const e = this.streetView.getPosition(), s = { lat: e.lat(), lng: e.lng() }; document.dispatchEvent(new CustomEvent(t.MOVE_ON_MAP, { detail: { pos: s } })), this.bindBackToHomeButton() })))}Uses the same MutationObserver pattern as street_view_inject to intercept the Google Maps API load event and replace `google.maps.Map` with a subclass that captures the first Map instance. This gives the extension a persistent reference to the game's map object, used to draw polylines and inject saved-location markers — but also grants the ability to call any Map API method, read map bounds, center, zoom, or attached data layers at any time.
i = function(e) { e.maps.Map = class extends e.maps.Map { constructor(e, i) { super(e, i); const a = this.addListener("idle", (() => { null === t && (t = this, s.reinit(this), o.reinit(this), a.remove()) })) } } }, new MutationObserver(((e, t) => { const s = function(e) { for (const t of e) for (const e of t.addedNodes) { const t = e; if (t && t.src && t.src.startsWith("https://maps.googleapis.com/")) return t } return null }(e); s && function(e, t, s) { const o = e.onload; e.onload = i => { const a = window.google; a && t.disconnect(), s(a), o && o.call(e, i) } }(s, t, i) })) .observe(document.documentElement, { childList: !0, subtree: !0 })The extension wraps `document.createElement` itself on the document object, meaning every call site that creates any element passes through extension-controlled code. While the inner branch only activates for `canvas`, the outer wrapper intercepts all element creation at the document level — a broader hook than needed for legitimate shader injection, and a pattern that could be expanded to intercept other element types.
t(document, { createElement: e => function(...o) { const n = e.apply(this, o), c = o[0]; return c && "canvas" === c.toLowerCase() && t(n, { getContext: e => function(...o) {By severity
Versions scanned
Showing 1 of 45 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 2.6.3 | 6 |
Files with findings
4 distinct paths — top paths by unique finding count:
- canvas_inject.bundle.js2
- street_view_inject.bundle.js2
- maps_inject.bundle.js1
- websocket_inject.bundle.js1
URLs
View the external URLs this extension communicates with to understand its network activity and data interactions.
Gain full insight into all external connections.
Upgrade for full visibility.
Gain full insight into all external connections.
Upgrade for full visibility.
Code Diff
Compare extension code between any two versions.
No comparable text files found between these versions.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.