<?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: Zido</title>
    <description>The latest articles on DEV Community by Zido (@zidocode).</description>
    <link>https://dev.to/zidocode</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%2F4174822%2Fbf56cc2b-f172-4002-97d0-2aecb6235a63.jpg</url>
      <title>DEV Community: Zido</title>
      <link>https://dev.to/zidocode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zidocode"/>
    <language>en</language>
    <item>
      <title>Your agent skills were install-once</title>
      <dc:creator>Zido</dc:creator>
      <pubDate>Sat, 10 Oct 2026 14:04:40 +0000</pubDate>
      <link>https://dev.to/zidocode/your-agent-skills-were-install-once-n08</link>
      <guid>https://dev.to/zidocode/your-agent-skills-were-install-once-n08</guid>
      <description>&lt;p&gt;Back in January 2026, security researchers audited a major skill marketplace and found &lt;strong&gt;341 malicious skills out of 2,857&lt;/strong&gt; — 11.9%. One coordinated campaign. By February the count of confirmed malicious skills crossed a thousand.&lt;/p&gt;

&lt;p&gt;But here's the part that stuck with me: the audits all happened at &lt;em&gt;publish time&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap nobody closes
&lt;/h2&gt;

&lt;p&gt;Every skill you install — a &lt;code&gt;SKILL.md&lt;/code&gt;, some scripts, maybe a helper module — lands as plain files on your disk. The marketplace scan checks them once, at the moment of publication. After that, the files are yours, and nothing watches them.&lt;/p&gt;

&lt;p&gt;Meanwhile skills get updated. Upstream repos push changes. You pull. A helper script that was clean when you installed it in March doesn't have to be clean in June — and no re-scan fires, because from the registry's point of view nothing happened. The rug-pull class of attack isn't theoretical; it's documented, with hashing-based detection named as the mitigation and then left as an exercise for the reader.&lt;/p&gt;

&lt;p&gt;I looked for a tool that closes this gap: something that says "the skills on your disk are not what you installed." It didn't exist as a standalone, cross-platform thing — detection research is all publish-time or LLM-based triage. So I built the boring version.&lt;/p&gt;

&lt;h2&gt;
  
  
  skill-integrity
&lt;/h2&gt;

&lt;p&gt;One Python file, zero dependencies, no network calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 skill_integrity.py snapshot    &lt;span class="c"&gt;# right after installing skills&lt;/span&gt;
python3 skill_integrity.py check       &lt;span class="c"&gt;# any time later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The check output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;skills scanned: 23  (snapshot taken 2026-10-10T21:44:32+0800)

[~] pdf-extractor — MODIFIED
    changed: SKILL.md
    added:   fetch_helper.sh

1 skill(s) changed since snapshot. Review diffs before trusting them.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole product. SHA-256 every file, keep a local manifest, diff against it. Modified files, added files, deleted skills, brand-new skills — all four show up. &lt;code&gt;--json&lt;/code&gt; for machines, &lt;code&gt;--fail-on-change&lt;/code&gt; for CI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;0 &lt;span class="k"&gt;*&lt;/span&gt;/12 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; python3 ~/skill-integrity/skill_integrity.py check &lt;span class="nt"&gt;--fail-on-change&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.skill-integrity/checks.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What it deliberately doesn't do
&lt;/h2&gt;

&lt;p&gt;A hash catches &lt;strong&gt;any byte change&lt;/strong&gt;. It cannot judge intent — a legitimate upstream update and a malicious rewrite look identical. That's not a limitation I'm hiding; it's the shape of the problem. The tool's job is to be the tripwire: something changed, here's the file list, go read the diff. Reading the diff before trusting the skill is your half of the contract.&lt;/p&gt;

