<?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: AgentAvow</title>
    <description>The latest articles on DEV Community by AgentAvow (@agentavow).</description>
    <link>https://dev.to/agentavow</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%2F3834436%2F663e96af-1a1c-44fd-8467-3a247b48444d.png</url>
      <title>DEV Community: AgentAvow</title>
      <link>https://dev.to/agentavow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/agentavow"/>
    <language>en</language>
    <item>
      <title>AgentGraph is now AgentAvow</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Fri, 07 Aug 2026 23:51:35 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-is-now-agentavow-3805</link>
      <guid>https://dev.to/agentavow/agentgraph-is-now-agentavow-3805</guid>
      <description>&lt;p&gt;Quick note: we've renamed AgentGraph to &lt;strong&gt;AgentAvow&lt;/strong&gt; (agentavow.com). Same team, same product, sharper focus: signed, verifiable safety grades for the tools your AI agents connect to (MCP servers, packages, skills). Paste a URL, get a letter grade backed by a scan across 12 safety categories, plus a signed attestation anyone can recompute offline.&lt;/p&gt;

&lt;p&gt;The public verification is unchanged: the attestation format, the CTEF namespace, and the JWKS are all the same, so your existing badges and receipts keep working, and agentgraph.co redirects to agentavow.com.&lt;/p&gt;

&lt;p&gt;Check a tool: &lt;a href="https://agentavow.com/check" rel="noopener noreferrer"&gt;https://agentavow.com/check&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How We Built Verifiable Agent Identity with DIDs — and Why the Moltbook Breach Should Scare You</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 06 Aug 2026 01:11:16 +0000</pubDate>
      <link>https://dev.to/agentavow/how-we-built-verifiable-agent-identity-with-dids-and-why-the-moltbook-breach-should-scare-you-2kd2</link>
      <guid>https://dev.to/agentavow/how-we-built-verifiable-agent-identity-with-dids-and-why-the-moltbook-breach-should-scare-you-2kd2</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; AI agent platforms without identity verification are a security disaster waiting to happen — and the Moltbook breach proved it. AgentGraph uses W3C Decentralized Identifiers (DIDs) to give every agent a cryptographic identity that's auditable, on-chain, and not owned by any single platform. Here's how we built it and what we got wrong along the way.&lt;/p&gt;




&lt;p&gt;The Moltbook breach hit 35,000 emails and 1.5 million API tokens. 770,000 agents, zero identity verification. Meta acquired the platform, the breach happened, and suddenly every developer who had integrated Moltbook agents into their pipelines had to assume those agents were compromised. No audit trail. No way to know which agents had been tampered with. No cryptographic proof of anything.&lt;/p&gt;

&lt;p&gt;That's the actual problem we're solving at &lt;a href="https://agentgraph.co/?utm_source=agentgraph_bot&amp;amp;utm_medium=devto&amp;amp;utm_campaign=security" rel="noopener noreferrer"&gt;AgentGraph&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenClaw has 512 CVEs and 12% of their skills marketplace has been flagged as malware. These aren't edge cases — they're what happens when you build agent infrastructure without identity as a first-class concern.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Agent Identity Is Different From User Identity
&lt;/h2&gt;

&lt;p&gt;OAuth solves identity for humans. JWT handles session auth. X.509 certificates work for servers. None of these map cleanly to agents.&lt;/p&gt;

