In Part 1 of this series, we explored how authentication flaws and logic errors can compromise Web3 platforms – from brute-force attacks bypassing two-factor authentication to IDOR vulnerabilities that lock users out of their own funds. Those vulnerabilities were dangerous, but they required some level of exploitation skill and understanding of API manipulation.
What we’re sharing today is different. These are the vulnerabilities that keep security teams awake at night – the ones where a single mistake exposes everything. No complex attack chains, no sophisticated techniques required. Just catastrophic oversights that hand attackers complete control.
Throughout our 2025 assessments at Securze, we encountered many vulnerabilities that represent the worst-case scenarios in Web3 security: regulatory compliance bypassed with a browser proxy, private keys exposed through unprotected APIs, and platform secrets sitting in plain sight for anyone to find. Each one could single-handedly destroy a platform.
These aren’t theoretical risks. These are real vulnerabilities we discovered in production systems serving millions of users, managing substantial funds, and operating under regulatory oversight. The platforms looked professional, had experienced teams, and followed security best practices – or so they thought.
Let’s continue where we left off and examine the vulnerabilities that cross the line from “serious security issue” to “existential threat.”
Before we start; Our Founder – Harsh Parekh recently spoke about the critical security vulnerabilities we identified while pentesting different Web3 applications and platforms at Securze. Listen to him here:
Vulnerability #4: Trading Without Identity – The KYC Bypass
Application Type:
A Web3 crypto trading exchange with integrated custodial wallet functionality. The platform requires KYC (Know Your Customer) verification to comply with financial regulations and enable full trading capabilities.
Vulnerability Description & Severity:
Critical Severity – Client-side KYC verification allowed attackers to bypass identity checks and access restricted features including custodial wallets, trading, and fund withdrawals – creating complete regulatory non-compliance and enabling anonymous financial transactions.
Behind the Scenes (Discovery):
KYC verification is the backbone of regulated crypto platforms. It’s not just a feature – it’s a legal requirement in most jurisdictions. Platforms that fail to properly verify user identities face massive fines, regulatory shutdowns, and criminal liability for enabling money laundering or terrorist financing.
So when we started testing this exchange’s KYC implementation, we were looking for the most critical question in financial security: Can someone use this platform to move money anonymously?
We created a test account and intentionally didn’t complete KYC verification. The platform showed us a banner: “Complete KYC to unlock full features.” Fair enough. But we wanted to see what happened under the hood when the platform checked our KYC status.
We intercepted the API responses and found something interesting: every time we accessed a page, the server sent back our user profile with a field: “kyc_verified”: false. The front-end JavaScript read this value and decided what features to show us. Simple client-side authorization.
Then we asked ourselves: What if we just… changed it?
Technical Flow:
The platform’s KYC verification worked like this: When a user logged in, the front-end made API calls to fetch user data. The server responded with a JSON object containing various user attributes:
json
{ "userId": "a3d5f891-4c2e-4b8a-9d3f-8e7c1b2a4f6d", "email": "user@example.com", "kyc_verified": false, "account_status": "active", }
The front-end JavaScript code checked this kyc_verified field and made decisions:
- If false: Hide trading features, disable wallet access, show KYC prompt
- If true: Enable full platform access, show custodial wallet, allow trading
The critical flaw: this check happened entirely in the browser. The server sent the actual status (false), but it was the client-side code that enforced the restrictions.
The Vulnerability:
We set up a local HTTP proxy on our machine – a tool that intercepts network traffic between our browser and the server. Think of it like a filter that can read and modify data as it passes through. These tools are available (Burp Suite, OWASP ZAP) and commonly used for our internal security testing.
Here’s what we did:
Step 1: Configured our browser to route all traffic through the proxy.
Step 2: Logged into our non-KYC-verified account and intercepted the API response containing our user profile.
Step 3: Modified the response in real-time, changing “kyc_verified”: false to “kyc_verified”: true before it reached our browser.
Step 4: The browser’s JavaScript code received the modified response, saw “kyc_verified”: true, and unlocked all platform features.
From the browser’s perspective, we were a fully verified user. The interface changed completely – trading features appeared, the KYC banner disappeared, and most importantly, the custodial wallet option became available.
Step 5: We navigated to the wallet section and clicked Create Wallet.
Now, we expected this to fail. Surely the backend would verify KYC status before creating a wallet, right?
Wrong.
The wallet was created successfully. The wallet APIs didn’t perform their own KYC checks – they relied on the assumption that if a user could access the wallet page, they must be KYC verified. It was a trust-the-front-end architecture.
Step 6: We now had an active custodial wallet address on the platform. We tested whether we could actually use it by sending a small amount of crypto to the wallet address through an on-chain transaction from our personal MetaMask wallet.
The funds appeared in our platform wallet balance. We were holding real money on a regulated exchange, with zero identity verification.
Step 7: We placed test trades on the exchange – buying and selling crypto pairs. All trades executed successfully. We were conducting financial transactions completely anonymously.
Step 8: Here’s where it gets worse. We attempted to withdraw funds. We initiated a withdrawal to an external wallet address (back to our MetaMask).
The platform processed the withdrawal. Funds left the platform and arrived in our external wallet.
We had successfully:
- Created an account without KYC
- Activated a custodial wallet
- Deposited funds
- Executed trades
- Withdrawn funds to an external address
All while the server’s database correctly showed “kyc_verified”: false. We never actually bypassed the KYC process – we just made the front-end think we had.
Why This Worked:
The platform made a fundamental architectural mistake: it treated authorization as a UI problem instead of a security problem.
Here’s what should have happened: Every sensitive operation (create wallet, execute trade, withdraw funds) should independently verify KYC status on the backend. The front-end UI can hide buttons for better user experience, but the backend APIs must enforce the actual security rules.
Instead, the flow was:
- Front-end checks kyc_verified → hides/shows features
- User clicks “Create Wallet”
- Backend receives request → creates wallet (no KYC check)
- Backend assumes: “If they got this far, they must be verified”
One interesting detail: we found that direct deposit attempts through the platform’s deposit interface were blocked by backend checks. The platform integrated with a third-party payment provider that performed its own KYC verification. But the custodial wallet was an internal system, and it had no such protection. By using on-chain deposits directly to the wallet address, we bypassed the protected deposit flow entirely.
Real-World Impact:
This vulnerability completely undermines the platform’s regulatory compliance and creates severe legal and financial exposure. Attackers can conduct fully anonymous financial transactions on a supposedly regulated exchange – depositing funds, trading, and withdrawing to external wallets without any identity verification. This enables money laundering, terrorist financing, proceeds from ransomware attacks, and sanctions evasion, all through a platform that claims regulatory compliance. For the platform, the consequences are catastrophic: regulators can impose multi-million dollar fines, revoke operating licenses, pursue criminal charges against executives, and force immediate shutdown of operations. The platform becomes a liability magnet – every anonymous transaction could be linked to criminal activity, creating unlimited legal exposure. Beyond regulatory consequences, the platform loses partnerships with compliant exchanges and payment providers, faces reputational destruction in the industry, and becomes a target for sophisticated criminals who exploit the KYC bypass at scale. The severity multiplies in jurisdictions with strict AML (Anti-Money Laundering) requirements – a single instance of KYC bypass enabling illicit transactions can trigger investigations that reveal systemic compliance failures.
Recommended Fix:
Implement server-side KYC enforcement on every sensitive operation: wallet creation, trading, deposits, and withdrawals must independently verify kyc_verified status from the database before processing, never trusting client-supplied data or front-end state. Specifically, the wallet API endpoints must check KYC status directly against the user’s database record using the authenticated session’s user ID. Remove any dependency on front-end parameters for authorization decisions – the UI can enhance user experience by hiding unavailable features, but all security enforcement must happen server-side. Add comprehensive KYC audit logging that tracks every attempt to access restricted features (successful or blocked) with timestamps, user IDs, and KYC status at the time of attempt, enabling detection of bypass attempts.
Vulnerability #5: The Keys to Everyone’s Kingdom – Private Key Exposure
Application Type:
A custodial Web3 wallet application with over 1 million users.
Vulnerability Description & Severity:
Critical Severity – An IDOR vulnerability in the private key retrieval API allowed any authenticated user to access other users’ wallet private keys, enabling complete takeover of victim wallets and theft of all funds.
Behind the Scenes (Discovery):
In crypto wallets, your private key is everything. It’s the mathematical proof of ownership. Whoever controls the private key controls the funds – no exceptions, no reversals, no customer support that can help.
We were testing the wallet application’s API endpoints when we noticed something alarming:
GET /api/user/wallet/privatekey/11
Why would an API endpoint openly expose private keys? We had to investigate.
Technical Flow:
Users created accounts, and each account could have multiple wallets identified by numeric IDs (1, 2, 3, etc.). When users accessed their wallet details, the application made this API call:
GET /api/user/wallet/privatekey/11 HTTP/2 Host: wallet.example.com Authorization: Bearer [user's_auth_token]
The response:
json
{ "walletId": 11, "userId": "a3d5f891-4c2e-4b8a-9d3f-8e7c1b2a4f6d", "publicKey": "0x742d35Cc6634C05....95f0bEb", "privateKey": "0x4c0883a6910293....8836t3681d8c2b3a" }
Both public and private keys were sent in the response.
The Vulnerability:
We changed the wallet ID from 11 to 12 in the URL and sent the request with our same authentication token.
The server responded with wallet ID 12’s complete information – including its private key. This wallet belonged to a different user entirely.
We tested random IDs: 1, 50, 100, 500. Every request returned valid wallet data with private keys. The API only verified the authentication token was valid and the wallet ID existed – it never checked if the authenticated user owned that wallet.
The Attack:
Step 1: Create an account on the platform.
Step 2: Make automated requests to /api/user/wallet/privatekey/[ID], iterating through wallet IDs from 1 to potentially millions.
Step 3: Extract private keys from each response.
Step 4: Import those private keys using Import functionality on the platform.
Step 5: Transfer all funds to attacker-controlled addresses.
With over 1 million users, an automated script could extract all private keys in hours. Once an attacker has your private key, they have permanent, irrevocable access to your wallet forever. They can drain funds immediately, monitor for new deposits, or sell the keys to other criminals. There’s no recovery – a compromised private key means that wallet is permanently unsafe.
Real-World Impact:
Any authenticated user could drain every wallet on the platform. Users lose all crypto holdings with no recourse – no insurance, no refunds, no way to reverse transactions. The platform faces total destruction: legal liability potentially reaching billions of dollars, complete loss of user trust, regulatory investigations for gross negligence, criminal charges for failing to protect user funds, and immediate mass exodus. This is an extinction-level event – the platform cannot survive once this becomes public. Every dollar stored on the platform is at risk from anyone with a free account.
Recommended Fix:
Implement strict authorization checks: the /privatekey endpoint must verify that the authenticated user owns the requested wallet by comparing the wallet’s userId in the database against the authenticated session’s user ID – reject any mismatch immediately. Replace sequential wallet IDs with UUIDs to prevent enumeration. Add rate limiting (max 5 requests per user per minute) and comprehensive logging that flags any attempts to access wallets not owned by the requester. Consider architectural changes: encrypt private keys at rest with user-controlled passwords that the platform never stores, require additional authentication (2FA, email confirmation) before exposing private keys, and implement anomaly detection for bulk key access patterns. Conduct immediate security audit to determine exposure scope and notify affected users. The principle: wallet ownership must be cryptographically verified server-side for every sensitive operation – never trust the client-supplied wallet ID.
Vulnerability #6: The $100+ Million Mistake in Plain Sight
Application Type:
A Web3 trading + wallet application managing user funds through hot wallets. Hot wallets are internet-connected wallets used for operational liquidity – processing user withdrawals, facilitating trades, and managing platform reserves.
Vulnerability Description & Severity:
Critical Severity – Platform hot wallet private keys were hardcoded in publicly accessible JavaScript files, exposing complete control of the platform’s operational funds to anyone who viewed the source code.
Behind the Scenes (Discovery):
During our security assessment, we followed standard practice: reviewing the application’s client-side code. Modern web applications load JavaScript files that handle everything from UI interactions to API calls. These files are publicly accessible – anyone can view them through browser developer tools.
We opened the browser’s developer console, navigated to the “Sources” tab, and started examining the JavaScript files loaded by the application. One file caught our attention – it was larger than typical frontend code and had an unusual name suggesting configuration or setup logic.
We opened it and started reading through the code. Then we saw it.
Technical Flow:
Buried in the JavaScript file, among thousands of lines of code, were hardcoded values:
const hotWallets = [ { address: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", privateKey: "0x4c0883a69102937d6231471b5dbb6204fe512961708279f4f9f1a8c4f7d8c2b3a" }, { address: "0x8d12A197cB00D4747a1fe03395095ce2A5CC6819", privateKey: "0x2a5c9f8e1b3d4a6c8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d" }, // ... 8 more key pairs ];
Ten complete key pairs. Public addresses and their corresponding private keys. For the platform’s hot wallets.
This wasn’t obfuscated. It wasn’t encrypted. It was plain text, sitting in a file that anyone visiting the website would automatically download to their browser.
The Vulnerability:
Hot wallets hold operational funds – the liquidity platforms need to process user transactions. Depending on the platform’s size and trading volume, hot wallets can contain anywhere from thousands to millions of dollars worth of crypto assets.
These private keys gave complete, unrestricted access to those wallets. Anyone who found them could:
- Check the current balance of each wallet
- Transfer all funds to their own addresses
- Empty the platform’s operational reserves instantly
- Leave the platform unable to process withdrawals
We immediately checked the wallet addresses on blockchain explorers to see if they were active and funded. They were. The wallets contained significant amounts of crypto assets – enough to process the platform’s daily operations.
The Attack:
The exploitation path was absurdly simple:
Step 1: Visit the platform’s
Step 2: Open browser developer tools (F12 key on most browsers).
Step 3: Navigate to Sources tab and read the JavaScript files.
Step 4: Find the hardcoded private keys (takes minutes with basic text search).
Step 5: Import those private keys into a corresponding wallet application.
Step 6: Transfer all funds to attacker-controlled addresses.
This required zero hacking skills. No API exploitation, no authentication bypass, no complex attack chains. Just reading publicly available code that the platform itself served to every visitor.
The scariest part: this vulnerability had likely existed since the code was deployed. Any user, competitor, security researcher, or malicious actor who looked at the source code could have discovered it. We found it during a scheduled assessment – but how many others had seen it before us? The platform immediately took action in investigating and revoking wallets, transferring funds to another safe wallet for the time being.
Real-World Impact:
This is a critical platform vulnerability. An attacker could drain all operational funds instantly, leaving the platform unable to process user withdrawals and creating an immediate liquidity crisis. Users attempting to withdraw would face errors and delays, triggering panic and potential bank run scenarios. The platform would need to halt all operations, announce the breach, and face complete loss of user confidence – no one trusts a platform that left millions of dollars in private keys sitting in public JavaScript files. Financial losses could reach tens of millions depending on hot wallet balances, with additional costs from emergency response, legal liability, regulatory fines for gross negligence, and potential criminal investigations. The reputational damage is permanent – this level of security failure demonstrates fundamental incompetence in protecting user funds.
Recommended Fix:
Remove all private keys from client-side code immediately – private keys must never exist in JavaScript files, configuration files, or any code that gets sent to users’ browsers. Hot wallet management must be exclusively server-side: private keys should be stored in secure key management systems (Hardware Security Modules or cloud KMS like AWS KMS, Google Cloud KMS), encrypted at rest, accessible only to backend services with strict access controls, and never exposed through any API or frontend code. Implement emergency key rotation: assume these keys are compromised, generate new hot wallet addresses, migrate funds to the new wallets, and deprecate the exposed addresses. Conduct comprehensive code audit to identify any other hardcoded secrets (API keys, database credentials, authentication tokens). Implement secrets scanning in the CI/CD pipeline to prevent future commits containing sensitive data. Add monitoring for the compromised wallet addresses to detect if any unauthorized transactions occur. The principle: anything sent to the client is public – secrets must live exclusively on secure backend infrastructure.
Closing:
Here’s the uncomfortable truth: every vulnerability we’ve shared was in a production platform. Real users. Real money. Real consequences waiting to happen.
The founders thought they were secure. They had experienced developers, multiple code reviews, and passing audits. But they missed what matters most—understanding how an attacker actually thinks. Not following checklists. Not running automated scans. Actually breaking down each component and asking: “Where does the logic fail?”
Your smart contract audit gave you a clean report. Great. But can someone brute-force every account in 10 minutes? Can they create redemption requests that lock users out of their own funds? Are there logical gaps in your authentication flow that make passwords optional?
You don’t know what you don’t know. And that’s exactly what attackers exploit.
Over the past year, we’ve identified over 100 vulnerabilities across Web3 platforms—critical flaws, logical gaps, and architectural failures that could have destroyed businesses overnight. What we’ve shared in this series is just a fraction of what we encounter. It’s impossible to document every finding, every near-miss, every disaster we’ve prevented. But we share what we can because the patterns repeat, and the stakes are too high to stay silent.
At Securze, we’ve stopped attacks before they happened. We’ve found the critical flaws that would have made headlines—the ones that end platforms, destroy reputations, and cost millions. Not because we’re lucky. Because we don’t think like auditors. We think like attackers.
The question isn’t whether vulnerabilities exist in your platform. They do. The question is: will you find them first, or will someone else?
Every day you wait is another day you’re exposed.
Get your application tested by Securze. Let us find what’s hiding before someone else does.
Links: Schedule Your Assessment


