<?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: felixpg13-glitch</title>
    <description>The latest articles on DEV Community by felixpg13-glitch (@felixpg13glitch).</description>
    <link>https://dev.to/felixpg13glitch</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%2F4103023%2Fdf8892de-cc60-48ce-abc8-998f15239c5d.png</url>
      <title>DEV Community: felixpg13-glitch</title>
      <link>https://dev.to/felixpg13glitch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/felixpg13glitch"/>
    <language>en</language>
    <item>
      <title>My AI spent $15 on a test order, so I built an open-source payment guardrail</title>
      <dc:creator>felixpg13-glitch</dc:creator>
      <pubDate>Mon, 31 Aug 2026 15:56:17 +0000</pubDate>
      <link>https://dev.to/felixpg13glitch/my-ai-spent-15-on-a-test-order-so-i-built-an-open-source-payment-guardrail-339g</link>
      <guid>https://dev.to/felixpg13glitch/my-ai-spent-15-on-a-test-order-so-i-built-an-open-source-payment-guardrail-339g</guid>
      <description>&lt;h1&gt;
  
  
  My AI spent $15 on a test order, so I built an open-source payment guardrail
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; An open-source Python + MCP library that sits between AI agents and money. Spend-capped agent identity (KYA), four deterministic gates (dry-run, budget, amount limit, human approval), prompt-injection defense, encrypted secret vault. &lt;code&gt;pip install spendshield&lt;/code&gt; — &lt;a href="https://github.com/felixpg13-glitch/spendshield" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The incident that started it
&lt;/h2&gt;

&lt;p&gt;On Aug 9, 2026, my automation system ran a "test order." I sent &lt;code&gt;dry: true&lt;/code&gt; in the body, expecting a price preview. The server only honored &lt;code&gt;?dry=1&lt;/code&gt; in the URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4 orders of ¥99 ($15) went through. Charged. Real money, gone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn't lose much — but I realized something uncomfortable: &lt;em&gt;this exact bug is about to happen everywhere, at much larger scale.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI agents are starting to order food, buy compute, call paid APIs. Every one of those is a new place where a test flag can silently fail, a budget can be exceeded, a prompt-injected agent can spend without permission.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When AI starts spending real money, who puts a gate in front of it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I turned my scar into a library.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;spendshield&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SpendShield&lt;/span&gt;

&lt;span class="n"&gt;guard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpendShield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dry_run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;whitelist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;McDonald&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@guard.protect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;call_real_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# real payment code
&lt;/span&gt;
&lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;McDonald&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; DryRunBlocked: nothing executed. dry_run is the default.
&lt;/span&gt;
&lt;span class="n"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dry_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;McDonald&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# 3rd order blocked by BudgetExceeded
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four deterministic gates — dry-run, budget, per-transaction limit, human approval — plus full audit. &lt;strong&gt;Rules are code, not AI opinion.&lt;/strong&gt; An agent cannot argue, trick, or inject its way past.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three pillars
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Identity (KYA)&lt;/strong&gt; — every agent registers with its own budget, blacklist, rate limits. &lt;em&gt;Unregistered agents are denied by default.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mcd_bot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;blacklist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown_vendor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;whitelist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;McDonald&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Intent alignment (anti prompt-injection)&lt;/strong&gt; — new recipients and large amounts &lt;em&gt;always&lt;/em&gt; require human sign-off. A prompt-injected agent trying to pay a stranger gets blocked at "human didn't approve."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Secret vault&lt;/strong&gt; — keys encrypted at rest (AES-256), master key never on disk, access gated and audited. No more "private key in a config file."&lt;/p&gt;

&lt;h2&gt;
  
  
  x402-ready
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://x402.org" rel="noopener noreferrer"&gt;x402&lt;/a&gt; is the emerging open payment protocol for the internet (HTTP 402) — how agents will pay for APIs. SpendShield already has an adapter: gate the payment &lt;em&gt;before&lt;/em&gt; it settles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;spendshield.adapters.x402&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;X402PaywallGuard&lt;/span&gt;

&lt;span class="n"&gt;pw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;X402PaywallGuard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorize_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weather-api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USDC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pay_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0x...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;x402 lets agents pay. SpendShield stops them paying recklessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  State of the project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;36 tests, identity/intent/vault/gates all covered&lt;/li&gt;
&lt;li&gt;MCP server for Claude Code / OpenClaw / any MCP client&lt;/li&gt;
&lt;li&gt;Dockerfile included&lt;/li&gt;
&lt;li&gt;MIT licensed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a 0-star project &lt;em&gt;today&lt;/em&gt;. It was built in one day, from a real scar, for a problem I'm confident is coming.&lt;/p&gt;

&lt;p&gt;If you've ever been burned by a "test order" — or you're building agents that will touch money — I'd love your feedback.&lt;/p&gt;

&lt;p&gt;⭐ &lt;a href="https://github.com/felixpg13-glitch/spendshield" rel="noopener noreferrer"&gt;GitHub: felixpg13-glitch/spendshield&lt;/a&gt;&lt;br&gt;
📦 &lt;code&gt;pip install spendshield&lt;/code&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
