<?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: JUAN F L O res</title>
    <description>The latest articles on DEV Community by JUAN F L O res (@juan_flores_eaa04c5d5a).</description>
    <link>https://dev.to/juan_flores_eaa04c5d5a</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4198154%2F23f01b1c-f3e7-4526-8959-1f7b8d743fcb.png</url>
      <title>DEV Community: JUAN F L O res</title>
      <link>https://dev.to/juan_flores_eaa04c5d5a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juan_flores_eaa04c5d5a"/>
    <language>en</language>
    <item>
      <title>Three Ways Session-Key Modules Leak Permissions</title>
      <dc:creator>JUAN F L O res</dc:creator>
      <pubDate>Wed, 21 Oct 2026 10:51:42 +0000</pubDate>
      <link>https://dev.to/juan_flores_eaa04c5d5a/three-ways-session-key-modules-leak-permissions-722</link>
      <guid>https://dev.to/juan_flores_eaa04c5d5a/three-ways-session-key-modules-leak-permissions-722</guid>
      <description>&lt;h1&gt;
  
  
  Three Ways Session-Key Modules Leak Permissions
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;For teams shipping session keys, agent wallets, or any "limited" key that can move money: the policy is the product. These are the first three patterns I check in every review — because each one turns a carefully scoped session into something close to a blank check.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A session key is a capability token. The account owner signs once, and a lesser key — a dApp, a bot, an AI agent — gets to act within limits: this much value, to these contracts, until this time. Every word of that sentence is enforced by policy code, and policy code is where the leaks live. Not in exotic cryptography. In accounting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leak 1: The silent approve
&lt;/h2&gt;

&lt;p&gt;Most spending policies count what a session &lt;em&gt;transfers&lt;/em&gt;. Approvals are not transfers, so they sail through — and an approval is a loaded weapon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The session calls &lt;code&gt;approve(attacker, uint256.max)&lt;/code&gt; on a token the account holds. No value moved. Every transfer-based check passes.&lt;/li&gt;
&lt;li&gt;The attacker then calls &lt;code&gt;transferFrom&lt;/code&gt; &lt;strong&gt;whenever they like&lt;/strong&gt; — tomorrow, next month, after the session key has expired or been revoked. Revoking the session does nothing to the allowance; it lives on the token contract, not in your session system.&lt;/li&gt;
&lt;li&gt;Worst part: the eventual drain &lt;strong&gt;never passes through the account's execution path at all&lt;/strong&gt;. No hook fires, no policy is consulted. The money leaves via a pull payment your module never sees.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Variants of the same hole: &lt;code&gt;increaseAllowance&lt;/code&gt;, &lt;code&gt;setApprovalForAll&lt;/code&gt; on NFT collections, and signed permits relayed by a third party.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; treat approval-class calls as spend. When a session calls &lt;code&gt;approve&lt;/code&gt;/&lt;code&gt;increaseAllowance&lt;/code&gt;, count the approved amount against the session's cap &lt;em&gt;at approval time&lt;/em&gt; — or ban those selectors for session keys outright and make approvals an owner-only action. If your policy can't see it, it isn't a limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leak 2: Target without selector
&lt;/h2&gt;

&lt;p&gt;Allowlists are usually keyed on contract addresses: "the session may call the DEX router and the token." But an address is not a permission — a &lt;em&gt;function&lt;/em&gt; is. Call any method on an allowlisted contract and the session inherits the whole surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allowlist a &lt;strong&gt;token&lt;/strong&gt; for transfers, and the session also gets &lt;code&gt;approve&lt;/code&gt; (see Leak 1).&lt;/li&gt;
&lt;li&gt;Allowlist a &lt;strong&gt;router or aggregator&lt;/strong&gt;, and the session gets every swap path, every callback, and often a generic execution entry point that can be aimed at arbitrary contracts with arbitrary calldata — your allowlist just became a proxy to anywhere.&lt;/li&gt;
&lt;li&gt;Allowlist a &lt;strong&gt;vault or account-adjacent contract&lt;/strong&gt;, and admin-flavored methods (pause, rescue, reconfigure, withdraw-to) may sit one selector away from the benign function you meant to permit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; permissions are &lt;em&gt;(target, selector)&lt;/em&gt; pairs, never bare targets. A session allowed to swap gets the router's swap selectors — not its &lt;code&gt;multicall&lt;/code&gt;, not its &lt;code&gt;execute&lt;/code&gt;, not its admin surface. And any selector that itself dispatches arbitrary calls (&lt;code&gt;multicall&lt;/code&gt;, &lt;code&gt;execute&lt;/code&gt;, &lt;code&gt;aggregate&lt;/code&gt;) gets treated as guilty until its arguments are inspected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leak 3: Window games
&lt;/h2&gt;

