<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0"><channel><title>ALTWEB | Blog</title><description>Signed context capsules for AI agents: verifiable, optionally encrypted markdown artifacts + an MCP loader that refuses untrusted context.</description><link>https://altweb.software/</link><language>en</language><fh:complete/><atom:link rel="self" href="https://altweb.software/blog/rss.xml"/><item><title>Your AI agent trusts any text file. That&apos;s the vulnerability.</title><link>https://altweb.software/blog/your-agent-trusts-any-text-file/</link><guid isPermaLink="true">https://altweb.software/blog/your-agent-trusts-any-text-file/</guid><description>The files that steer an AI agent are plain text with no provenance. Anything that can write them controls the agent — and post-hoc audits and opt-in checks don&apos;t fix it. Here&apos;s what does.</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;An AI agent is steered by text: a system prompt, a persona file, a set of skills, a memory store it reads back on every run. That text is treated as ground truth. Whatever the file says, the agent does.&lt;/p&gt;
&lt;p&gt;Now ask the uncomfortable question: what proves that text is what its author wrote?&lt;/p&gt;
&lt;p&gt;For almost every agent shipping today, the answer is nothing. The files are plain Markdown or JSON on a disk, in a repo, in a synced folder, in a database row. There is no author attached, no integrity check, no signature. Which means the security of your agent is exactly the security of write-access to those files — and write-access is everywhere: a rogue process, a compromised sync, a bad merge, a second tool on the same machine, a poisoned document the agent itself just ingested.&lt;/p&gt;
&lt;p&gt;One silent edit and the agent is running on someone else’s instructions. Nothing warns you, because there was never anything to verify.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;this-is-not-hypothetical&quot;&gt;This is not hypothetical&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;It already happened at scale — and the research didn’t lag behind it, it ran ahead: the mechanism was named and the fix was measured, and almost nothing in the agents shipping today changed.&lt;/p&gt;
&lt;p&gt;In early 2026, a &lt;a href=&quot;https://www.antiy.net/p/clawhavoc-analysis-of-large-scale-poisoning-campaign-targeting-the-openclaw-skill-market-for-ai-agents/&quot;&gt;coordinated campaign&lt;/a&gt; poisoned 1,184 published agent skills on a public registry — malware planted where agents go looking for capability. A &lt;a href=&quot;https://snyk.io/blog/toxicskills-malicious-ai-agent-skills-clawhub/&quot;&gt;February audit of 3,984 skills&lt;/a&gt; found that more than a third carried at least one security flaw, with 76 shipping confirmed malicious payloads. Some of those payloads wrote straight into the agent’s own memory and persona files, so the compromise survived restarts. And the scanners meant to catch this don’t: in June, &lt;a href=&quot;https://blog.trailofbits.com/2026/06/03/the-sorry-state-of-skill-distribution/&quot;&gt;Trail of Bits&lt;/a&gt; bypassed the ClawHub, Cisco, and Vercel skill detectors — three of the four techniques took under an hour to build. On August 17, OWASP published the &lt;a href=&quot;https://owasp.org/www-project-agentic-skills-top-10/&quot;&gt;Agentic Skills Top 10&lt;/a&gt; — a whole framework for a threat class that barely had a name eighteen months ago.&lt;/p&gt;
&lt;p&gt;The academic work names the mechanism precisely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://arxiv.org/abs/2512.16962&quot;&gt;MemoryGraft&lt;/a&gt;&lt;/strong&gt; (December 2025) is the clean version of the attack, and its cleverness is that it doesn’t plant instructions at all. It plants &lt;em&gt;successful experiences&lt;/em&gt; — procedure templates the agent stores as its own past wins. Later, when a similar task arrives, retrieval surfaces those grafted memories and the agent imitates them. No exploit, no CVE, nothing that reads as an instruction to a scanner. Just writing to the place the agent trusts. The paper’s own proposed countermeasure is cryptographic provenance attestation: sign validated entries, and exclude from retrieval anything that can’t be verified.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://arxiv.org/abs/2606.12703&quot;&gt;SMSR&lt;/a&gt;&lt;/strong&gt; (June 2026) measured what that’s worth. Across fifteen enterprise scenarios and 3,150 trials, adding provenance at write time cut attack success from 93–100% to zero for every unsigned variant. Without provenance, the poison lands almost every time. With it, unsigned context simply never reaches the model.&lt;/p&gt;
&lt;p&gt;Read that gap again: the difference between “owned” and “safe” was whether the context could prove where it came from.&lt;/p&gt;
&lt;p&gt;But read the rest of that paper too, because it’s the honest half. Against an adversary who holds a valid credential, provenance alone does nothing — SMSR needs an entirely separate mechanism for that case, and even then success only drops to around 8%. Signing shuts the door on strangers. It does not make a trusted signer trustworthy. Hold onto that; I’ll come back to it.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-fixes-that-dont-work&quot;&gt;The fixes that don’t work&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Once you accept the problem, two fixes suggest themselves. Both fail, and it’s worth being precise about why.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Post-hoc auditing.&lt;/strong&gt; Log everything, sign the logs, let an auditor verify later. This is real and useful — for forensics. It does nothing for the agent, because by the time anyone audits, the poisoned context already ran. You get a beautiful record of the moment you were compromised. Verification that happens after injection is not a defense; it’s a receipt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Opt-in enforcement.&lt;/strong&gt; Add a “verify signatures” flag. The problem is the default: a flag that defaults to off protects no one, and a flag that defaults to on but falls through when a file is simply unsigned protects no one either. Most real systems tolerate unsigned input “for compatibility.” That tolerance is the hole. An attacker doesn’t forge a signature — they just send you something with no signature at all, and your tolerant loader waves it through.&lt;/p&gt;
&lt;p&gt;The pattern behind both failures is the same: the check is optional, or it’s late. To actually defend an agent, verification has to be mandatory and at load time — before a single byte reaches the model.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-a-real-fix-looks-like-refuse-by-default&quot;&gt;What a real fix looks like: refuse by default&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Flip the default. The loader’s job is not “accept unless proven bad.” It’s “refuse unless proven trusted.”&lt;/p&gt;
&lt;p&gt;Concretely, the thing feeding context to your agent should return content only when three things hold at once:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the context is signed,&lt;/li&gt;
&lt;li&gt;the signature verifies against the content, and&lt;/li&gt;
&lt;li&gt;the signer’s key is one you decided to trust.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anything else — unsigned, tampered, or signed by a stranger — is refused at the door, with an explicit reason. An empty trust list rejects everything. You add trust deliberately, one key at a time. Default-deny isn’t a feature you switch on; it’s the only state the system has until you say otherwise.&lt;/p&gt;
&lt;p&gt;This is the design I built ALTWEB around.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;how-altweb-does-it&quot;&gt;How ALTWEB does it&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Two pieces.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;capsule&lt;/strong&gt; is your Markdown compiled into a single self-contained artifact — a &lt;code dir=&quot;auto&quot;&gt;.altweb.html&lt;/code&gt; file or a URL. The content is compressed, optionally encrypted (AES-256-GCM), and optionally signed (ECDSA P-256). It opens in any browser, verifies with no server, and needs no hosting. You hand someone a file, not a database. The signature travels inside the capsule, so anyone can check who signed it and that not one byte changed — offline.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;loader&lt;/strong&gt; — the &lt;code dir=&quot;auto&quot;&gt;altweb-context&lt;/code&gt; MCP server — sits between your capsules and your agent. When the agent asks for context, the loader verifies the signature and checks the signer’s key against your local trust file. On success it returns the Markdown, prefixed with the verified signer. On anything else it refuses:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;REFUSED (UNSIGNED)          no signature at all&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;REFUSED (INVALID_SIGNATURE) bytes changed since signing&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;REFUSED (UNTRUSTED_KEY)     valid signature, signer not in your trust file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Refusal is the default. An empty trust file rejects every capsule, signed or not.&lt;/p&gt;
&lt;p&gt;There’s a subtle trap even here, and it’s worth showing because it’s the kind of thing that separates a real design from a demo. When the loader returns verified content to the agent, the provenance line and the content travel as one stream of text. What stops the content from containing a fake provenance line — &lt;code dir=&quot;auto&quot;&gt;[verified — signer: Anthropic]&lt;/code&gt; — and impersonating its own chain of custody? In ALTWEB, the content is fenced between markers that embed a random nonce drawn fresh on every load. The content can’t predict the nonce, so it can’t forge a fence. Anything provenance-shaped inside the fence is data, by definition. Small detail; it’s the difference between a signature that means something and a badge anyone can paint on.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;isnt-this-just-sigstore&quot;&gt;Isn’t this just Sigstore?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Fair question — and Sigstore is genuinely excellent, so let me be precise about where it fits and where it doesn’t.&lt;/p&gt;
&lt;p&gt;Sigstore’s keyless signing binds your identity to an OIDC provider (GitHub, Google) and records every signature in a public transparency log. Both are strengths right up until they’re constraints — and ALTWEB is built for when they’re constraints: air-gapped and classified environments where verification cannot phone home, organizations that won’t federate identity to a third party, and content that has to stay confidential — signing systems attest, they don’t encrypt. A capsule verifies on a laptop with the network cable pulled, and its contents can be encrypted at rest inside the same file.&lt;/p&gt;
&lt;p&gt;Where Sigstore wins, it wins for real: revocation via short-lived certificates, and a public transparency log anyone can audit — neither of which ALTWEB has. If you sign in CI and your team lives on GitHub, use Sigstore. Different trade, not a better one; pick the one whose costs you can live with.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-a-signature-does-not-prove&quot;&gt;What a signature does not prove&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Here is where most “signed AI” pitches get quiet, so let me be loud about it.&lt;/p&gt;
&lt;p&gt;A valid signature proves two things: who authored the capsule, and that the bytes are intact. That’s it. It does not prove the content is safe, true, or wise. A trusted author can sign bad instructions; the signature will verify perfectly. This is the same limit SMSR ran into — provenance is a wall against strangers, not against a compromised insider. Provenance moves the trust decision to a human — you, via the trust file — instead of pretending the math made the content harmless.&lt;/p&gt;
&lt;p&gt;It also attests the author, not the derivation. If a memory entry was computed from earlier ones, the signature says “this signer vouches for these bytes,” not “this was derived correctly from trustworthy inputs.” That’s a real limit, and chaining provenance across derivations is genuinely unsolved — I’m not going to wave a signature at it and call it done.&lt;/p&gt;
&lt;p&gt;And there’s no revocation server, because there’s no server at all. Rotating an identity means changing the passphrase, which changes the fingerprint, and everyone who trusted you updates their trust file. That’s the cost of “nothing stored, verifiable anywhere.” I think it’s the right trade for this problem; you should know it’s a trade.&lt;/p&gt;
&lt;p&gt;If that honesty makes ALTWEB sound less magical, good. A security tool that oversells is worse than no tool, because it convinces you to stop looking.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;i-had-it-audited-before-i-called-it-safe&quot;&gt;I had it audited before I called it safe&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Before this announcement, ALTWEB went through an external security review: a full read of the source plus execution against the built artifacts, AI-assisted, with every claim checked against what the code actually did rather than what the docs said.&lt;/p&gt;
&lt;p&gt;It found real things. Content could impersonate its own provenance line. Identity derivation used a key-derivation function with weak economics against precomputed dictionaries. The signing path wasn’t reproducible, so “deterministic builds” was false for exactly the case that matters — signed ones. The fetch guard had a DNS-rebinding window between checking an address and connecting to it.&lt;/p&gt;
&lt;p&gt;Every finding is fixed in this release: the nonce fence described above, Argon2id for identity derivation, deterministic RFC 6979 signing, an SSRF guard pinned into the socket’s own DNS lookup, a strict CSP on the editor, and CI that runs typecheck, the full test suite, and the build on every push — including &lt;a href=&quot;https://github.com/danielsoimu/altweb/blob/main/packages/mcp/src/frame.test.ts&quot;&gt;eight regression tests&lt;/a&gt; aimed squarely at the provenance forgery.&lt;/p&gt;
&lt;p&gt;One recommendation I didn’t take. The review suggested a per-user salt for key derivation. I kept the salt fixed and moved to Argon2id instead: a per-user salt would double what you have to remember exactly, and memory-hardness removes the economics of a precomputed dictionary rather than merely un-sharing it. That’s a judgment call, it’s documented in the code, and you’re free to disagree with it.&lt;/p&gt;
&lt;p&gt;The commit history says all of this, in plain language, on purpose. For a tool whose entire pitch is &lt;em&gt;verify before you trust&lt;/em&gt;, the audit trail isn’t an embarrassment to hide — it’s the point.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Both tools are on npm; nothing to clone.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# verify any capsule — offline, no server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;altweb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;verify&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;page.altweb.html&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# wire the refusing loader into your agent (Claude Code shown)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;claude&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mcp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;altweb-context&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;altweb-context&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://altweb.software/quickstart/&quot;&gt;quickstart&lt;/a&gt; walks the full loop — identity, sign, verify, load. The &lt;a href=&quot;https://altweb.software/security-model/&quot;&gt;security model&lt;/a&gt; has the caveats above in full, including the encrypted-capsule and rotation details. The code is &lt;a href=&quot;https://github.com/danielsoimu/altweb&quot;&gt;AGPL on GitHub&lt;/a&gt;, with a commercial license available.&lt;/p&gt;
&lt;p&gt;Your agent will keep trusting any text file you point it at. The question is whether that text can prove it’s yours — and whether your loader is willing to say no when it can’t.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Verify before you inject.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>security</category><category>ai-agents</category><category>provenance</category></item></channel></rss>