~/mikey-strauss

Static-analysis disclosure · ru.oneme.app “MAX”

If You Wanted to Watch a Country

We pulled MAX apart and read the code: the surveillance machine you could build on top of it, and how little of it we had to make up.

Build 26.31.0 / vCode 6822· APK SHA-256 0b077115…9768b2· We downloaded and decompiled the real app ourselves · no third-party dumps
The short version

MAX (ru.oneme.app) is Russia’s state-mandated national messenger, built by VK and preinstalled by law. It was never meant to be just a chat app. One login is being wired to your messages, your whole contact book, your government ID, and your bank: your whole civic life in one place. And none of it is private. There is no end-to-end encryption on anything, not your texts, not your voice notes, not the videos you send, so the operator holds it all in the clear.

We decompiled the shipping build. That same server can do more than read. It can move your connection to one it chooses with the encryption switched off, flip any of 455 settings for a single account, pull a live location fix from your phone, report your device, IP and VPN status to an unlisted server, and replace the whole app on your phone, all aimed at one user. Every piece ships today. And since nothing is encrypted, in theory it could even put words in your mouth: a message injected so it reads as a contact’s, though we found no sign this is used.

So MAX isn’t the spy. It’s the infrastructure a spy would plug into. One app ties a single, named citizen, physical and digital life alike (identity, location, money, messages), to the rest of the state’s databases, where all of it can be cross-referenced against one person. Every wire is real and present in the shipping build, and it is already the operator’s to hand over by law. The only thing we invented is the “Service” that pulls it together into a command-and-control operation.

MAX, our subjectthe real statethe imagined Servicethe targeted citizen
CapabilityIn the codeNeeds the ServiceProofVerdict
Read your messages (plaintext)●○§7Confirmed
Reroute your connection, turn off encryption●○§1Confirmed
Rewrite one account’s rules (455 flags)●○§3Confirmed
Locate you on demand●○§5Confirmed
Report device, IP, VPN to an unlisted server●○§4Confirmed
Swap the app on your phone (targeted)●○§2Confirmed
Inject a message as anyone◑●§7Narrowed
Cross-reference you across state databases○●noneImagined
The whole case in one grid: six proven levers, one narrowed, one purely imagined. ● in the code  ◑ architectural consequence  ○ not in the code.

If you wanted to watch a whole country, you wouldn’t break in. Breaking in is work. You find a flaw in every phone, exploit it, and cling on as the patches land, and that window keeps closing faster now that AI is putting the defenders ahead. The smarter move is to never break in at all: own the supply chain. Build a super-app that holds a whole life (messages, money, ID, dealings with the state), ship it through the official store as a legitimate app, and make everyone install it. Russia did exactly that. Since 1 September 2025, federal law puts its national messenger, MAX, on every new phone sold in the country, and the state is routing essential services through it. We pulled it apart and read the code.

And they did: it worked
~140M
registered accounts by Oct 2026 (VK), up from ~1M in mid-2025
~77M
people reached in a single day, Mar 2026
Sep 2025
mandatory preinstall on new phones & tablets (Law 156-FZ)
blocked
WhatsApp calls restricted, then WhatsApp blocked and Telegram throttled, 2025–26

You don’t have to force an install when the alternatives disappear. Adoption figures are VK’s own and count registered accounts, not unique people; independent outlets flag likely inflation. Competitor restrictions are Roskomnadzor’s, reported by The Moscow Times and Russian wires.

The hard way: an exploit operation

break in, one target at a time
  1. Find a flaw in the phone
  2. Build and deliver an exploit
  3. Escalate & gain persistence
  4. Exfiltrate, then keep re-winning as patches land
costly · fragile · one target · window closing
vs.

The pivot: own the super-app

no break-in required
  1. Mandate the app onto every phone
  2. Capabilities already granted; it’s a legit app
  3. Push new code through the official store, any time
  4. Aim it at anyone, at population scale
cheap · durable · everyone · nothing to “catch”
Why a mandated super-app beats an exploit: there’s no bug to find, the access ships already granted, and it scales to a whole country.

Read this first. The whole usage story (the Service, pointing MAX at a person, deciding to pull the levers) is imaginary and speculative. We built it by piecing together the infrastructure we observed and the features and bugs sitting in MAX’s own code, to show what such an app could be worth to a government that chose to use it. Everything on the MAX client side, Acts I and II, is pinned to a line in the build we pulled and decompiled: each claim carries its citation, and the Appendix walks the evidence. We leave it to you to weigh exactly which claims are proven, and how well. Where a detail comes from public reporting rather than our own read of the code, we mark it.

