Is Core Wallet: Crypto Made Easy safe?
Core is medium risk. Core Wallet repeatedly POSTs to a PostHog feature-flag endpoint via proxy-api.avax.network. The body base64-decodes to a token and persistent distinct ID; this timer starts at feature-flag init, not the consent-checking analytics path.
Who publishes itAva Labs, Inc. - no other listings under this identity, 1 shared hostname
Ava Labs, Inc. - no other listings under this identity, 1 shared hostname
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 1 hostname
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
Feature flag polling sends persistent IDs to PostHog
Core Wallet repeatedly POSTs to a PostHog feature-flag endpoint via proxy-api.avax.network.
The body base64-decodes to a token and persistent distinct ID; this timer starts at feature-flag init, not the consent-checking analytics path.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
The wallet remains installed while its background feature-flag timer runs.
This does not require you to visit a specific website or press a specific button.
The service worker posts a persistent identifier to the PostHog feature-flag proxy.
Dynamic analysis observed the request repeating about every 30 seconds.
- Content-Type
- application/x-www-form-urlencoded
- Persistent request identity077248ad-c61e-4ae5-bdb9-4f7b9e9f494d
This lets repeated feature-flag checks be tied back to the same wallet installation or user.
- PostHog project tokenphc_rJkTcxMflyO69hd8gnLBDvWBMQqyL2joPDxy6lvKcTD
This tells the receiving service which PostHog project should process the feature-flag request.
- Group context{}
The request includes a group field even when no group values are provided.
Feature-flag polling and request construction in the shipped service worker
Feature flag timer
sw/js/backgroundPage.jsconstructor(e,t,r){this.analyticsService=e,this.lockService=t,this.storageService=r,this.#N=new(i()),this.#eR=v.D9,this.#eN=null,this.initFeatureFlags().catch(e=>{console.error(e)}),this.analyticsService.addListener(u._qu.ANALYTICS_STATE_UPDATED,()=>{this.#eN&&clearInterval(this.#eN),this.initFeatureFlags().catch(e=>{console.error(e)})})}ensureFlagEnabled(e){if(!this.featureFlags[e])throw Error(`Feature (${e}) is currently unavailable`)}async initFeatureFlags(){let e=await this.analyticsService.getIds(),t=async()=>{try{let{flags:t,flagPayloads:r}=await (0,T.B)("phc_rJkTcxMflyO69hd8gnLBDvWBMQqyL2joPDxy6lvKcTD",e?.userId??"","https://app.posthog.com");await this.updateFeatureFlags(this.#eD(t,r))}catch(e){console.error(e.message)}};this.#eN=setInterval(()=>{t()},(0,x.P)()?3e4:5e3),t()}PostHog decide request helper
sw/js/backgroundPage.jsasync function o(e,t,r,c="1.20.0",u="3"){if(!e)throw Error("Invalid token");let l=JSON.stringify({token:e,distinct_id:t||"core-extension",groups:{}}),x=s.from(l).toString("base64"),h=new URLSearchParams({ip:"0",_:Date.now().toString(),v:u,ver:c}),b=async()=>{let e=async e=>await (0,n.i)([`${e}/decide?${h}`,{method:"POST",body:"data="+encodeURIComponent(x),headers:{"Content-Type":"application/x-www-form-urlencoded"}}],i.Z);try{let t=await e("https://proxy-api.avax.network/proxy/posthog");if(!t.featureFlags)throw Error("Failed to fetch cached data.");return t}catch{if(!r)throw Error("Invalid Posthog URL");return await e(r)}},y=await b();return{flags:{...a.Yn,...y.featureFlags},flagPayloads:y.featureFlagPayloads??{}}}Identifier creation and unencrypted device ID storage
sw/js/backgroundPage.jsasync initIds(e){let t=await this.storageService.loadUnencrypted(a.br9),r=t?.deviceId,n={deviceId:r||crypto.randomUUID(),userId:crypto.randomUUID()};r||await this.storageService.saveUnencrypted(a.br9,{deviceId:n.deviceId}),await this.cacheAnalyticsIds(n),e&&await this.storageService.save(a.mPV,n),this.eventEmitter.emit(a._qu.ANALYTICS_STATE_UPDATED,n)}Analytics event path checks consent, but this is not the feature-flag path
sw/js/backgroundPage.jsasync #P(e,t){let{analyticsConsent:r}=await this.settingsService.getSettings();if(!this.featureFlagService.featureFlags[u.yyv.EVENTS]||r===u.tXx.Denied)return;let n=await this.analyticsService.getIds();if(!n)throw Error("Analytics State is not available.");let a=await this.analyticsService.getSessionId(),i=chrome.runtime.getManifest().version,s=this.getFeatureFlagsData(),{chainIdProps:o,encryptableProps:c}=t&&e.properties?this.#B(e.properties):{chainIdProps:{},encryptableProps:e.properties},l=t&&!!c&&Object.keys(c).length>0,x=c?await this.prepProperties(e.windowId,c,l):{},h={api_key:"phc_rJkTcxMflyO69hd8gnLBDvWBMQqyL2joPDxy6lvKcTD",event:e.name,properties:{...x,...o,...s,distinct_id:n.userId,$user_id:n.userId,$device_id:n.deviceId,$session_id:a,extension_Version:i,$host:chrome.runtime.id,$groups:{device:n.deviceId}},timestamp:Date.now().toString(),ip:""};return this.http.post("/capture/",h,{headers:{"Content-Type":"application/json"}}).then(()=>this.updateGroupPropertiesIfNeeded(n)).catch(e=>{throw console.error(e),Error("Analytics capture error")})}Every 30 seconds
The feature-flag check repeats on a background interval while the service worker is active.
- proxy-api.avax.network
Receives the feature-flag POST at /proxy/posthog/decide and forwards the request through Ava Labs' proxy infrastructure.
- app.posthog.com
Configured as the fallback PostHog endpoint if the proxy request cannot return feature flags.