Is Core Wallet: Crypto Made Easy safe?

Medium risk

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.

Ava Labsv1.135.0Chrome Web Store
45Risk
Who publishes it

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.

Publisher
Ava Labs
Declared legal entity
Ava Labs, Inc.
Registered address
1177 Avenue of the Americas, suite 50992, New York, NY 10036, US
Registered contact
Ava Labs, Inc.

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.

sievecache.com
Also called by 1 other listing: MetaMask

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

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 extension did this

The service worker posts a persistent identifier to the PostHog feature-flag proxy.

Dynamic analysis observed the request repeating about every 30 seconds.

Captured request
POSThttps://proxy-api.avax.network/proxy/posthog/decide
Headers
Content-Type
application/x-www-form-urlencoded
Decoded fields in the feature-flag request
  • Persistent request identity
    077248ad-c61e-4ae5-bdb9-4f7b9e9f494d

    This lets repeated feature-flag checks be tied back to the same wallet installation or user.

  • PostHog project token
    phc_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.

The code that does this

Feature-flag polling and request construction in the shipped service worker

Readable version

Feature flag timer

sw/js/backgroundPage.js
constructor(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.js
async 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.js
async 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.js
async #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")})}
When this fires

Every 30 seconds

The feature-flag check repeats on a background interval while the service worker is active.

Where the identifier is sent
    • 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.

Updated 30 September 2026agoakfejjabomempkjlepdflaleeobhb