And we are not the only ones who looked. In a nine-week dynamic analysis (Mar–May 2026), the security lab InterSecLab captured MAX’s live traffic on the wire and independently confirmed the core of what we found in the code: no end-to-end encryption, with message content captured in plaintext as the app handed it off; the entire address book uploaded in cleartext at registration; and capabilities toggled per-account by server-pushed flags, with nothing shown in the interface. Where we read the code, they watched it run, and the two accounts converge. interseclab.org/research/max
2023 VK Messenger required preinstall 1 Sep 2025 MAX · federal preinstall every new phone & tablet, by law ongoing services migrate in Gosuslugi · 2FA · e-signature
Mandated national infrastructure, established as fact before any argument about what it could do. Dates from public reporting; the hinge is the 1 September 2025 federal preinstall.
Act I · the foundation · all of this is in the code

Not a Backdoor. The Architecture.

It isn’t hidden, and it isn’t a hack. It’s the architecture: six everyday features that, stacked into one app, hand a single operator a whole life. Each one is confirmed in the build we pulled.

MAXru.oneme.app Your identityDigital ID · ESIA Your contactswhole address book Government servicesGosuslugi mini-apps Your messagesread in the clear Your moneyin-chat pay, banking The updaterown server, no store
Six assets, one operator, one app, with every wire confirmed in the decompiled client.

Start with what the one app already holds. Your messages sit on the server in the clear. There’s no end-to-end encryption anywhere, and the web client at web.max.ru proves it: a browser that never held a key still shows your history (§7). Your whole contact book, including people who never installed MAX, uploads at login. And the moment you link Digital ID, your real name and state identity bind to the same account as your chats, through ESIA / Gosuslugi (Russia’s national login for state services) and a tap-to-verify NFC service (§6).

The rest of a life follows. Your money runs through in-chat payments and bank mini-apps, tagged to you (SBP, VTB, Alfa, per public reporting). Your dealings with the state go through the same app: Gosuslugi login, the 2FA codes that replaced SMS, the e-signature. And the updater can replace MAX itself with a build of the operator’s choosing, from its own server, outside any store (§2). Six ordinary features. Stacked in one app, behind one operator, they are a filing cabinet of a whole life, before a single “surveillance feature” is switched on.

What MAX is actually made of

MAX wasn’t written from scratch. Under the new name it’s TamTam, VK and Odnoklassniki’s old messenger, reskinned. Our own copy of the app carries roughly 200 classes under ru.ok.tamtam.* (the whole messaging core: chats, contacts, folders, uploads) and still sends messages in TamTam’s own nano.Protos format, over a proprietary binary protocol to api2.oneme.ru. That matters because the parts this whole story turns on, namely no end-to-end encryption, the cloud-mailbox model, and the server opcodes that carry the RECONNECT redirect, aren’t new experiments bolted on for a national rollout. They are a mature, years-old codebase, lightly repainted and handed a country.