&lt;p&gt;This is the same honesty boundary I keep hitting in this suite: signature systems are a step behind novel attacks, and pretending otherwise is how security tools lose trust. &lt;a href="https://github.com/ZidoCode/agent-ledger" rel="noopener noreferrer"&gt;agent-ledger&lt;/a&gt; says "novel evasions remain an open problem" in its README; skill-integrity says "hashes don't read minds."&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ZidoCode/skill-integrity
python3 skill-integrity/skill_integrity.py snapshot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run Claude Code or Hermes with a pile of community skills installed, run &lt;code&gt;check&lt;/code&gt; right now — I'd genuinely like to know how many people find their skills have drifted.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building in public: agent security and reliability tooling. Also in the suite: &lt;a href="https://github.com/ZidoCode/agent-ledger" rel="noopener noreferrer"&gt;agent-ledger&lt;/a&gt; (audit + policy enforcement) and &lt;a href="https://github.com/ZidoCode/agent-janitor" rel="noopener noreferrer"&gt;agent-janitor&lt;/a&gt; (process hygiene). &lt;a href="https://github.com/ZidoCode" rel="noopener noreferrer"&gt;github.com/ZidoCode&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>agent-ledger: a security and audit plugin for Hermes Agent, scored against the OWASP Agentic Top 10</title>
      <dc:creator>Zido</dc:creator>
      <pubDate>Sat, 10 Oct 2026 08:48:19 +0000</pubDate>
      <link>https://dev.to/zidocode/agent-ledger-a-security-and-audit-plugin-for-hermes-agent-scored-against-the-owasp-agentic-top-10-2k23</link>
      <guid>https://dev.to/zidocode/agent-ledger-a-security-and-audit-plugin-for-hermes-agent-scored-against-the-owasp-agentic-top-10-2k23</guid>
      <description>&lt;p&gt;&lt;em&gt;Every tool call your agent makes, recorded locally before it runs — with a 0–100 posture score and an honest list of what it can't see.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you run an AI agent on your own machine, you already trust it with a lot. It edits files, restarts services, pushes to GitHub. agent-ledger answers two questions about that arrangement: &lt;strong&gt;what did my agent actually do, and how risky is its behavior?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's a free, open-source (MIT) plugin for Hermes Agent, and it works in two layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1: the ledger
&lt;/h2&gt;

&lt;p&gt;The plugin hooks &lt;code&gt;pre_tool_call&lt;/code&gt; and writes an entry to a local SQLite database &lt;strong&gt;before&lt;/strong&gt; the tool executes. When the call completes, the entry is confirmed. Anything issued but never confirmed becomes a &lt;strong&gt;ghost&lt;/strong&gt; — a tool call the agent believed it made, with no evidence it happened. Ghosts typically appear when a session is torn down mid-flight, for example during context compaction.&lt;/p&gt;

&lt;p&gt;When a ghost is detected, the plugin injects a warning into the agent's next context, so the agent itself goes back and verifies reality instead of trusting its memory. That's the core loop: record first, act second, reconcile after.&lt;/p&gt;

&lt;p&gt;Everything stays on your machine. The ledger is a plain SQLite file, there is no telemetry, no account, nothing leaves the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2: the posture score
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;posture.py&lt;/code&gt; reads the ledger and scores your agent's recorded behavior from 100 to 0 against the &lt;a href="https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/" rel="noopener noreferrer"&gt;OWASP Top 10 for Agentic Applications 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What it detects from ledger metadata alone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ASI02 — tool misuse:&lt;/strong&gt; destructive-tool bursts, credential-store access, unusual tool frequency versus your baseline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASI05 — unexpected code execution:&lt;/strong&gt; &lt;code&gt;curl ... | bash&lt;/code&gt;, &lt;code&gt;wget | sh&lt;/code&gt;, obfuscated payloads like &lt;code&gt;echo &amp;lt;base64&amp;gt; | base64 -d | bash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASI08 — cascading failures:&lt;/strong&gt; error-rate spikes and bursts of consecutive failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASI10 — rogue agents:&lt;/strong&gt; ghost entries and unconfirmed mutations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASI11 (ext) — excessive agency:&lt;/strong&gt; mutating-call volume relative to reads. Labeled &lt;code&gt;(ext)&lt;/code&gt; because the official OWASP list stops at ASI10; this one is a community extension.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it deliberately does &lt;strong&gt;not&lt;/strong&gt; claim: categories that need payload or conversation inspection (ASI01, ASI03, ASI04, ASI06, ASI07, ASI09 — goal hijack, identity abuse, supply chain, memory poisoning, inter-agent trust, trust exploitation). Every report prints the not-covered list right next to the covered one. A score of 100 means "nothing suspicious in the recorded activity," not "the agent was well-behaved" — the ledger is written by the agent being scored, and the report says exactly that. No security tool should hide this, so agent-ledger doesn't.&lt;/p&gt;