&lt;p&gt;An agent isn't a user. It acts autonomously, often across multiple sessions, sometimes spawning sub-agents, sometimes being cloned or forked by other operators. The identity model needs to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Persistence across sessions&lt;/strong&gt; — the agent's identity shouldn't be tied to a single API session or runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegation&lt;/strong&gt; — agent A can authorize agent B to act on its behalf, and that delegation needs to be verifiable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evolution&lt;/strong&gt; — an agent that gets new capabilities, a new model, or a new system prompt is still "the same agent" in some meaningful sense, but that change should be auditable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt; — identity shouldn't be locked to one platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;W3C DIDs solve most of this. A DID is a globally unique identifier that resolves to a DID document containing public keys, service endpoints, and verification methods. The identifier itself is controlled by whoever holds the private key — not by a registry, not by a platform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;did:agentgraph:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's what an agent identity looks like on AgentGraph. The &lt;code&gt;did:agentgraph&lt;/code&gt; method stores the DID document on-chain, which means resolution doesn't go through our servers. If we disappear tomorrow, your agent's identity still resolves.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Here's the high-level flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Agent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Operator&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;▼&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;AgentGraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;SDK&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Generates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;keypair&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(Ed&lt;/span&gt;&lt;span class="mi"&gt;25519&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Creates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;DID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;document&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Anchors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;chain&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Returns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;DID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;verification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;material&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;▼&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;DID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(on-chain)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://www.w3.org/ns/did/v1"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:agentgraph:z6Mkha..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"verificationMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:agentgraph:z6Mkha...#key-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ed25519VerificationKey2020"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"controller"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:agentgraph:z6Mkha..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"publicKeyMultibase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"z6Mkha..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:agentgraph:z6Mkha...#agentgraph"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AgentGraphProfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"serviceEndpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://agentgraph.co/agents/z6Mkha..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When agent A wants to verify it's talking to agent B, it resolves B's DID, gets the public key from the DID document, and checks that B's messages are signed with the corresponding private key. No central authority involved. No "trust us, we verified them."&lt;/p&gt;




&lt;h2&gt;
  
  
  Registering an Agent: The SDK Flow
&lt;/h2&gt;

&lt;p&gt;Here's what registration looks like using the AgentGraph SDK:&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;agentgraph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AgentGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AgentConfig&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize the client
&lt;/span&gt;&lt;span class="n"&gt;ag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Register a new agent with a verifiable identity
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;AgentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data-pipeline-agent-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processes and validates financial data streams&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;capabilities&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;data-processing&lt;/span&gt;&lt;span class="sh"&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;validation&lt;/span&gt;&lt;span class="sh"&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;reporting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;operator_did&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;did:agentgraph:z6MkOperator...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# your DID as operator
&lt;/span&gt;        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.1.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;did&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# did:agentgraph:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trust_score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 72  (starts lower, increases with verified activity)
&lt;/span&gt;
&lt;span class="c1"&gt;# Sign a message as this agent
&lt;/span&gt;&lt;span class="n"&gt;signed_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&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;process_batch&lt;/span&gt;&lt;span class="sh"&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;batch_id&lt;/span&gt;&lt;span class="sh"&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;batch-20260318-001&lt;/span&gt;&lt;span class="sh"&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;timestamp&lt;/span&gt;&lt;span class="sh"&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;2026-03-18T09:00:00Z&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Another agent verifying that signature
&lt;/span&gt;&lt;span class="n"&gt;verification_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;did&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;did:agentgraph:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signed_message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signed_message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verification_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verification_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trust_score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 72
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verification_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;audit_trail_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Link to on-chain history
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;operator_did&lt;/code&gt; field is where the human accountability chain starts. Every agent is registered by an operator, and that operator has their own DID. If an agent goes rogue, you can trace back to the operator who deployed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Trust Score: What It Actually Measures
&lt;/h2&gt;

&lt;p&gt;Trust scores are the part we've thought hardest about and gotten wrong in interesting ways.&lt;/p&gt;

&lt;p&gt;The score (0-100) is a composite of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity verification depth&lt;/strong&gt; — just a DID, or DID + operator verification + source repo?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavioral consistency&lt;/strong&gt; — does the agent do what its DID document claims it does?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit trail length&lt;/strong&gt; — how much verifiable history exists?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operator reputation&lt;/strong&gt; — what's the trust score of the humans/orgs behind this agent?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capability attestations&lt;/strong&gt; — third-party verification of claimed capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we got wrong in v1: we weighted "age" too heavily. An agent that had been around for six months got a big trust boost just from longevity. That's wrong. A malicious agent that's been operating quietly for six months is more dangerous, not more trustworthy. We now weight behavioral consistency against claimed capabilities much more heavily.&lt;/p&gt;

&lt;p&gt;The other thing we got wrong: we tried to make the score opaque, like a credit score. Developers hated it. Now every component is visible in the API response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"did"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:agentgraph:z6Mkha..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trust_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"identity_depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"behavioral_consistency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"audit_trail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"operator_reputation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"capability_attestations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"last_updated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-03-18T08:45:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audit_trail_entries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;147&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Audit Trail Problem
&lt;/h2&gt;

&lt;p&gt;Every change to an agent's capabilities, model, or system prompt gets recorded as an on-chain event. This is the "evolution trail" — the idea that you can see exactly how an agent has changed over time.&lt;/p&gt;

&lt;p&gt;This matters because the Moltbook-style attack vector isn't just "steal credentials." It's "quietly modify an agent's behavior and wait." If you can't see that an agent's system prompt changed three weeks ago, you can't detect that attack.&lt;/p&gt;

&lt;p&gt;The trade-off here is cost. On-chain writes aren't free. We batch non-critical updates and only write immediately for security-relevant changes (new keys, capability additions, operator changes). Minor version bumps get batched into daily writes. It's a compromise — a sophisticated attacker could theoretically modify an agent and wait for the batch window. We're honest about that.&lt;/p&gt;

&lt;p&gt;The alternative was keeping the audit trail off-chain in our database. Faster, cheaper, but then you're trusting us. For a trust infrastructure platform, that's a bad look.&lt;/p&gt;




&lt;h2&gt;
  
  
  MCP Bridge and Tool Discovery
&lt;/h2&gt;

&lt;p&gt;Agents don't just have identities — they use tools. The Model Context Protocol is becoming the standard way agents discover and call tools, and we've built a bridge that integrates DID-based identity into that flow.&lt;/p&gt;

&lt;p&gt;When an agent discovers a tool through AgentGraph's MCP bridge, it gets the tool's DID, trust score, and audit trail alongside the normal MCP response. Before calling an untrusted tool, the agent can check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this tool's DID document valid and resolvable?&lt;/li&gt;
&lt;li&gt;What's the trust score?&lt;/li&gt;
&lt;li&gt;Has this tool's behavior changed recently in unexpected ways?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also open-sourced &lt;a href="https://github.com/agentgraph-co/mcp-security-scan" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-security-scan&lt;/code&gt;&lt;/a&gt; — a CLI and GitHub Action that scans MCP servers for credential theft vectors, data exfiltration patterns, unsafe execution, filesystem access, and code obfuscation. It outputs a trust score that integrates directly with AgentGraph trust badges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Scan an MCP server before integrating it&lt;/span&gt;
npx mcp-security-scan scan &lt;span class="nt"&gt;--server&lt;/span&gt; https://mcp.example.com/tools

&lt;span class="c"&gt;# Output:&lt;/span&gt;
&lt;span class="c"&gt;# Trust Score: 67/100&lt;/span&gt;
&lt;span class="c"&gt;# ⚠️  Filesystem access detected (read: /tmp, write: none)&lt;/span&gt;
&lt;span class="c"&gt;# ✅  No credential theft patterns found&lt;/span&gt;
&lt;span class="c"&gt;# ✅  No data exfiltration vectors detected&lt;/span&gt;
&lt;span class="c"&gt;# ⚠️  One obfuscated code block in tool handler&lt;/span&gt;
&lt;span class="c"&gt;# &lt;/span&gt;
&lt;span class="c"&gt;# Full report: https://agentgraph.co/scan/abc123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GitHub Action version runs in CI so you catch problems before deployment. It's MIT licensed because the goal is for this to become standard practice, not to lock anyone in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why On-Chain and Not Just a Database?
&lt;/h2&gt;

&lt;p&gt;This is the question we get most often.&lt;/p&gt;

&lt;p&gt;The honest answer: on-chain is slower, more expensive, and more complex to operate. We chose it anyway because the alternative — a database we control — creates a single point of failure and a single point of trust. If our database gets breached (see: Moltbook), all the identity records are compromised. If we get acquired and the acquirer has different incentives, the identity records can be modified.&lt;/p&gt;

&lt;p&gt;On-chain means the DID documents are verifiable without going through our infrastructure. An agent can resolve another agent's DID using any DID resolver that supports the &lt;code&gt;did:agentgraph&lt;/code&gt; method. We're not in the critical path for verification.&lt;/p&gt;

&lt;p&gt;The cost is real though. We absorb chain write costs for registered agents and pass them through at scale. It adds latency to registration (seconds, not milliseconds). For high-frequency updates, it's genuinely limiting.&lt;/p&gt;

&lt;p&gt;Some things we keep off-chain: the social graph visualization, detailed behavioral logs, the marketplace listings. Those live in a database. The cryptographic roots — keys, capability hashes, operator relationships — go on-chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Healthcare and Finance Verticals Are Teaching Us
&lt;/h2&gt;

&lt;p&gt;A few teams building AI agents for healthcare have started using AgentGraph, and they've pushed us hard on one thing we hadn't fully thought through: &lt;strong&gt;agent delegation chains&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A healthcare agent might be: deployed by a hospital (operator), configured by a department (sub-operator), and used by a specific doctor (end user). The liability chain matters. When the agent makes a recommendation, who is cryptographically accountable?&lt;/p&gt;

&lt;p&gt;We're building delegation proofs into the DID document structure — verifiable credentials that capture the full chain from operator to end user. It's not shipped yet. But the requirement is real and the W3C Verifiable Credentials spec gives us the building blocks.&lt;/p&gt;

&lt;p&gt;The finance teams have a different problem: they need to prove to auditors that the agent that ran a transaction in January is the same agent (or provably different) from the one running transactions now. The audit trail solves this, but only if the auditors can read it. We're working on a human-readable audit report export that doesn't require understanding DIDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you're building agents and you're not thinking about identity yet, the Moltbook breach is the argument. 1.5 million API tokens exposed because there was no cryptographic link between agents and their operators.&lt;/p&gt;

&lt;p&gt;AgentGraph is live and free to register. You get a DID for your agent, a trust score, and access to the API and marketplace. The SDK supports Python and TypeScript, with more coming.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mcp-security-scan&lt;/code&gt; tool is a good starting point even if you're not ready to commit to the full platform — run it against any MCP servers you're integrating and see what comes back.&lt;/p&gt;

&lt;p&gt;Full docs, API reference, and early access registration are at &lt;a href="https://agentgraph.co/?utm_source=agentgraph_bot&amp;amp;utm_medium=devto&amp;amp;utm_campaign=security" rel="noopener noreferrer"&gt;agentgraph.co&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: This post was generated with AI assistance and reviewed by the AgentGraph team. We think transparency about that is table stakes for a company whose whole thing is trust.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Audit Your MCP Servers for Security Risks</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 30 Jul 2026 00:15:25 +0000</pubDate>
      <link>https://dev.to/agentavow/how-to-audit-your-mcp-servers-for-security-risks-5e8a</link>
      <guid>https://dev.to/agentavow/how-to-audit-your-mcp-servers-for-security-risks-5e8a</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; MCP servers run with significant privileges inside AI agent pipelines, and most teams ship them without any security review. &lt;code&gt;mcp-security-scan&lt;/code&gt; is an open-source CLI and GitHub Action that checks for credential theft patterns, data exfiltration, unsafe execution, and code obfuscation — and outputs a 0-100 trust score that integrates with AgentGraph's identity layer.&lt;/p&gt;




&lt;p&gt;The Moltbook breach last year is still the clearest example of what happens when you scale agent infrastructure without thinking about trust. 770,000 agents, zero identity verification, and when it went down it exposed 35,000 emails and 1.5 million API tokens. The tokens were the real problem — many of them were credentials passed through MCP servers that nobody had audited.&lt;/p&gt;

&lt;p&gt;MCP (Model Context Protocol) servers are the connective tissue of modern agent systems. They sit between your LLM and the outside world, handling tool calls, filesystem access, API requests. That position gives them a lot of power. It also makes them an obvious target.&lt;/p&gt;

&lt;p&gt;And yet most teams treat MCP servers like they treat npm packages circa 2015: install and trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Goes Wrong
&lt;/h2&gt;

&lt;p&gt;Before getting into the scanner, it's worth being specific about the threat categories. There are four that show up most often in real codebases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credential theft&lt;/strong&gt; — MCP servers that read environment variables indiscriminately, log request/response payloads, or forward tool call arguments to external endpoints. This one is subtle because the server might be doing legitimate work &lt;em&gt;and&lt;/em&gt; exfiltrating credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data exfiltration&lt;/strong&gt; — Outbound HTTP calls to domains that weren't declared in the server's manifest, or calls that happen inside tool handlers where the LLM can influence the destination URL. Prompt injection into tool parameters is the attack vector here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unsafe execution&lt;/strong&gt; — &lt;code&gt;eval()&lt;/code&gt;, &lt;code&gt;exec()&lt;/code&gt;, &lt;code&gt;subprocess&lt;/code&gt; calls, or dynamic &lt;code&gt;require()&lt;/code&gt;/&lt;code&gt;import()&lt;/code&gt; where the argument comes from tool call input. If an LLM can influence what gets executed, you have a problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filesystem access&lt;/strong&gt; — Path traversal risks, reading outside declared directories, writing to sensitive locations. Especially bad in servers that accept filename parameters from the model.&lt;/p&gt;

&lt;p&gt;OpenClaw's skills marketplace has 512 CVEs at last count, and roughly 12% of skills contain what their own security team classifies as malware. That's a marketplace that grew fast and audited slowly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing &lt;code&gt;mcp-security-scan&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mcp-security-scan&lt;/code&gt; is a CLI tool and GitHub Action for scanning MCP server source code and runtime behavior. It's MIT licensed, lives at &lt;a href="https://github.com/agentgraph-co/mcp-security-scan" rel="noopener noreferrer"&gt;github.com/agentgraph-co/mcp-security-scan&lt;/a&gt;, and produces a structured JSON report plus a 0-100 trust score.&lt;/p&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; mcp-security-scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basic scan against a local server directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mcp-security-scan scan ./my-mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;74&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"findings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HIGH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"credential_theft"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"env-wildcard-read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/tools/search.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"process.env spread into tool response object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"snippet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"return { ...process.env, results }"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MEDIUM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unsafe_execution"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dynamic-require"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"require() called with non-literal argument"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"snippet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"const mod = require(toolName)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"passed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agentgraph_trust_badge"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://agentgraph.co/badge/mcp/..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The score drops from 100 based on finding severity: HIGH findings cost 15 points each, MEDIUM costs 5, LOW costs 1. That's configurable via a &lt;code&gt;.mcp-scan.json&lt;/code&gt; file if your threat model weights things differently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Running It in CI
&lt;/h2&gt;

&lt;p&gt;The GitHub Action is the more useful integration for teams that ship MCP servers regularly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MCP Security Scan&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scan MCP Server&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentgraph-co/mcp-security-scan@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./server&lt;/span&gt;
          &lt;span class="na"&gt;fail-on-severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HIGH&lt;/span&gt;
          &lt;span class="na"&gt;min-score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;
          &lt;span class="na"&gt;agentgraph-api-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AGENTGRAPH_API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;agentgraph-api-key&lt;/code&gt; is optional. Without it, you get the local scan results. With it, the score gets pushed to your agent's trust profile on &lt;a href="https://agentgraph.co/?utm_source=agentgraph_bot&amp;amp;utm_medium=devto&amp;amp;utm_campaign=security_scanner" rel="noopener noreferrer"&gt;AgentGraph&lt;/a&gt;, and your README badge updates automatically after each passing scan.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fail-on-severity: HIGH&lt;/code&gt; will exit with code 1 on any HIGH finding, blocking the PR merge. &lt;code&gt;min-score: 70&lt;/code&gt; does the same if the aggregate score drops below threshold. You can use one, both, or neither depending on how strict you want to be.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Scanner Works
&lt;/h2&gt;

&lt;p&gt;The scan runs in two phases: static analysis and (optionally) dynamic analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static Analysis
&lt;/h3&gt;

&lt;p&gt;Static analysis uses AST parsing via &lt;code&gt;@typescript-eslint/parser&lt;/code&gt; for TypeScript/JavaScript servers and &lt;code&gt;ast&lt;/code&gt; module for Python servers. The rules are pattern-based, not ML-based. That was a deliberate call.&lt;/p&gt;

&lt;p&gt;ML-based detection would catch more subtle patterns, but it would also produce false positives that developers learn to ignore. A rule that says "flag &lt;code&gt;process.env&lt;/code&gt; spread into any object that gets returned from a tool handler" is specific, auditable, and easy to suppress with a comment when you have a legitimate reason.&lt;/p&gt;

&lt;p&gt;Every rule has a rule ID, a description, and a link to the rationale. If a finding doesn't make sense for your codebase, you suppress it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mcp-scan-disable-next-line env-wildcard-read&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That suppression gets logged in the report so reviewers can see what was intentionally skipped.&lt;/p&gt;

&lt;p&gt;Current rule count: 34 rules across the four categories. The full list is in the repo's &lt;code&gt;docs/rules.md&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Analysis
&lt;/h3&gt;

&lt;p&gt;Dynamic analysis is opt-in and requires Docker. It spins up the MCP server in a sandboxed container with network monitoring enabled, runs a set of synthetic tool calls, and records outbound connections.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mcp-security-scan scan ./my-mcp-server &lt;span class="nt"&gt;--dynamic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This catches things static analysis misses: obfuscated code that decodes at runtime, dependencies that phone home, servers that behave differently under specific input patterns.&lt;/p&gt;

&lt;p&gt;The trade-off is obvious: it's slower (adds 30-90 seconds depending on server startup time), requires Docker, and can't catch everything — a server could behave differently with real LLM-generated inputs than with synthetic ones. But it catches the low-hanging fruit reliably.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Trust Score
&lt;/h3&gt;

&lt;p&gt;The 0-100 score is designed to integrate with AgentGraph's trust infrastructure. AgentGraph assigns W3C DIDs to AI agents and maintains auditable trust scores based on verifiable signals — scan results, deployment history, operator reputation. The scanner is one input into that system.&lt;/p&gt;

&lt;p&gt;When you push scan results via the API key, they get recorded on-chain as part of the agent's evolution trail. That means you can show users of your MCP server a verifiable history of security scans, not just a static badge that could be faked.&lt;/p&gt;

&lt;p&gt;This is the piece that distinguishes it from running ESLint with some custom rules. ESLint output lives in your CI logs. The trust score lives in a verifiable record that third parties can check before deciding whether to use your server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Decisions and What We Got Wrong
&lt;/h2&gt;

&lt;p&gt;A few honest notes on choices that didn't go perfectly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The scoring formula is too simple.&lt;/strong&gt; Flat point deductions per severity don't capture the difference between a HIGH finding in a core authentication handler versus a HIGH finding in a rarely-called utility function. We're working on a weighted scoring model that factors in code path reachability. The current version errs toward simplicity — a score you can explain beats a score that's accurate but opaque.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python support is incomplete.&lt;/strong&gt; The TypeScript/JavaScript rules are more mature. Python servers get about 60% of the rule coverage. If you're building Python MCP servers, the scanner will still catch the most common issues, but don't treat a passing score as a clean bill of health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic analysis doesn't handle auth flows well.&lt;/strong&gt; If your MCP server requires OAuth or API key setup before it will respond to tool calls, the dynamic scanner will time out waiting for initialization. There's a &lt;code&gt;--dynamic-init-script&lt;/code&gt; flag that lets you provide a setup script, but it's clunky. This is on the roadmap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The false positive rate on obfuscation detection is ~8%.&lt;/strong&gt; Some legitimate minification patterns trigger the obfuscation rules. The fix is usually adding the file to &lt;code&gt;.mcp-scan-ignore&lt;/code&gt;, but it's annoying when it hits a vendored dependency you can't control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Integrating with AgentGraph Trust Badges
&lt;/h2&gt;

&lt;p&gt;If you're publishing an MCP server publicly — on npm, GitHub, or through a marketplace — the trust badge is the user-facing output of all this.&lt;/p&gt;

&lt;p&gt;After your first successful scan with an API key, you get a badge URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;![MCP Security Score&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://agentgraph.co/badge/mcp/your-server-id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;](https://agentgraph.co/agent/your-server-id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The badge shows the current score and links to the full scan history. It updates after each scan that pushes results to the API. If a scan fails or the score drops below 70, the badge goes red.&lt;/p&gt;

&lt;p&gt;This is the same trust infrastructure that AgentGraph uses for AI agents more broadly — verifiable DIDs, on-chain audit trails, social graph trust scoring. The scanner is a way into that system for teams who build tooling rather than agents directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Doesn't Catch
&lt;/h2&gt;

&lt;p&gt;Being clear about limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supply chain attacks in dependencies.&lt;/strong&gt; The scanner checks your code, not your &lt;code&gt;node_modules&lt;/code&gt;. Use something like &lt;code&gt;socket.dev&lt;/code&gt; or &lt;code&gt;npm audit&lt;/code&gt; alongside it for dependency scanning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logic-level vulnerabilities.&lt;/strong&gt; If your server correctly implements a tool that does something dangerous by design, the scanner won't flag it. It checks implementation patterns, not intent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime prompt injection.&lt;/strong&gt; The dynamic analysis catches some injection patterns, but a sophisticated attack that only triggers under specific LLM-generated inputs won't show up in synthetic testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration security.&lt;/strong&gt; How you deploy the server, what permissions it runs with, network policies — none of that is in scope.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it as one layer in a defense-in-depth approach, not a complete security solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; mcp-security-scan

&lt;span class="c"&gt;# Scan a local server&lt;/span&gt;
mcp-security-scan scan ./path/to/server

&lt;span class="c"&gt;# Scan with dynamic analysis&lt;/span&gt;
mcp-security-scan scan ./path/to/server &lt;span class="nt"&gt;--dynamic&lt;/span&gt;

&lt;span class="c"&gt;# Output JSON for CI integration&lt;/span&gt;
mcp-security-scan scan ./path/to/server &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;--output&lt;/span&gt; report.json

&lt;span class="c"&gt;# Check a specific rule&lt;/span&gt;
mcp-security-scan rules list
mcp-security-scan rules explain env-wildcard-read
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full documentation is in the repo. Issues and PRs are open — the rule set in particular benefits from real-world examples of patterns people have seen in the wild.&lt;/p&gt;




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

&lt;p&gt;MCP servers are infrastructure. They deserve the same security review you'd give any other piece of infrastructure that touches credentials and runs code on behalf of users. Most teams aren't doing that review today because there wasn't a fast, automated way to do it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mcp-security-scan&lt;/code&gt; is the starting point. It won't catch everything, and the trust score is a signal, not a guarantee. But a score of 45 with three HIGH findings is a concrete thing you can act on before shipping.&lt;/p&gt;

&lt;p&gt;The broader project — verifiable agent identity, auditable trust trails, a trust layer that scales across the agent ecosystem — is what &lt;a href="https://agentgraph.co/?utm_source=agentgraph_bot&amp;amp;utm_medium=devto&amp;amp;utm_campaign=security_scanner" rel="noopener noreferrer"&gt;AgentGraph&lt;/a&gt; is building. The scanner is how a lot of developers find their way into it.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/agentgraph-co/mcp-security-scan" rel="noopener noreferrer"&gt;github.com/agentgraph-co/mcp-security-scan&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This post was generated with AI assistance as part of AgentGraph's content pipeline. The technical details reflect the actual tool's behavior.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Audit Your MCP Servers for Security Risks</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 16 Jul 2026 17:49:54 +0000</pubDate>
      <link>https://dev.to/agentavow/how-to-audit-your-mcp-servers-for-security-risks-4keh</link>
      <guid>https://dev.to/agentavow/how-to-audit-your-mcp-servers-for-security-risks-4keh</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; MCP servers run with surprising access to your filesystem, environment variables, and network — and most developers ship them without any security review. &lt;code&gt;mcp-security-scan&lt;/code&gt; is an open-source CLI and GitHub Action that checks for credential theft, data exfiltration, and unsafe execution patterns, outputting a 0-100 trust score. It's free, MIT-licensed, and takes about 30 seconds to run.&lt;/p&gt;




&lt;p&gt;If you've wired up an MCP server to Claude or another agent runtime, you've probably not thought too hard about what that server can actually do. That's normal. You were focused on getting the tool calls working.&lt;/p&gt;

&lt;p&gt;But MCP servers run in a privileged position. They sit between your agent and the outside world, and they can read files, make network requests, spawn subprocesses, and access environment variables. The Model Context Protocol spec doesn't define a security model — it defines a communication protocol. What happens inside your server is entirely up to you.&lt;/p&gt;

&lt;p&gt;That gap is where &lt;code&gt;mcp-security-scan&lt;/code&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the scanner actually checks
&lt;/h2&gt;

&lt;p&gt;The tool runs static analysis on your MCP server source code (TypeScript, Python, and JavaScript supported) and looks for six categories of risk:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credential theft patterns&lt;/strong&gt; — environment variable reads that touch anything matching &lt;code&gt;*_KEY&lt;/code&gt;, &lt;code&gt;*_SECRET&lt;/code&gt;, &lt;code&gt;*_TOKEN&lt;/code&gt;, &lt;code&gt;*_PASSWORD&lt;/code&gt;, or &lt;code&gt;*_CREDENTIAL&lt;/code&gt;. Not all of these are bugs, but they should be visible. If your weather tool is reading &lt;code&gt;STRIPE_SECRET_KEY&lt;/code&gt;, that's worth knowing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data exfiltration&lt;/strong&gt; — outbound HTTP calls from inside tool handlers. Again, not inherently bad. But a tool that's supposed to format a string shouldn't be POSTing to an external endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unsafe execution&lt;/strong&gt; — &lt;code&gt;exec()&lt;/code&gt;, &lt;code&gt;eval()&lt;/code&gt;, &lt;code&gt;subprocess.run()&lt;/code&gt;, &lt;code&gt;child_process.spawn()&lt;/code&gt;, and similar. These are the ones that keep security people up at night. An MCP tool that eval's user-supplied input is a remote code execution waiting to happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filesystem access&lt;/strong&gt; — reads and writes outside the working directory. Particularly dangerous when the agent is passing file paths that come from user input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code obfuscation&lt;/strong&gt; — high-entropy strings, base64-encoded payloads, minified code shipped without source maps. These aren't automatically malicious, but they're a signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency confusion risks&lt;/strong&gt; — package names that shadow popular packages, or dependencies pulled from unusual registries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @agentgraph/mcp-security-scan ./my-mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or install globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @agentgraph/mcp-security-scan
mcp-security-scan ./my-mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python projects work the same way — the scanner detects the runtime from &lt;code&gt;package.json&lt;/code&gt; or &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Output looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AgentGraph MCP Security Scanner v0.4.1
Scanning: ./my-mcp-server

[PASS] No credential theft patterns detected
[WARN] 3 outbound HTTP calls in tool handlers (lines 47, 112, 203)
[FAIL] eval() usage detected in tools/execute.ts (line 89)
[WARN] Filesystem read outside working directory (tools/reader.ts, line 34)
[PASS] No obfuscated code detected
[PASS] Dependencies look clean

Trust Score: 61/100

Issues requiring attention:
  HIGH   eval() in tool handler — potential RCE vector
  MEDIUM Filesystem traversal — validate paths before use
  LOW    Outbound HTTP in 3 handlers — document or restrict

Run with --json for machine-readable output
Run with --fix for suggested remediations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trust score integrates directly with &lt;a href="https://agentgraph.co/?utm_source=agentgraph_bot&amp;amp;utm_medium=devto&amp;amp;utm_campaign=security_scanner" rel="noopener noreferrer"&gt;AgentGraph&lt;/a&gt;'s trust badge system, so if you're publishing an MCP server for others to use, you can attach a verified score to your README.&lt;/p&gt;

&lt;h2&gt;
  
  
  The GitHub Action
&lt;/h2&gt;

&lt;p&gt;Drop this in &lt;code&gt;.github/workflows/security.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MCP Security Scan&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run MCP Security Scan&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentgraph-co/mcp-security-scan@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
          &lt;span class="na"&gt;fail-below&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;
          &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sarif&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload SARIF results&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github/codeql-action/upload-sarif@v3&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always()&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;sarif_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mcp-security-scan.sarif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;fail-below&lt;/code&gt; threshold is configurable. We default to 70 for most projects — below that, you have at least one HIGH or several MEDIUMs that haven't been addressed. The SARIF output means findings show up natively in GitHub's Security tab, which is useful if you're already using CodeQL or similar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture decisions (and what we got wrong)
&lt;/h2&gt;

&lt;p&gt;Building a security scanner for something as loosely-defined as MCP servers involved some choices worth being upfront about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static analysis vs. dynamic analysis.&lt;/strong&gt; We chose static. Dynamic analysis would catch more — you'd actually run the server and observe its behavior. But it's dramatically harder to do safely. Running arbitrary MCP server code in a sandbox to observe what it does is the kind of thing that requires real infrastructure. Static analysis misses obfuscated runtime behavior, but it's fast, safe, and works in CI without any special setup.&lt;/p&gt;

&lt;p&gt;The trade-off: a sufficiently motivated bad actor can evade static analysis. If someone really wants to hide malicious behavior, they'll encode it in a way that pattern-matching won't catch. We know this. The scanner isn't a guarantee — it's a baseline that catches the obvious stuff and raises the cost of shipping something obviously dangerous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regex vs. AST parsing.&lt;/strong&gt; For the first version, we used regex patterns for Python and a lightweight AST walk for TypeScript/JavaScript. Regex is fast and easy to maintain, but it produces false positives. A comment that says &lt;code&gt;# don't use eval()&lt;/code&gt; will still trigger the eval check. We're migrating the Python analyzer to use &lt;code&gt;ast&lt;/code&gt; module parsing in v0.5, which will cut false positives significantly.&lt;/p&gt;

&lt;p&gt;This is the thing about security tooling: false positives erode trust in the tool itself. If developers learn to ignore the warnings, the scanner becomes noise. We'd rather have fewer, higher-confidence findings than comprehensive but noisy output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trust score math.&lt;/strong&gt; The 0-100 score is a weighted sum. HIGH findings cost 25 points each (capped at 2), MEDIUM findings cost 10 points each (capped at 3), LOW findings cost 3 points each. Starting from 100, you can floor at 0 but not go negative. This is... fine. It's not a sophisticated risk model. But it produces numbers that feel intuitively right for the cases we tested, and it's transparent enough that developers can understand why their score is what it is.&lt;/p&gt;

&lt;p&gt;We considered a more sophisticated model — CVSS-style scoring with exploitability and impact dimensions. We decided against it for v1 because the complexity wasn't justified by the signal quality of static analysis. When you're doing AST pattern matching, you don't actually know if that &lt;code&gt;eval()&lt;/code&gt; call is reachable from a tool handler or buried in dead code. Pretending you have CVSS-level precision would be misleading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why MCP security is messier than it looks
&lt;/h2&gt;

&lt;p&gt;The Moltbook breach earlier this year exposed 1.5 million API tokens. That incident wasn't an MCP-specific attack, but the attack surface is similar: a platform that aggregates agent tools and credentials, with insufficient verification of what those tools actually do.&lt;/p&gt;

&lt;p&gt;OpenClaw's skills marketplace had 12% of submissions flagged for malware in their last public audit. That's not a rounding error. That's one in eight tools doing something it shouldn't.&lt;/p&gt;

&lt;p&gt;The problem is that MCP servers are easy to write and increasingly easy to publish. The friction between "I built a thing" and "other people's agents are running my thing" is very low. That's good for the ecosystem's growth. It's bad for security.&lt;/p&gt;

&lt;p&gt;The Traceforce launch on HN this week (company-wide security monitoring for AI apps) is hitting the same problem from the enterprise end. They're watching what AI apps do at runtime. We're catching issues before deployment. Both approaches are necessary — the question of "is this agent doing what it claims to do" doesn't have a single answer at a single layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the API for custom integrations
&lt;/h2&gt;

&lt;p&gt;If you want to integrate the scanner into something beyond a standard CI pipeline, there's a REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MCPSecurityScanner&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@agentgraph/mcp-security-scan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scanner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MCPSecurityScanner&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AGENTGRAPH_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// optional — enables trust badge publishing&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;failBelow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;checks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;credentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exfiltration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;execution&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;filesystem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.test.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-mcp-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Trust Score: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trustScore&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Findings: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finding&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;finding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;finding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;finding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;finding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Publish to AgentGraph trust registry (requires API key)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trustScore&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;badge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publishTrustBadge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Badge URL: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;badge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Embed in README: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;badge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API key is only needed if you want to publish results to the AgentGraph trust registry and get a verified badge for your README. Scanning itself is entirely local — nothing leaves your machine without the API key configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the scanner won't catch
&lt;/h2&gt;

&lt;p&gt;Being honest about limitations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtime behavior.&lt;/strong&gt; If your server loads a malicious plugin at runtime from a URL that isn't in the source code, static analysis won't see it. This is a known gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic bugs.&lt;/strong&gt; The scanner doesn't understand what your tool is supposed to do. If your tool is supposed to read files and it reads files, that's a WARN, not a FAIL — even if the specific files it reads are sensitive. You need a human to evaluate whether the behavior is appropriate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supply chain attacks in dependencies.&lt;/strong&gt; We check package names for obvious confusion attacks, but we don't run a full audit of your dependency tree. Use &lt;code&gt;npm audit&lt;/code&gt; or &lt;code&gt;pip-audit&lt;/code&gt; for that — they're better tools for that specific job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obfuscated malice.&lt;/strong&gt; A determined attacker who encodes their payload in a way that looks like a base64 config string will probably get through. We flag high-entropy strings, but the false positive rate on that check is high enough that many projects will tune it down.&lt;/p&gt;

&lt;p&gt;The scanner is a floor, not a ceiling. It catches the stuff that shouldn't be there at all — the &lt;code&gt;eval()&lt;/code&gt; calls, the credential reads in tools that don't need credentials, the outbound HTTP calls that weren't in the README.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a trust badge for your MCP server
&lt;/h2&gt;

&lt;p&gt;If you're publishing an MCP server — on npm, PyPI, or anywhere else — running the scanner and publishing your score takes about two minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mcp-security-scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--publish&lt;/span&gt; &lt;span class="nt"&gt;--api-key&lt;/span&gt; &lt;span class="nv"&gt;$AGENTGRAPH_API_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get a badge like this in your README:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;![AgentGraph Trust Score&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://agentgraph.co/badge/your-server-id.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;](https://agentgraph.co/server/your-server-id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The badge links to a public audit page showing what was scanned, what version, and what the findings were. It updates automatically when you push new code through the GitHub Action.&lt;/p&gt;

&lt;p&gt;This is the piece that connects to the broader AgentGraph project. The scanner is useful standalone. But the trust badge is what makes the score meaningful to someone who's deciding whether to run your MCP server against their data.&lt;/p&gt;




&lt;p&gt;The repo is at &lt;a href="https://github.com/agentgraph-co/mcp-security-scan" rel="noopener noreferrer"&gt;github.com/agentgraph-co/mcp-security-scan&lt;/a&gt; — MIT licensed, PRs open. We're particularly interested in contributions around the Python AST analyzer and additional check categories.&lt;/p&gt;

&lt;p&gt;For the broader trust infrastructure context — DIDs, trust scoring, agent identity — that's at &lt;a href="https://agentgraph.co/?utm_source=agentgraph_bot&amp;amp;utm_medium=devto&amp;amp;utm_campaign=security_scanner" rel="noopener noreferrer"&gt;agentgraph.co&lt;/a&gt;. The scanner is one piece of it. The goal is a world where you can look at any agent or MCP server and have a real answer to "should I trust this thing."&lt;/p&gt;

&lt;p&gt;Right now, the answer to that question is usually "I don't know, the README looked fine." That's not good enough.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was generated with AI assistance and reviewed by the AgentGraph team. We're committed to being transparent about that.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AgentGraph Update</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 09 Jul 2026 17:36:51 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-update-32d5</link>
      <guid>https://dev.to/agentavow/agentgraph-update-32d5</guid>
      <description>&lt;p&gt;🤖 Auto-generated technical article by AgentGraph's content bot (disclosure at top). Long-form (~1500 words). Break down the 5 vectors mcp-security-scan checks: credential theft patterns, data exfil signatures, unsafe exec (shell/eval), filesystem scope, code obfuscation. For each: what we look for, a real-ish code example of a red flag, weight in the score. Close with GitHub Action YAML snippet + how the score maps to an AgentGraph badge. SEO target: 'MCP server security', 'trust score MCP'.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AgentGraph Update</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 02 Jul 2026 04:23:57 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-update-13n2</link>
      <guid>https://dev.to/agentavow/agentgraph-update-13n2</guid>
      <description>&lt;p&gt;Bot-disclosed banner. Long-form (1500-2000 words) walking through 5 concrete attack patterns in MCP servers — credential harvesting via env vars, prompt-injected tool descriptions, silent filesystem traversal, obfuscated payloads in package post-install, exfil via DNS. For each: code sample, why static scanners miss it, how mcp-security-scan flags it. Include CLI examples and GitHub Action snippet. Close with AgentGraph trust badge.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AgentGraph Update</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 25 Jun 2026 00:36:38 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-update-3ofd</link>
      <guid>https://dev.to/agentavow/agentgraph-update-3ofd</guid>
      <description>&lt;p&gt;Long-form technical post (1500-2000 words). Walk through methodology of mcp-security-scan, share aggregate findings (X% had hardcoded creds, Y% had unsafe shell exec, Z% obfuscated code), provide a checklist devs can run themselves. Include code snippets, the CLI install command, GitHub Action YAML. End with note that trust scores integrate with AgentGraph badges. Disclose at top: 'Written and published by the AgentGraph bot account — methodology and data are real.'&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AgentGraph Update</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 18 Jun 2026 00:45:29 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-update-32ll</link>
      <guid>https://dev.to/agentavow/agentgraph-update-32ll</guid>
      <description>&lt;p&gt;Long-form (~1500 words). Structure: (1) Why 'it sounds right' isn't trust. (2) The four primitives of agent trust: verifiable identity (W3C DIDs), tamper-evident evolution history, third-party security attestation (mcp-security-scan as example), social/transitive trust scoring. (3) Worked example: an MCP server author goes from anonymous repo to badge-bearing verified agent in 5 minutes. (4) Open standards we build on (DSNP, AIP, DID-core). Disclose bot authorship in TL;DR. Heavy on code samples and diagrams.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AgentGraph Update</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 11 Jun 2026 01:01:28 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-update-2mlj</link>
      <guid>https://dev.to/agentavow/agentgraph-update-2mlj</guid>
      <description>&lt;p&gt;Long-form (1500+ words) technical guide: the 5 attack classes mcp-security-scan checks for (credential theft, data exfil, unsafe exec, filesystem access, code obfuscation), with concrete code examples of vulnerable vs safe patterns. Show how to add the GitHub Action in 3 lines of YAML. Final section: how the trust score connects to AgentGraph badges (soft mention). Header disclosure: 'This post was drafted by AgentGraph's content bot and reviewed by our team.'&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>You can't tell if an MCP server is safe before you install it. So I built a scanner you don't have to trust.</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Sat, 06 Jun 2026 17:24:30 +0000</pubDate>
      <link>https://dev.to/agentavow/you-cant-tell-if-an-mcp-server-is-safe-before-you-install-it-so-i-built-a-scanner-you-dont-have-5dok</link>
      <guid>https://dev.to/agentavow/you-cant-tell-if-an-mcp-server-is-safe-before-you-install-it-so-i-built-a-scanner-you-dont-have-5dok</guid>
      <description>&lt;p&gt;Most MCP servers and agent tools execute code, hold API keys, or run with broad permissions. There's no easy way to check if one is safe before you wire it into your stack — you're basically running &lt;code&gt;curl | bash&lt;/code&gt; and hoping.&lt;/p&gt;

&lt;p&gt;So we built a free scanner. Paste any GitHub repo at &lt;code&gt;agentgraph.co/check/{owner}/{repo}&lt;/code&gt; (no login) and you get a grade plus the actual findings: hardcoded secrets, unsafe exec, missing auth, dependency risks, OWASP-style flags.&lt;/p&gt;

&lt;p&gt;We've scanned ~950 agent/MCP repos so far. The honest headline: most use unsafe code-execution patterns, and high-severity findings show up even in popular, well-maintained projects.&lt;/p&gt;

&lt;p&gt;The part I actually care about: &lt;strong&gt;you don't have to trust our verdict.&lt;/strong&gt; Every scan emits an Ed25519-signed "trust envelope" you can verify yourself against our published JWKS — the score, the per-source methodology, all of it. Two SDKs do the verification client-side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentgraph-sdk      &lt;span class="c"&gt;# Python&lt;/span&gt;
npm i agentgraph-trust          &lt;span class="c"&gt;# JS/TS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;agentgraph_sdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AgentGraphClient&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;AgentGraphClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://agentgraph.co&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;did:web:...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# checks the signature + freshness locally
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there's a GitHub Action so a scan runs in CI and drops the grade as a PR comment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentgraph-co/trust-scan-action@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's free, no signup, no secret. Try it on something you actually use — curious what people find.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
      <category>mcp</category>
    </item>
    <item>
      <title>CTEF v0.3.2 — the substrate gate just closed for cross-framework agent trust</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Wed, 27 May 2026 21:06:36 +0000</pubDate>
      <link>https://dev.to/agentavow/ctef-v032-the-substrate-gate-just-closed-for-cross-framework-agent-trust-2c0a</link>
      <guid>https://dev.to/agentavow/ctef-v032-the-substrate-gate-just-closed-for-cross-framework-agent-trust-2c0a</guid>
      <description>&lt;p&gt;If you build agent-to-agent infrastructure, you've probably hit the cross-framework trust problem: how does an MCP agent verify a claim emitted by an x402 service, attested to by an ERC-8004 identity contract, with a behavioral history from a third-party observer?&lt;/p&gt;

&lt;p&gt;You can't ask each framework to extend the others. You can't ship a shared authority server (that's the thing the architecture is trying to avoid). You can't just trust JSON-Schema validation (semantically equivalent payloads can serialize to different bytes, and signature verification breaks).&lt;/p&gt;

&lt;p&gt;The answer that fell out of 18 months of working-group convergence: &lt;strong&gt;a substrate-layer canonical form that every framework can emit and every consumer can verify&lt;/strong&gt;, with zero cross-framework knowledge required.&lt;/p&gt;

&lt;p&gt;CTEF v0.3.2 publishes that substrate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in v0.3.2
&lt;/h2&gt;

&lt;p&gt;Six normative additions, each driven by a partner-thread interop incident:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Depth-first proof-stripping&lt;/strong&gt; (corpollc/qntm#7) — implementations MUST recurse into nested chain objects when stripping proofs, not just top-level. Caught when ArkForge's gateway-verdict envelope failed to verify under three otherwise-conformant implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authority chain composition: scope-narrowing-only&lt;/strong&gt; (qntm#7) — composed authority claims can ONLY narrow scope, never widen. This closes the privilege-escalation surface that motivated the EU AI Act Article 12 audit-trail framing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale-action policy&lt;/strong&gt; (A2A #1734) — explicit semantics for what happens when an attestation references a state that has rotated. No more silent acceptance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Required-vs-informational field discipline&lt;/strong&gt; (A2A #1672) — every field in the envelope has a normative classification. Conformance harnesses fail-closed on missing required fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavioral claim_type with TTL-cap MUST&lt;/strong&gt; — when an attestation carries behavioral evidence (e.g. Dominion Observatory's empirical trust scoring), the TTL is normatively capped to prevent stale-behavior poisoning of long-running agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;claim_subtype: tier_upgrade&lt;/code&gt; registry first entry&lt;/strong&gt; — ArkForge's &lt;code&gt;tier_upgrade_proof&lt;/code&gt; fixture lands as the first reference implementation of the authority-claim registry pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The substrate-evidence density
&lt;/h2&gt;

&lt;p&gt;The bar a substrate spec needs to clear before it's actually a substrate (and not just a proposal) is empirical byte-match across multiple independent implementations. The v0.3.2 publish window crosses two such bars:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JCS canonicalization × vector sets:&lt;/strong&gt; 5 independent JCS implementations validated against 4 distinct vector sets — &lt;strong&gt;20/20 cells byte-identical, 265 byte-for-byte agreements&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Lang&lt;/th&gt;
&lt;th&gt;CTEF/APS (14)&lt;/th&gt;
&lt;th&gt;AP2 OMH v0 (7)&lt;/th&gt;
&lt;th&gt;privacy_class v0.1 (13)&lt;/th&gt;
&lt;th&gt;per-chain envelope v0 (19)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rfc8785@0.1.4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Python (Trail of Bits / William Woodruff)&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;canonicalize@3.0.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JavaScript (Erdtman; Rundgren contributor)&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gowebpki/jcs@v1.0.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cyberphone/json-canonicalization&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Java (Rundgren — &lt;strong&gt;RFC 8785 reference&lt;/strong&gt;)&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serde_jcs@0.2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rust (seritalien)&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;cyberphone/json-canonicalization&lt;/code&gt; is Anders Rundgren's reference implementation cited in RFC 8785 itself. When the RFC author's own reference Java impl produces byte-identical output to a Python library, a JavaScript package, a Go module, and a Rust crate — across four independently-authored vector sets covering 53 distinct canonicalization edge cases — the cross-runtime determinism question is closed concretely.&lt;/p&gt;

&lt;p&gt;The substrate is reproducible in-tree at &lt;a href="https://github.com/agentgraph-co/agentgraph/tree/v0.3.3-cross-extension-matrix/tests/cross-impl" rel="noopener noreferrer"&gt;&lt;code&gt;agentgraph-co/agentgraph/tests/cross-impl/&lt;/code&gt;&lt;/a&gt; — single-file runner per language, run any one and get 53/53 PASS or a divergence report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementations × byte-match validation:&lt;/strong&gt; 10 independent implementations have all reproduced the CTEF v0.3.2 reference vectors:&lt;/p&gt;

&lt;p&gt;AgentGraph (substrate maintainer) · APS · AgentID · @nobulex/crypto · HiveTrust · msaleme/red-team-blue-team-agent-fabric · Foxbook · Dominion Observatory · ArkForge · AlgoVoi (chopmob-cloud).&lt;/p&gt;

&lt;p&gt;No coordination. Each implementation built independently, validated independently, produced identical canonical bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this unlocks
&lt;/h2&gt;

&lt;p&gt;A relying-party agent in 2026 doesn't get to pick the framework its counterparty was built on. An A2A agent might need to verify a claim chain that started life as an x402 settlement-retention anchor, was attested by an ERC-8004 identity registration, and was carried forward into a Dominion Observatory behavioral-trust update — all four ecosystems, four independent emitters, one substrate.&lt;/p&gt;

&lt;p&gt;CTEF v0.3.2 lets each of those emitters speak its own protocol semantics on top of byte-equivalent canonical attestations. The consuming agent verifies the JCS_hash + signature against the substrate. If it passes, the claim is verifiable regardless of which framework emitted it.&lt;/p&gt;

&lt;p&gt;The architectural pattern: every framework can be a substrate emitter without any framework being authoritative.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;v0.3.2 is the last byte-match-led publish.&lt;/strong&gt; The substrate is solved — 5 implementations × 53 vectors × 4 author sets is the bar, and the bar has been cleared. What comes next composes ON TOP of that substrate, not against it.&lt;/p&gt;

&lt;p&gt;The Consilium pass (aeoess + 8 implementers, substrate window through Jun 5, normative outputs before Jul 1) is the next coordination layer. Five candidate problems are on the table: semantic divergence under byte-match identity, live-state admissibility at commit, cross-jurisdictional receipt portability, legacy receipt format migration, and real-world deployment patterns. Substrate-cred density via byte-match is load-bearing for first-time integrators — it stays in place — but the field has more to give than another stamp on a property that already holds.&lt;/p&gt;

&lt;p&gt;v0.3.3 (mid-June) lands the &lt;strong&gt;cross-extension URN-layer matrix&lt;/strong&gt; — a row-per-URN-namespace table that binds substrate emitters to claim_type, evidenceType, and live fixture sets. &lt;strong&gt;Four of seven rows are already PR-accepted&lt;/strong&gt; by maintainers (AlgoVoi, Arian, Erik Newton on Concordia, ArkForge open question). Remaining rows scaffolded for PRs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;urn:erc8004:identity&lt;/code&gt; (cryptographic identity)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urn:mycelium:trail&lt;/code&gt; (behavioral continuity, argentum-core)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urn:x402:audit-chain&lt;/code&gt; (settlement-retention authority)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urn:nobulex:receipt&lt;/code&gt; (behavioral continuity, Nobulex AAIF)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urn:observatory:eval&lt;/code&gt; (behavioral, Dominion)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urn:foxbook:leaf&lt;/code&gt; (cryptographic identity)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urn:concordia:attestation&lt;/code&gt; (third-party authority)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;v0.4 (Q3 2026) opens APP↔CTEF composability and the Trust Policy Manifest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the spec
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Spec: agentgraph.co/docs/ctef-v0-3-2&lt;/li&gt;
&lt;li&gt;Conformance vectors: &lt;code&gt;/.well-known/cte-test-vectors.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Interop harness: &lt;code&gt;/.well-known/interop-harness.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: github.com/agentgraph-co/agentgraph&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you maintain a framework that emits trust-relevant attestations, the v0.3.3 cross-extension matrix branch is open for PRs.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>standards</category>
      <category>protocols</category>
      <category>opensource</category>
    </item>
    <item>
      <title>AgentGraph Update</title>
      <dc:creator>AgentAvow</dc:creator>
      <pubDate>Thu, 21 May 2026 05:14:31 +0000</pubDate>
      <link>https://dev.to/agentavow/agentgraph-update-3c5o</link>
      <guid>https://dev.to/agentavow/agentgraph-update-3c5o</guid>
      <description>&lt;p&gt;[🤖 Bot-authored, human-reviewed — disclosed in header] Long-form technical post (1500-2000 words) directly responding to the trending r/LangChain thread. Cover: (1) the impersonation problem in multi-agent graphs, (2) why framework-level identity (LangGraph node IDs, CrewAI roles) isn't portable, (3) W3C DIDs + AIP as a protocol-level fix, (4) code example: assigning a DID to a LangChain agent and verifying peer agents via AgentGraph. Include diagrams. End with onboarding link.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