From our decompile: the ru/ok/tamtam/** class tree, the ru.ok.tamtam.nano.Protos$* wire types, the plaintext body field Tasks$MsgEdit.text, and the opcode-plus-map session protocol (the Appendix walks the chain). Reported only, not in our build: a separate Russian-channel build is said to swap standard TLS for Russian GOST cryptography (host api-gost.oneme.ru); the build we pulled ships GOST switched off (Gost:false, no such host), so we make no GOST claim here.

Act II · the expansion · the switches are real; the hand on them is the story

Now the Service Wants Hands

A filing cabinet is nice, but our Service wants reach. The uncomfortable part is that it doesn’t need to break in, smuggle a payload, or even push an update. Every way of reaching further is already in the app: switches the operator throws from its own servers, pointed at a single account when that is all it wants. We found the switches in the code. What a security service would do with them is the only part we’re imagining.

The operator’s serverdecides when tothrow each switch your phone ↓ Find you on demandserver asks for a GPS fix, no fresh prompt See you’re hiding your trafficdetects the VPN, reports vpn=1, can nag Move your connection, encryption offRECONNECT: any host, no allow-list Profile you silentlybeacons IP, device, VPN to trace-flow.ru Change the rules for you alone455 remote flags, no validation Push a different app to one phoneself-update, own server, no signature check Prove who’s behind the SIMMobile-ID bridge relays the raw answer
Seven doors, each a real mechanism in the build. The dashed arrows (the server choosing to throw a switch, for you specifically) are the imagined part.

Walk the seven. Every one is throwable from the server, aimed at one account if that’s all it wants. Several aren’t even separate systems: the reroute (§1), the per-account config flip (§3), an on-demand re-upload of your whole address book, and the location request (§5) are all opcodes on the one command channel the mailbox already runs: the server reaches each by sending your phone a single numbered message on the same wire. On command, the app hands over a GPS fix (gated on a location permission granted once, not fresh consent; §5), and it flags you the moment you switch on a VPN: detect-and-report, not a block (ledger). One message, RECONNECT, can move your whole connection to any server it names with the encryption switched off, with no allow-list, and it survives logout (§1). A dormant reporter can beacon (silently phone home) your IP, carrier, VPN state and device to an unlisted domain whose address is scrambled in the code to hide it (§4).

The last three reach further still. A config message flips any of 455 settings for your account alone (§3). Every app updates through a store, which vets the download for you; MAX keeps a second path of its own. The self-updater can replace MAX with a build of the operator’s choosing, from its own server; the only backstops left are the system “install this app?” prompt and MAX’s own signing key (§2). And a whitelisted mini-app can run a carrier-grade SIM check and read the raw answer, with no consent prompt (§6). Seven ordinary features, and the only imagined part is a hand deciding to throw one at you.

Why “for one account” is the whole game

A switch flipped for everyone is a boring product setting. The same switch flipped for one named person, when every request the app sends already identifies you, becomes a dial pointed at a single citizen. That shift, from everyone to you, is the whole difference between a messaging app and a weapon. (The app makes it possible; whether a server actually targets you that way is what we can’t see from the outside, and it is where the Service steps in.) It also dissolves the split in the public reporting: one team watched a clean install and called MAX boring, another found it probing and reporting, the same app in two server states. An independent study (InterSecLab) observed exactly that, the behaviour varying from one account to the next.

Interlude · who the operator is · public reporting, not our code

One Company Builds the App, and Owns the Store It Skips

We’ve been saying “the operator” like it’s a neutral box. It isn’t. It’s VK, Russia’s largest internet company, and who controls VK is the whole point. VK builds and runs MAX; it also runs RuStore, the national app store that Act II’s self-updater steps around, and the same ministry ordered both onto every phone. But VK is not independent. Since late 2021 its voting control has sat with a holding company, MF Technologies, owned by Kremlin-adjacent state money, and its chief executive is Vladimir Kiriyenko, the son of Sergei Kiriyenko, the official who runs the Kremlin’s domestic politics. The chart below names each link. The short of it: the state that forces MAX onto your phone also owns the company that operates it.

None of this is in the code. It’s public reporting, and we flag it as such. One detail is too good to leave out: in July 2026, days after the EU sanctioned VK and MAX’s operator for building the messenger as a surveillance tool, VK sold RuStore, not to an outside buyer but to the CEO of the firm it had hired to build the store (Dmitry Pankrushev of Many Applications). A sale to a close associate, a tidy way to put daylight between the store and a sanctioned parent.

Kremlin-adjacent state capital · owners in 2021 Sogaz state insurer, tied to Putin ally Kovalchuk Gazprombank state-linked bank, Gazprom group Rostec state arms conglomerate (Chemezov) own MF Technologies holding company ~57% of VK's votes (2021) holds voting control VK Russia's largest internet company WHO CONTROLS VK CEO Vladimir Kiriyenko, son of Sergei Kiriyenko, who runs the Kremlin's domestic politics. builds & runs MAX ru.oneme.app, the national messenger RuStore the national app store Ministry of Digital Development “Mintsifry” ordered both preinstalled mandates
The chain that runs MAX. State-linked owners control a holding (MF Technologies) that holds VK’s voting shares; VK, led by Vladimir Kiriyenko, built both MAX and RuStore (it sold RuStore in July 2026, though product ties remain); and the Ministry of Digital Development ordered both preinstalled. Public reporting, not our code; ownership figures are from 2021 and may have shifted.

The app and the store are one company

The “out-of-store” updater and the official store both lead back to VK. MAX is built by VK’s «Коммуникационная платформа» (“Communication Platform”); RuStore, Russia’s mandated app store, is VK’s «Много приложений». The escape hatch and the front door belong to the same firm.

corporate entities: public reporting

Shared wiring, one owner

The two halves don’t just share an owner; they share plumbing. RuStore’s push notifications run through a VK service literally called VKPNS (“VK Push”), and VK’s own apps now let you sign in with MAX. The app, the store, the login, and the company behind them are one system.

ownership (2021–22) & infra: public reporting

Sources (public reporting, not our code): Meduza, The Bell, IntelliNews, The Moscow Times, TASS, and the Council of the EU sanctions listing, 2021–2026. Ownership percentages are from 2021–22 reporting and may have shifted since; the July 2026 EU sanctions and the RuStore sale were reported at the time.

Act III · behind the operator · the levers are real; the hand is imagined

So Who’s Behind the Operator?

We’ve seen who owns the operator and what its servers can do. The last step is the one we can’t photograph: a command-and-control console wired to drive those real levers at a single, named person. Every lever it pulls ships in the code. The console, the hand on those levers, is the part we imagine. One hard fact holds it up: Russian law already forces an operator to hand its data to the state on demand (SORM for the live tap, Yarovaya for the stored archive). The compulsion is real; only the console is drawn.

Make it one person. Say she joins an opposition channel on MAX one morning, having done nothing the law forbids. The operator already holds her messages in the clear, voice notes included (§7), and her real name and verified identity, because her Digital ID is bound to the account (§6). Ask the phone where she is and it answers (§5). The instant she opens a VPN to hide, the app notes it (§1). Want more reach? Flip a handful of her 455 account settings (§3), or send her a fresh build of MAX straight from the server, outside any store (§2). None of that is hypothetical code; it all sits in the build we pulled. The only invented part is someone deciding she is worth the trouble.

By law, VK must hand your data to the state: SORM = the live wiretap · Yarovaya = years of stored messages the operator proven in code · 455 per-account flags Mailboxread & forge messages Reroutemove connection · drop TLS Updatertargeted swap → jump env ID + telemetrydevice · VPN · location the state real, by law & public record Gov IDESIA · Gosuslugi Comms archiveSORM · Yarovaya TelecomMobile-ID · location Police, courts, bankswarrants · SBP THE LAW ① the legal avenue (real) MAX collects it all uploads to the operator ② reroute · §1 diverts MAX’s whole output (not by law) drives the levers ② the operational console imagined a server driving VK’s levers at one user › GPS tracking › impersonation › watch VPN › reroute you › app-swap → jump env › read messages Messagesplaintext Contactswhole book DeviceID · VPN state IdentityMobile-ID Locationon grant Moneyin-chat pay One citizen fully identified · and in the crosshairs
Everything a citizen does flows up into MAX. From there it goes two ways: ① by law, to the operator (VK) and the state, or ② rerouted by the §1 lever to an operational console that drives MAX’s own levers back onto the one user. Every lever and the law are real; the only invented part is a console choosing to receive the reroute.

None of the links are exotic: the operator already holds your messages in the clear and, through Digital ID, can know who you are; the console’s switches are Act II’s seven doors; the wire up to the ID database is just what “one messenger, one identity, one company, one country’s law” already means. We invented only the room that draws it together, and the law that would hand it the keys isn’t invented at all.

The line we hold

What’s Real, What’s Imagined, What We Won’t Say

This story only works if the fact half is trustworthy, so here is where the ground ends and the thought experiment begins.

Real, and this is the point

Every capability in Acts I and II is pinned to a line in the build we pulled and hashed. The foundation and the seven doors are facts about MAX 26.31.0, not predictions. (Where payment rails, bank names, or specific government services are named, those come from public reporting and are marked as such.)

Imagined, built from the real

The Service, the console, and the server-side stack are a thought experiment. We are not claiming MAX does this. We’re showing it would need no new client code, only an operational server to receive the reroute and the decision to use what ships today, inside a legal system that can already compel the operator.

What we deliberately won’t say

We did no live interception, so we don’t claim the mailbox runs plaintext on the wire today, only that the code accepts a tls:false redirect. We can’t see the server’s targeting logic. We never pulled the Google Play build. “Refuted” means absent in this build, not impossible forever.

The rumors that don’t survive the code

No always-on microphone, no server-triggered stealth call recording, no silent upload of your installed-app list, no hidden screenshot-and-send, no neural keyword listener (that engine existed in older builds and was pulled). Ruling these out is what makes the rest credible, and honestly, a Service built on MAX wouldn’t need any of them. An independent nine-week dynamic study of the earlier 26.12.0 build (InterSecLab) reached the same conservative conclusions on the big rumors: installed-app upload present but inactive, no silent call recording, contacts not hashed. Where the builds differ, we say so: InterSecLab observed a VPN send-block and an on-device call-audio detector in 26.12.0 that we find unarmed or removed by 26.31.0, a version change, not a disagreement.

Appendix · proof, claim by claim

The Proof

The story spends no time on smali class names; this is where they live. Each confirmed capability below traces to a specific chain in the decompiled code, drawn as a diagram and walked in prose, and closes with the raw citation into the decompiled client itself. A claim earns a place only if a specific file:line in the app backs it.

  1. §1 Move the connection: RECONNECT
  2. §2 Replace the code: self-update
  3. §3 Rewrite the rules: remote config
  4. §4 Watch without telling: trace-flow.ru
  5. §5 Ask where you are: on demand
  6. §6 Bridge into government identity
  7. §7 No E2E: held in the clear
  8. §8 Live calls: relayed
§1

Move the connection: RECONNECT (opcode 3)

MAX’s main connection, the one carrying your login, messages and contacts, can be redirected by its own server to any address, with encryption switched off, without asking you. There’s no fallback address and no allow-list, and the change survives logging out.

ServerRECONNECT · opcode 3 z4f parserredirectHost, tlstls defaults true k1k.onReconnectguard: host non-emptyno allow-list is9 mailbox confighost · port · useTls is9.b() restores host, port and TLS across logout
The only guard before the client rewrites its own connection target and TLS flag is a non-empty host string.

The mailbox protocol has an opcode named RECONNECT (opcode 3). When one arrives, the handler runs a single check (is the host field empty?) and then overwrites its own connection target:

# k1k.smali onReconnect  (payload parsed by z4f.smali)
onReconnect(msg):
    if msg.redirectHost == "": return   # the ONLY check - no allow-list
    mailbox.host   = msg.redirectHost
    mailbox.port   = msg.port
    mailbox.useTls = msg.tls             # server may send false → TLS off

# is9.b() saves host/port/useTls, clears state, then writes them back
#   → the redirect outlives logout

So: the server can move your whole connection to any host and turn encryption off, and it sticks across logout. We don’t claim the live mailbox speaks plaintext today, only that the client accepts and keeps a tls:false redirect to an unrestricted host. Read as charitably as possible, the redirect itself is ordinary plumbing: every messenger lets its server steer clients between gateways for load-balancing and failover. But a real failover names a fixed set of its own hosts and never switches the encryption off. This one does neither, and the setting outlives logout. Even at its most innocent, those three properties are the part no routine feature needs. And the redirect doesn’t stand alone: RECONNECT is one opcode on the same server command channel that also carries the per-account config flip (§3), an on-demand re-upload of your address book, and the location request (§5). Read it not as a lone feature but as the most dangerous entry on a bus of commands the operator can send a single phone. And RECONNECT isn’t even the only way in: a second, quieter lever lets the server move the client’s API connection through a hidden DNS–TXT record (appendix), with the same no-allow-list blind trust (milder, since it can relocate the connection but can’t strip encryption or survive a restart), yet the same defect a second time.

ru.oneme.app 26.31.0 (decompiled) · §1
§2

Replace the code: self-update, no app-side signature check

MAX can replace itself with any build the operator signs, from its own server, and MAX itself never checks that what arrived is genuinely its own code. (Android still enforces the signing key, so a build signed with a different key is refused; what’s missing is any app-side integrity check of MAX’s own.)

Server (PMS)release-url / -version n41.smalifills %vendor%/%abi% download.max.ru/android/release/%vendor%/%abi%/MAX.apk PackageInstallersystem dialog No integrity check on this pathMessageDigest · checkSignature · CertificatePinnersearched kuf/n37/w17/adg/vu6, none found
Everything above the dim box is real code on the install path; everything inside it is a check that doesn’t exist.

MAX’s own updater builds its download URL from a server-controlled template and installs whatever comes back, with no integrity check of its own on the way:

url = "https://download.max.ru/android/release/%vendor%/%abi%/MAX.apk"
# server also sets the version: release-url, release-version (remote config)

download(url) then PackageInstaller.install(apk)   # system "install?" dialog

# install path (kuf, n37, w17, adg, vu6) searched for:
#   MessageDigest · SHA-256 · GET_SIGNATURES · checkSignature · CertificatePinner
#   → none found

So: the only thing between a swapped APK and your phone is Android refusing a package signed with a different key. The store-signed forced-update path (Google Play, RuStore) is separate and keeps that protection; it’s this self-hosted path that skips it. (Ironically, MAX fingerprints itself at login: an anti-tamper check inside the oddly-named libqrcode.so hashes the app’s own signature and native libraries for the server, so a modified client can be spotted (appendix), yet no such check is applied to what its own updater installs.)

ru.oneme.app 26.31.0 (decompiled) · §2
§3

Rewrite the rules per account: PMS remote config

What the app does, and does to you specifically, can change the moment the operator chooses, with nothing on your phone standing in the way.

ServerCONFIG · opcode 0x16 Request identitydeviceId · uidGAID · locale rides every request tsd.smali:20176 pxg.smali:1689stores any property, no gate 455 client flagsapplied immediately
Identity travels in; config flows out, with no validation step between the two.

The remote-config channel (opcode 0x16, NOTIF_CONFIG) applies whatever the server sends, key by key, with no validation:

onConfig(payload):                 # opcode 0x16 → pxg.smali:1689
    for key, value in payload:
        store[key] = value         # no validation, no allow-list (455 flags)

# every request already carries: deviceId · uid · GAID · locale
#   → the server CAN return a different map to one chosen phone

So: per-account targeting is possible from the client’s side: a feature can be switched on for one phone. What we can’t see is the server’s targeting logic; that isn’t in anything we pulled.

ru.oneme.app 26.31.0 (decompiled) · §3
§4

Watch without telling: the trace-flow.ru reporter

The app can fingerprint your connection and device and send it to a destination you’re never told about, and it can start doing this with no new version installed.

PMS flagdps = true AccountInitializerbuilds pipelinehardcoded key :136 j8l report builderip · vpn · deviceIduid · hostsgzip JSON nof.smali:179XOR-decodes domain POSTtrace-flow.rucert: O=VK LLC manifest: DpsInitProvider enabled=“false”, Java runs it anyway
Disabled in the manifest; built and sent in Java whenever one remote-config flag says to.

A reporter class ships disabled in the manifest, but Java builds and runs it the moment a remote flag flips:

# manifest: ru.trace_flow.dps.DpsInitProvider  android:enabled="false"
if config["dps"] == true:                 # AccountInitializer.smali:104
    report = { ip, carrier, isVpn, deviceId, uid, reachableHosts, appVersion, ts }
    host = decodeXor(...)                     # nof.smali:179 → https://trace-flow.ru
    POST host + "/api/v1/report"   (gzip json)   # key hardcoded in the APK

So: the destination is XOR-hidden in the binary and never surfaced to the user, and two config keys (selfIpDetectionDomains, reachabilityHosts) let the server swap the host list without an update. And the destination’s certificate names VK: the TLS certificate trace-flow.ru presented in 2026 was issued to “VK LLC”, an organization-validated certificate, so the issuing authority checked that legal identity, which anyone can confirm in public certificate-transparency logs. (An OV certificate attests the named owner, not that VK runs every server behind the domain.) An independent nine-week study (InterSecLab) separately observed the reporter contacting home 19 times in 26 days.

ru.oneme.app 26.31.0 (decompiled) · §4
§5

Ask exactly where you are, on demand

The server can ask your phone for a GPS fix, live or one-shot, any moment it chooses, with no new consent screen at the time of the ask.

ServerNOTIF_LOCATION_REQUEST onNotifLocationRequest location permissionalready granted?no fresh consent asked yes → GPS fixlive or one-shot → reply
The gate is a permission granted at some point in the past, not consent at the moment of the ask.

An inbound server message asks for a fix; the only gate is a permission that was granted at some point in the past:

onNotifLocationRequest():            # NOTIF_LOCATION_REQUEST (server opcode)
    if locationPermissionAlreadyGranted:
        reply(getGpsFix())           # live or one-shot
    # no fresh consent shown at the moment of the ask

So: this is separate from the “share live location” button you press yourself. We don’t claim it bypasses the Android permission, only that once that’s granted, the operator can pull a fix on its own schedule.

ru.oneme.app 26.31.0 (decompiled) · §5
§6

Bridge into government identity: the Mobile-ID handler

A web page running inside MAX can be allowed to make your phone perform a carrier-grade identity lookup and read the full, raw result, the same trick used for silent SIM authentication, with nothing on screen asking if that’s okay.

Server allow-listwebapp-pr containsthis mini-app botId pqk.smali:608injectsPrivateWebViewHandler Mini-app pageWebAppVerifyMobileId{requestId, url} rnk: cellular-only HTTP GET evaluateJavascript() ← raw status,headers, base64 body, no consent prompt
Privilege is 100% server-assigned; the APK ships with an empty allow-list by default.

A mini-app only gets the privileged bridge if the server puts its bot-id on an allow-list that ships empty. Once it does, the page can run a carrier identity check and read the raw answer:

if config["webapp-pr"].contains(botId):    # pqk.smali:608 - empty by default
    attach(PrivateWebViewHandler)           # exposes the private bridge

WebAppVerifyMobileId({requestId, url}):
    resp = rnk.get(url)       # cellular-only (fails on Wi-Fi) = silent SIM auth
    page.eval(resp.status, resp.headers, base64(resp.body))   # no consent prompt

So: the cleartext allow-list for this bridge is carrier and government identity gateways: mobileid.megafon.ru, idgw.mobileid.mts.ru, nuc-cdp.digital.gov.ru, and more. The mini-app JS that drives it arrives from the server at runtime; we didn’t capture it.

ru.oneme.app 26.31.0 (decompiled) · §6
§7

No E2E, anywhere: text, voice and video held in the clear

Every message, voice note and video you send sits somewhere the operator can read, store, search and hand over; none of it is encrypted beyond the operator’s own reach.

ClientMsgEdit.text: String Server mailboxstores plaintext web.max.rurenders identical inbox Transcription pipelineopcode 0xca → 0x125
A browser can’t read a message it never held a key for; the server can only transcribe audio it already decoded.

There’s no secret-chat or Olm/Signal protocol anywhere in the tree, and the message body on the wire (MsgEdit.text) is a plain String, not a ciphertext blob. The clean proof needs no protobuf:

MAX ships a web client (web.max.ru) that logs into the same account, and a browser that just authenticated never held an end-to-end key, so for it to show your history the server has to hold the plaintext. Voice and video ride the same mailbox: the transcribe button (opcode 0xca) only works because the server already holds the raw media, and the transcription setting defaults on (though each note is transcribed only when you tap, not automatically).

The same gap cuts both ways. Because nothing cryptographically binds a message to its sender, the client has only the server’s word for who said what. A server that can read your inbox can therefore also write to it: inject a message that arrives attributed to any contact, rendered as genuine, with nothing on your phone able to tell the difference. This is not a “send-as” feature we found; it is the unavoidable consequence of no end-to-end encryption plus a server that relays every message. (We did no live interception; we claim the architecture permits it, not that it is happening.)

And the server isn’t a passive store. Every message you send carries a flag (detectShare, on by default) telling the server to inspect it for links and shared content, and the client does no link-parsing of its own, so it ships your plaintext plus an explicit “inspect this” instruction and lets the server find the links. (Signal does the opposite: it builds link previews on your device, so its server never sees the URL.) We can show the request to inspect and the missing client-side handling; what the server does with it downstream we can’t see from the binary.

ru.oneme.app 26.31.0 (decompiled) · §7
§8

Live calls: relayed, not provably intercepted

A group or relayed call is, to the operator, closer to a conference call it’s already routing, and two shipped features could turn that audio into text or render your face on its servers. We can’t prove either runs on any particular call.

Caller SFU / call-media serverrelayed, not peer-to-peerno E2E: SRTP ends here Callee request-asrlive captions (server-side) animojiBackendRenderserver-set → server face
Both branches are real, server-negotiated features; neither proves a specific call was read.

For a group or relayed call the media runs through the operator’s server, not a direct phone-to-phone link. The call is encrypted with DTLS-SRTP, but MAX never turns on WebRTC’s end-to-end option (the SFrame/FrameEncryptor API ships yet is never wired), so on a relayed leg the encryption terminates at the server, which holds the keys and can decode the audio and video. (A one-to-one call may stay peer-to-peer.) Two shipped features could lean on that:

request-asr {start:true}  →  AsrOnlineChunk(participantId, text)   # live captions, server-side
animojiBackendRender : set by the call's server config            # face model runs server-side

# enableAsrOnline has ZERO callers in MAX's own code - it fires only
#   from the bundled VK/OK call SDK (no user toggle). BUT an on-device
#   engine (libEnhancementLibShared.so) can do the SAME job locally - 
#   we did NOT prove which path a real call takes.

So: MAX group calls relay through the operator’s servers, and because no end-to-end layer is wired, those servers terminate the encryption and can read the media. Which calls take the relay path rather than staying peer-to-peer, and whether server-side captions or animoji run on any given one, we could not settle from the binary, and no live call was captured this pass. The operator can read a relayed call; we have not proven it does on a specific one.

ru.oneme.app 26.31.0 (decompiled) · §8
Appendix · the rest of the ledger

Every Other Claim, in Brief

The eight proofs above are the headline capabilities. The remaining claims cleared the same bar: a row exists only if a specific line backs it. Confirmed safe to publish as fact; Narrowed there’s a true core, but the popular version exaggerates it; Refuted not true in this build.

ClaimWhat the code showsCiteVerdict
Second reroute lever (hidden DNS record)Besides RECONNECT, the client will take a hidden Google-DNS TXT record and make whatever address it names its API server, with no allow-list on where that points. Weaker than RECONNECT: API host only, can’t switch encryption off, forgotten on restart, and only while the app is still on its built-in default address. The server flag it was reported to need is declared in the code but never read. Lead: zarazaex69/m, re-derived by us.decompiled client · §1Confirmed
Login-time self-integrity checkAt each login the app fingerprints its own signing certificate and native libraries and sends the result with the login, so the server can detect a modified or repackaged client. An anti-tamper mechanism, not surveillance; the accept-or-reject decision sits on the server, which we can’t see. Lead: owenewans, Habr (item 16), re-derived by us.decompiled clientConfirmed
Every message flagged for server-side inspectionEach message you send carries a detectShare flag (on by default) telling the server to scan it for links and shared content; the client does no link-parsing itself, so it sends plaintext plus the inspect instruction, the opposite of on-device preview. We show the request-to-inspect, not what the server does with it. Lead: InterSecLab, re-derived by us.decompiled client · §7Confirmed
Whole contact book uploadedAddress book incl. non-users uploaded at login; server can re-trigger a sync. Not a covert always-on loop; the UI admits it.decompiled clientConfirmed
Public IP echoed homeQueries five “what’s my IP” services on open and uploads the answer on the telemetry pipe.decompiled client · §4Confirmed
Google Advertising ID at loginLogin fetches and sends your GAID unless Limit Ad Tracking is on or the id is empty.decompiled clientConfirmed
deviceId = ANDROID_IDEvery login round-trip carries a user-agent string and the device’s ANDROID_ID.decompiled clientConfirmed
Root / Magisk fingerprintingDetects root/Magisk/emulator and uploads the flag with crash and ad telemetry; does not block login.decompiled clientConfirmed
VPN detection & reportingDetects a VPN transport, reports vpn=1, can nag the UI, but does not hard-lock chats.decompiled client · §4Narrowed
Transcription on by defaultServer-side transcription of voice/video notes: the setting ships default-enabled, but each note is transcribed on a user tap, not automatically (needs the server to hold the raw media).decompiled client · §7Confirmed
Daily permission censusBackground worker reports the live state of every sensitive permission, whether in use or idle.decompiled clientConfirmed
Immediate permission-flip loggingToggling a permission in Android settings is logged the moment it changes.decompiled clientConfirmed
Search queries loggedWhat you type into in-app search rides the telemetry pipe, not just the result you tap.decompiled clientConfirmed
Contact-vs-stranger countersServer-side presence counters already distinguish whether a sender is in your contacts.decompiled clientConfirmed
Battery / CPU / thermal censusDevice-performance telemetry collected alongside the rest of analytics.decompiled clientConfirmed
Digital-ID NFC serviceA genuine exported NFC host-card-emulation service, not a mock.decompiled client · §6Confirmed
Mini-app bridge platformReal opcode launch, a public JS bridge we pulled, phone-number share to a bot, and every bridge call telemetered.decompiled client · §6Confirmed
ML model push (ZipSlip)Server can push a new noise-suppression model; the unzip step has a path-traversal bug and the server supplies both file and checksum.decompiled clientConfirmed
Full installed-app list uploadedReported by an earlier code analysis; in the build we decompiled (26.31.0) the MyTracker enumeration hook is present but unwired: no class implements it, nothing calls it, and there is no QUERY_ALL_PACKAGES permission, so this build uploads no app list. The bundled SDK could do it; a different build could wire it.decompiled clientRefuted (this build)
Silent server-triggered call recordingInbound dispatcher (~49 commands) has no “collect the mic” case; every mic-dump function has zero callers. Real feature is a user-started, notified recorder.decompiled clientRefuted
Stealth chat screenshotsFLAG_SECURE blocks your screenshots on protected chats; it does not take and upload one.decompiled clientRefuted
Hidden keyword listener (KWS)Native engine present but zero Java arms it and the library can’t reach the network; the model was removed two versions back.decompiled clientRefuted
Dynamic remote code loadingZero DexClassLoader-family calls; short of the full app-swap, no new executable code loads from the network.decompiled clientRefuted

Across the full review: 32 confirmed, 6 narrowed, 5 refuted: 43 claims, each checked against the decompiled client.

Method: our own pull of the build, our own SHA-256, baksmali + Ghidra + strings/readelf against the decompiled client; no third-party dump or mirror backs any claim. Act III is an explicit thought experiment and describes no observed behaviour; payment rails, bank names and specific government services are from public reporting and marked as such.
Thanks & sources: external pointers we independently verified, InterSecLab’s nine-week dynamic study (corroboration and leads), and the forum / reverse-engineering write-ups by owenewans (Habr) and zarazaex. Their observations are credited as pointers; every claim here is re-derived against our own build.
MAX 26.31.0 / vCode 6822 · APK SHA-256 verified against our own pull · decompiled 2026.