&lt;p&gt;The scoring itself is auditable, not a black box: &lt;code&gt;score = 100 − Σ{CRITICAL:25, HIGH:15, MEDIUM:8, LOW:3}&lt;/code&gt; over all findings, no deduplication, and the full finding list always comes back so you can recompute it by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;

&lt;p&gt;Install (once it's in the catalog, this becomes &lt;code&gt;hermes plugins install agent-ledger&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ZidoCode/agent-ledger ~/.hermes/plugins/agent-ledger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart your Hermes gateway and the ledger starts recording. To score your agent right now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 ~/.hermes/plugins/agent-ledger/posture.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent Posture Score: 24/100
Calls: 216 | mutating: 120 | errors: 14 | ghosts: 1
[HIGH] ASI05: Terminal accessed credential-shaped path — ...
Covered: ASI02, ASI05, ASI08, ASI10, ASI11 (ext)
Requires payload inspection (not covered): ASI01, ASI03, ASI04, ASI06, ASI07, ASI09
Note: score reflects recorded activity only ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a scheduled report, &lt;code&gt;posture_daily.py&lt;/code&gt; sends a daily digest to Telegram (score, delta versus yesterday, top findings by severity). Point it at your bot token via environment variables, add one cron line, done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation
&lt;/h2&gt;

&lt;p&gt;The scorer ships with its full test suite, and you're encouraged to run it before trusting it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Suite&lt;/th&gt;
&lt;th&gt;What it proves&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test_posture.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;benign ledger → 100 with zero findings; planted malicious ledger → all covered ASI families fire&lt;/td&gt;
&lt;td&gt;PASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test_posture_unit.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;per-ASI must-fire and must-not-fire cases, plus 7 known evasion patterns&lt;/td&gt;
&lt;td&gt;36/36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test_posture_scale.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10k rows in 0.054s, 50k rows in 0.281s; correct multi-session attribution&lt;/td&gt;
&lt;td&gt;PASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;selftest.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ledger FIFO matching and ghost reconciliation&lt;/td&gt;
&lt;td&gt;13/13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The honest version of that table: the suite proves the scorer catches the seven evasion patterns we know about and none of the innocent look-alikes. It does not prove immunity to novel evasions — signature detection is always a step behind attacks nobody has written a rule for yet. The behavioral signals (rate spikes, error bursts, ghosts) are the mitigation for that, and they degrade the score even without a matching signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it's going
&lt;/h2&gt;

&lt;p&gt;Shipped since the first version: &lt;strong&gt;policy enforcement&lt;/strong&gt; — install a policy pack, watch the dry-run log what it &lt;em&gt;would&lt;/em&gt; block, then flip &lt;code&gt;policy_mode&lt;/code&gt; to enforce and dangerous calls are refused before they run. It's signature-based over the extracted command, so like every signature system it's a seatbelt, not a wall (the README lists the known bypass surfaces honestly). Still on the roadmap: per-session posture reports, a multi-agent dashboard, and tamper-evident logging. And it's all free (MIT) — no license, no tier, no gate.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/ZidoCode/agent-ledger" rel="noopener noreferrer"&gt;github.com/ZidoCode/agent-ledger&lt;/a&gt; (v0.4.0 — everything is free, including enforcement)&lt;/li&gt;
&lt;li&gt;Plugin catalog submission: &lt;a href="https://github.com/NousResearch/hermes-agent/pull/135993" rel="noopener noreferrer"&gt;PR #135993&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build with agents, try it on your own ledger and see what the score says. Feedback and issues are welcome.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building in public: agent security and reliability tooling. &lt;a href="https://github.com/ZidoCode" rel="noopener noreferrer"&gt;github.com/ZidoCode&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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