WRITEUP · FINTECH · LINKING · 2026 · @YNSMROZTAS

Wallet link, static client id

● live clk --:--:-- com.lab.wallet

Four classes on one lab wallet. Vendor hosts, PIN client id, account files and tap scripts are not on this page.

wallet // liveredacted
radar--:--:--
AndroScope CWE-798 linking API posture
01 Problem

A static PIN client id plus an unlink that resets merchant eligibility.

02 Move

Public-artifact review + lab posture on an authorized emulator session. No charge.

03 Evidence

Client id accepted (not 401). Linking probes had no bot challenge. App ran on a spoofed handset fingerprint.

04 Outcome

Rotate the id. Bind sessions. Persist pay-state across unlink. Step-up on unlink.

Summary

Lab wallet com.lab.wallet talks to api.lab.wallet.test for third-party merchant linking. A static X-Client-Id has been sitting in public artifacts since 2024. Linking routes answered lab probes without a bot challenge. Unlinking a merchant reset whatever flag the wallet used for “already paid this service.” The Android client accepted a spoofed handset fingerprint and showed its home surface with no integrity block.

This page is the class, not the kit. No PIN, no OTP path, no charge call, no coordinate list.

Classes: CWE-798 static client id · missing bot control on link · business-logic reset on unlink · empty emulator posture. Vendor chrome stripped.

Lab frames

Rebuilt from the session. Branding, balance and merchant tiles removed.

Redacted wallet splash
Splash — lab wallet, vendor mark gone
Redacted wallet home
Home — linked-apps row present, balance hidden
Redacted posture terminal
Posture + API class. Secrets and hosts replaced.

Four findings, one wallet

1. Static PIN client id

PIN-token mint used a header X-Client-Id that is not per-user and not per-session. The same literal appears in more than one public artifact. A lab probe that sent the id and omitted the PIN body came back as a field-validation error — not 401 / invalid_client. The id is treated as a known client, not as a secret that failed.

POST  api.lab.wallet.test/v1/users/pin/tokens/nb
X-Client-Id:  [REDACTED · static · public since 2024]

→  200   field cannot be blank
    not 401  ·  id accepted, body incomplete

mitsec@com.lab.wallet:

2. Linking API without a bot gate

Consent / validate-reference style routes on the linking host answered. There was no CAPTCHA, no device-bound assertion, no session cookie required for the probe to be parsed. Rate limit, if any, was not visible at the single-call layer. This page does not replay the six-step merchant charge.

3. Unlink resets eligibility

After a merchant link, the in-app “linked apps” row could drop the merchant. The next link treated the wallet as clean for that merchant again. No step-up (PIN / biometric) sat on the unlink confirm in the lab build. That is a state machine bug, not a tap recipe.

4. Emulator posture

The lab runtime presented a mid-range Samsung model string, user build, debuggable=0, secure=1, empty qemu flag. A twelve-check fingerprint scorer on that session printed “handset.” com.lab.wallet drew splash and home. No integrity interstitial. AndroScope logs the posture. It does not publish the ADB input sequence.

What this is not

Impact (class)

A static client id plus an unlink-reset means one authorized wallet can be driven through the same merchant link more than the product intended. Bot-empty linking means the drive does not need a human at each step. Emulator-blind UI means the drive can sit off a physical handset. Money movement is a program issue; this page stops at the four controls that failed.

Fix

Lab frame

Android 12 class image, authorized session, 2026-05-29. Static review of public artifacts plus passive probes. No live payment, no third-party mailbox, no customer PIN.

YUNUS EMRE ÖZTAŞ · MITSEC · RESPONSIBLE DISCLOSURE · LAB NAMES ONLY