&lt;p&gt;"500 USDC per day" sounds like a hard bound. With a calendar window, it isn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At 23:59 the session spends the full cap. At 00:01 the window resets and it spends the full cap again. &lt;strong&gt;2× the intended limit inside two minutes&lt;/strong&gt;, no rule broken.&lt;/li&gt;
&lt;li&gt;The same shape repeats at every boundary — week, month, "per epoch." The longer the window, the bigger the burst an attacker (or a malfunctioning agent loop) can fire the moment it opens.&lt;/li&gt;
&lt;li&gt;Agents make this worse than humans do: a buggy agent doesn't drain an account slowly and noticeably. It retries at machine speed, and it will find your window boundary at 3 a.m.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; rolling windows and per-transaction caps, working together. A trailing-24h accounting window has no cliff to burst across; a per-tx cap bounds any single action; a window cap bounds the total. Any one of the three alone has a shape that leaks — the combination is the actual control.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I build it — and where my own demo stands
&lt;/h2&gt;

&lt;p&gt;I shipped a small ERC-7579 hook module, &lt;strong&gt;SpendGuardHook&lt;/strong&gt;, as a public reference for this pattern: every execution is checked pre-flight against a target allowlist and a daily spend cap that accumulates native value &lt;em&gt;and&lt;/em&gt; ERC20 &lt;code&gt;transfer&lt;/code&gt; amounts against one budget. It's tested (11/11 Foundry tests, dependency-free), and it's registered in the Rhinestone Module Registry on Sepolia — registration is permissionless, so read the listing as proof of work, not an audit. Mapped against the three leaks, honestly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Approvals:&lt;/strong&gt; &lt;em&gt;roadmap, and the demo's sharpest known gap.&lt;/em&gt; The current version counts &lt;code&gt;transfer&lt;/code&gt; amounts; approval-counting (Leak 1's fix) is the next feature, and it's deliberately the headline item — a demo that hides its gaps teaches the wrong lesson.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selectors:&lt;/strong&gt; the hook already inspects calldata at exactly the point where selector-level policy belongs (that's how it recognizes transfers). The demo ships target-level allowlisting for readability; &lt;em&gt;(target, selector)&lt;/em&gt; pairs are the production configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows:&lt;/strong&gt; the demo uses calendar-day windows — which means it has the bounded version of Leak 3 (worst case at a boundary is 2× the daily cap, never unbounded). Rolling windows are the production upgrade, and the accounting structure already supports swapping the window function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That mapping is the review method in miniature: find where value can move &lt;em&gt;without being counted&lt;/em&gt;, find where a permission is &lt;em&gt;broader than its name&lt;/em&gt;, find where &lt;em&gt;time boundaries&lt;/em&gt; multiply limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work with me
&lt;/h2&gt;

&lt;p&gt;If you're shipping session keys or agent wallets and want a second set of eyes on exactly these questions, that's the review I run — and the integration work I do after it. I offer fixed-scope &lt;strong&gt;Integration Sprints&lt;/strong&gt; ($3,500–5,000, ~2 weeks: architecture note → implementation with Foundry tests → testnet deployment → docs, milestones 30/40/30, scope in writing before any code) and &lt;strong&gt;per-module security reviews&lt;/strong&gt; (permission-leak analysis, install/uninstall safety, hook ordering, upgrade paths; written findings, severity-ranked). Also available at $125–175/hr for scoped contract work. The demo repo is public — steal ideas from it either way.&lt;/p&gt;

&lt;p&gt;— &lt;strong&gt;Av&lt;/strong&gt; · modular smart account specialist (ERC-7579 · Smart Sessions · Safe/Kernel/Nexus)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Demo + tests: SpendGuardHook (ERC-7579 hook module) · Code: &lt;a href="https://github.com/freefreaky210-dot/spend-guard-demo" rel="noopener noreferrer"&gt;github.com/freefreaky210-dot/spend-guard-demo&lt;/a&gt; · Registry listing: Rhinestone Module Registry (ERC-7484, &lt;code&gt;0x000000000069E2a187AEFFb852bF3cCdC95151B2&lt;/code&gt;), Sepolia — module &lt;a href="https://sepolia.etherscan.io/address/0x6BA337A13E5006a26Fdf5eCef76A0Ad9b9218BcD" rel="noopener noreferrer"&gt;&lt;code&gt;0x6BA337A13E5006a26Fdf5eCef76A0Ad9b9218BcD&lt;/code&gt;&lt;/a&gt;, registered 2026-10-20 (registerModule tx &lt;code&gt;0x4551b8a893c3b857687d46bc0467efa133a5d40a6c3ca491ebd6e634e1748aa2&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>solidity</category>
      <category>smartcontract</category>
      <category>security</category>
    </item>
  </channel>
</rss>
