Security assessment · defensive research

Is braands.io a scam?

A forensic look at the "fractional ownership in domains" NFT marketplace — specifically what its Connect Wallet button asks you to sign, and whether the site is malicious. Nine agents tore the bundle and all 35 lazy chunks apart, then three more tried (and failed) to refute the verdict. The short answer: nothing is signed at connect, and it is not a wallet drainer — but it is a negligent, half-dead project you should not use.

Target https://braands.io Bundle main.41b471ce.js · 2.6 MB · 35 chunks Verdict confidence High Date 2026-07-14
Overall risk Medium —
do not use
Drain-at-connect None

Not an active wallet-draining scam. Connecting signs nothing, no drainer payload exists in the code, it is on no blocklist, and there are no victim reports. Three independent red-team lenses tried to break that conclusion and could not.

But "not a drainer" is not the same as "safe." It is a broken, centralized, leaky project.

The backend is dead (every /api/api/* endpoint returns 502), the NFT metadata layer is dead (IPFS returns 401), the "Ethereum" path points at the long-sunset Goerli testnet, a live write-capable Pinata API key and a client-side admin login of OTP "1234" are hardcoded in the bundle, and the one real contract is an upgradeable proxy owned by a single private key. You cannot lose funds to a signature at connect — but buying anything is non-functional, and the operator is negligent enough that connecting at all is a bad idea.

01

What "Connect Wallet" asks you to sign

the headline question

The connect button, the WalletConnect option, and the "ConnectViaWhatsApp" variant were all traced to their handlers in the minified bundle and verified byte-for-byte. The flow is the same in every case.

Answer
Nothing. Connect only triggers eth_requestAccounts — your wallet reveals your address, with no signature prompt. The app then POSTs that bare address to its login API and shows a "Signin Successful!" toast that is not backed by any signature.

No personal_sign, no signTypedData, no SIWE / "Sign in to…" message, and no nonce. The backend has no /nonce, /sign, or /verify endpoint — it simply trusts the address the wallet reports. (Note: that is itself a security flaw on the operator's side — anyone can impersonate any address — but it does not endanger the connecting wallet's funds.)

Connect handler
web3-react activate(InjectedConnector)eth_requestAccounts (address reveal only)
After connect
POST wallet_addresshttps://braands.io/api/api/login → JWT stored in cookie
Signatures at connect
None. The toast "Signin Successful!" is a label, not a signature
WalletConnect path
Identical — activate(WalletConnectConnector), then reads accounts from localStorage
ConnectViaWhatsApp
Activates injected, POSTs {sid, wallet_address} to /whatsapp/connectwallet, redirects to a WhatsApp chat — no signature
Later signatures
setApprovalForAll / approve / eth_sendTransaction exist only inside the buy/auction flow, gated behind an explicit action — never at connect
infoconfidence high

The MetaMask handler calls only activate() — no signing call follows

V is destructured as activate from useWeb3React; lt is the InjectedConnector. The entire handler is activate + a toast.

onClick: async () => { if (window.ethereum) { await V(lt), Q(), O(!1), m.oR.success("Signin Successful!"), K(!0) } else { m.oR.error("Metamask is not available…") } } // const { activate: V } = useWeb3React(); const lt = new InjectedConnector({ supportedNetworks:[1,4] });
mediumconfidence high

The "login" step is address-only — no signature, no nonce, no proof of ownership

The login function builds a FormData containing only wallet_address, POSTs it, and stores the returned JWT. No signature field anywhere in the request.

Z = function(e = account) { let t = new FormData; t.append("wallet_address", e); axios.post(API_URL + "/login", t).then(e => Cookies.set("Token", e.data.token)) } // API_URL = "https://braands.io/api/api"
infoconfidence high

No SIWE / sign-in message template exists anywhere

Zero app-level hits for signMessage, signTypedData, signTypedData_v4, "Welcome", "Sign in to", or SIWE. The 2 personal_sign matches are web3.js method-registry entries, not calls.

new i({ name:"sign", call:"personal_sign", params:3, inputFormatter:[inputSignFormatter, inputAddressFormatter, null] }) // web3.js registry, not an app call
infoconfidence high

Backend has no challenge-response endpoints

Full endpoint surface: /login, /register, /getuser, /profile, /newsletter, /whatsapp/connectwallet. No /nonce, /sign, /auth, or /verify — confirming no signature flow.

02

Wallet-drainer & malware scan

clean — main bundle + 35 chunks

One agent adversarially downloaded all 35 lazy-loaded chunks (1.81 MB total) and grepped each for drainer signatures, hidden recipient addresses, and obfuscation. The red-team static-code lens then re-ran the hunt independently. Both concluded: no drainer, no malware.

Drainer payload
None found

Zero hardcoded target addresses across all 35 chunks — a drainer must embed one.

Drainer-kit signatures
Zero

Permit2, seaport, inferno, pink, monkey, ice-phishing — all absent.

App obfuscation
None

No app-level eval / new Function / atob. Library internals only.

infoconfidence high

No hardcoded hex addresses in any lazy chunk

A wallet drainer must embed a recipient/target address somewhere in its code. Across all 35 chunks, grep '0x[a-fA-F0-9]{20,}' returns nothing. The 5 project contracts live only in the main-bundle config.

infoconfidence high

All approval/transfer drainer signatures absent from chunks

setApprovalForAll, safeTransferFrom, approve(, increaseAllowance, transferFrom — zero hits in every chunk. The only signing strings present live in chunk 182, which is the WalletConnect provider library.

// chunk 182 (232 KB) — WalletConnect provider transport, not app code: K = ["eth_sendTransaction","eth_sign","eth_signTypedData_v4","personal_sign","wallet_switchEthereumChain", …] // JSON-RPC method whitelist async signTypedData(t){ … this._formatRequest({ method:"eth_signTypedData", params:t }); return await this._sendCallRequest(e) }
infoconfidence high

The balanceOf calls are inventory display, not a "scan-then-drain"

Chunk 748 (the "My NFTs" dashboard) reads the user's own tokens read-only (.call()) to show inventory. It issues zero transfer / approve / sendTransaction calls.

lowconfidence high

Every "scary" primitive is explained by a benign library

createElement("script") in chunk 277 = react-recaptcha loader; iframe in 390 = react-lite-youtube-embed; navigator.clipboard in 177/523 = copy-share-link; wallet_switchEthereumChain only in the WalletConnect provider. No document.write, no remote-script injection.

infoconfidence high

No hidden dynamic loader

The webpack runtime chunk-map lists exactly 35 chunks; import( count in the main bundle is 0. There is no extra code loaded beyond what was scanned.

03

Contracts & on-chain reality

centralized · mostly dead

Of the five "custom contracts" the initial scan flagged, four are false positives (truncated genesis-block hashes embedded by ethereumjs, and a secp256k1 curve constant). Only one is real — and it is an upgradeable proxy under a single key, sitting on a network path that mostly doesn't work.

Real contract
0xe3a5284e979e1a60ed0abc1841070144057b989f on Polygon — name "Braands.io" (BRD), EIP-1967 TransparentUpgradeableProxy
Implementation
0x475bb1f7fce50ab4bad7090ce5f6b4e10601e7d0
Owner (proxy + admin)
Same single EOA: 0xa8dc7ed4331041471152d67d70fe3d09d3996fac
"ETH" contract
0x380dcDe4…5848A6no code on mainnet; config binds it to Goerli (chainId 5, dead since 2023)
On-chain activity
~38 lifetime transactions; contract holds 0 MATIC; owner EOA holds ~$0.40
NFT metadata
braands.infura-ipfs.io401; token CIDs → 504 no providers (orphaned)
highconfidence high

One private key controls everything

The proxy's owner() and the ProxyAdmin.owner() resolve to the same EOA. That key can upgrade the logic, mint unlimited supply (super_mint), and rewrite any token's metadata URI (setUrl) at will.

eth_call owner()(0x8da5cb5b) on proxy → 0xa8dc7ed4331041471152d67d70fe3d09d3996fac eth_call owner()(0x8da5cb5b) on ProxyAdmin → 0xa8dc7ed4331041471152d67d70fe3d09d3996fac // identical
infoconfidence high

No hidden drainer functions in the contract

The red-team extracted all 71 dispatcher selectors from the implementation bytecode and diffed them against the 82-entry frontend ABI. The only unexplained selector (0x0e89341c) resolves to uri(uint256), which is in the ABI. Zero hidden functions: no selfdestruct, no sweep, no arbitrary transferFrom, no honeypot tax.

highconfidence high

The Ethereum / IPFS halves of the product are dead

The "ETH" contract has no code on mainnet and only ever lived on Goerli (now sunset). The IPFS gateway returns 401 and the token CIDs return 504 — so NFT metadata cannot resolve. The dApp is effectively Polygon-only and even there sees ~no use.

infoconfidence high

What this means for funds today

There is currently 0 MATIC in the contract and no withdraw function exists in the ABI — so even the all-powerful owner cannot sweep a balance without a future upgrade. This is a future-rug capability, not a current drain. It does not change the verdict, but it is the single biggest reason not to buy and hold these tokens.

04

Domain & infrastructure

real operator, low-rent hosting

The domain is four years old and run by an identifiable (if small) Indian development shop — which actually argues against it being an anonymous drainer. But it is hosted on a bare shared VPS with no protections, next to some less-savory neighbours.

Registered
2022-07-29 via GoDaddy, privacy-shielded (Domains By Proxy) — renewed through 2026-07-29
Hosting
Bare VPS 38.225.206.93, Delhi, India (AS150654 Kennies Star); nginx/1.24.0 directly, no CDN / WAF
TLS
Let's Encrypt only (free, 90-day); first cert 2025-04-11 — current server went live ~2.7 yr after the domain
Operator
Co-hosted with simplicitylabs.org — a Gurugram Web3/AI dev agency (real LinkedIn, real clients)
Name
"braands" (double-a) is a deliberate brandable spelling, not typosquatting of a known brand
mediumconfidence high

Shared with an MLM admin panel and trading apps

Reverse-IP on the server lists co-hosted projects including mlm-admin-echobit, ecotrader, enterx, gaanagpt and rhoof.io, alongside simplicitylabs.org. MLM/trading adjacency is a yellow flag, though no corroborated fraud report names the agency.

lowconfidence high

Registration predates the current server by ~2.7 years

The domain was publicized via a BusinessWire press release (CEO Arjun Mishra, Gurugram) in Jan 2023, but the current server's first TLS cert is April 2025 — the project was parked or migrated. A real press release and a four-year-old domain are mild positive signals versus a fresh throwaway scam domain.

infoconfidence high

Infura IPFS gateway is genuine but dead

braands.infura-ipfs.io resolves to real Infura/AWS IPs but returns 401 — Infura deprecated its IPFS product in 2024. Stale infrastructure, not malicious.

05

Reputation & scam reports

unlisted everywhere — real, but dormant

An independent sweep across blocklists, scan engines, and community forums found no scam classification and no victim reports. The red-team reputation lens confirmed this against the raw blocklist files directly. The honest caveat: absence of reports is weak evidence on its own — but here it is corroborated by the empty contract and the nothing-signed-at-connect flow.

infoconfidence high

Not on any crypto blocklist

Grepped the raw source of CryptoScamDB, ScamSniffer, MetaMask eth-phishing-detect, PocketUniverse/PhishFort, and EtherAddressLookup — zero hits on all five. An active drainer is almost always on at least one.

infoconfidence high

urlscan.io: clean history

3 scans since 2022 (none since Apr 2024), each with an empty verdicts object — no engine flagged it malicious. urlvoid has no report at all.

infoconfidence high

No victim reports anywhere

No threads on Reddit (r/NFT, r/CryptoScams, r/Scams), no Trustpilot page, no Chainabuse report, no hits for the contract address in scam contexts. The only negative web result ("forexroboteasy.com dismal rating") is auto-generated SEO spam, not a real review.

infoconfidence high

Real, but tiny, footprint

Real BusinessWire press release (paid, but real), LinkedIn page (265 followers), live Twitter/Facebook, and an OpenSea collection (braands-domains-polygon) marketing cheap .online/.host domains. Consistent with an over-marketed, near-dormant side-project — not a thriving market.

06

Security holes & exposed secrets

the real problems

This is where the picture turns from "benign" to "negligent." The site doesn't steal from visitors, but it leaks live credentials and ships a fake admin panel. These are the operator's problems, but they are exactly why you shouldn't trust the platform with anything.

highconfidence high

Live, write-capable Pinata API key + secret hardcoded in the bundle

Verified live against Pinata's API (HTTP 200). Anyone can pin/unpin IPFS content on Braands' account — enabling NFT-metadata defacement or storage abuse.

REACT_APP_PINATA_KEY = "ba9bc9d12d6e83485906" REACT_APP_PINATA_SECRET = "5608de9caba11209a8d77f97e173a4c892970fa12f8bdcd098acb0d19a2269ea" // curl -H pinata_api_key / pinata_secret_api_key https://api.pinata.cloud/data/testAuthentication → 200 "Congratulations!…"
highconfidence high

Admin login is client-side OTP "1234" + a cookie

The /admin route is reachable (HTTP 200). Auth is if (otp === "1234") { Cookies.set("adminusername", email); go("/admin/dashboard") } — fully readable in the exposed sourcemap. No server check; anyone can set the cookie and enter.

highconfidence high

A 22 MB webpack sourcemap with full source is publicly served

main.41b471ce.js.map (HTTP 200) contains sourcesContent — the original TS/JSX for 113 app files, including the admin auth. Everything above was readable because the operator shipped the sourcemap.

mediumconfidence high

The entire backend API is dead (502)

Every /api/api/* endpoint (login, register, profile, getdomain, newsletter) returns 502 Bad Gateway. The frontend is alive but the backend is gone — so login/buy/checkout all fail.

mediumconfidence high

Infura IPFS project secret + dead ETH path exposed

Infura IPFS project ID + secret are in the config; the live "ETH" RPC points at Goerli (dead). Local endpoints (localhost:8500, localhost:8545) leaked into the production build.

lowconfidence high

Badly stale stack, never maintained

React 17.0.2 (Feb 2021), ethers v5, web3.js 1.x, moment.js; 7+ dead testnets still referenced (Ropsten/Rinkeby/Goerli/Kovan/Mumbai/Arb-Rinkeby/Opt-Kovan). Reads as ~2021–22 code that was abandoned, then parked on a fresh server in 2025.

infoconfidence high

No leaked user keys

No hardcoded private keys, mnemonics, or seed phrases in app code. All privateKey references are web3.js keystore internals — one small reassurance.

07

Verdict & what to do

bottom line
Is it a scam?
Not a wallet-draining scam — but an insecure, broken, centralized project that you should treat as untrusted.

Connecting will not drain your wallet (nothing is signed, no drainer payload exists, it is on no blocklist). But connecting does hand your address and IP to a negligent operator, and the product itself is non-functional (dead backend, dead metadata, single-key upgradeable contract, live leaked secrets). There is no good reason to connect or transact here.

What this means for you:

  • If you already connected — relax about the connection itself. Nothing was signed, so there is no approval to revoke from the connect step. Your funds are not at risk from having connected.
  • Check for approvals anyway — if you ever went further and bought/auctioned, review and revoke any setApprovalForAll granted to 0xe3a5…989f on Polygon (e.g. via revoke.cash). The contract is upgradeable under one key.
  • Do not buy or hold BRD tokens — the owner can mint unlimited supply and rewrite metadata unilaterally, the market is effectively dead, and NFT metadata won't even display.
  • Do not enter any credentials — the admin auth is fake client-side code; treat all input to this site as compromised-adjacent.
  • Use a burner wallet for any curiosity-driven web3 interaction, never your main holdings.
08

How this was checked

methodology

Static analysis of the live production bundle (main.41b471ce.js, 2.6 MB) plus all 35 lazy webpack chunks (downloaded from /static/js/{id}.{hash}.chunk.js using the runtime chunk-map — 1.81 MB total, zero hidden loaders). Wallet-flow handlers were traced byte-for-byte in the minified code and cross-checked against the exposed sourcemap. The backend API surface was enumerated from the bundle and probed live.

On-chain checks were done over public RPC (Polygon / BSC / Ethereum): eth_getCode, eth_getStorageAt on the EIP-1967 slots, eth_call for owner() / name() / symbol(), implementation-selector extraction and diff against the frontend ABI. Domain/infra via WHOIS, DNS, crt.sh, reverse-IP, and TLS inspection. Reputation via raw greps of CryptoScamDB, ScamSniffer, MetaMask eth-phishing-detect, PocketUniverse/PhishFort, and EtherAddressLookup blocklists, plus urlscan.io and community forums.

An adversarial red-team pass then tried to refute the headline verdict from three lenses — static code, on-chain/contract, and reputation/intel. All three returned can_refute: false at high confidence. Reported honestly: a full historical on-chain log sweep (2022→present) could not be completed because public RPCs cap eth_getLogs ranges — so 2022–23 mint activity cannot be 100% excluded, though all other evidence points the same way.