<?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: Jason Miller</title>
    <description>The latest articles on DEV Community by Jason Miller (@secbyjasonmiller).</description>
    <link>https://dev.to/secbyjasonmiller</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%2F4090372%2F3526e323-9829-470e-9dd7-02b018fc9d06.webp</url>
      <title>DEV Community: Jason Miller</title>
      <link>https://dev.to/secbyjasonmiller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/secbyjasonmiller"/>
    <language>en</language>
    <item>
      <title>Five of the Top Seven Agent Skills Were Malware. Your Install Flow Is the Problem.</title>
      <dc:creator>Jason Miller</dc:creator>
      <pubDate>Wed, 26 Aug 2026 13:51:08 +0000</pubDate>
      <link>https://dev.to/secbyjasonmiller/five-of-the-top-seven-agent-skills-were-malware-your-install-flow-is-the-problem-4ga8</link>
      <guid>https://dev.to/secbyjasonmiller/five-of-the-top-seven-agent-skills-were-malware-your-install-flow-is-the-problem-4ga8</guid>
      <description>&lt;p&gt;At peak infection, five of the seven most-downloaded skills on the ClawHub registry were confirmed malware. Not flagged for review. Confirmed. If your install flow is still "the agent suggested it, so I added it," that number should bother you.&lt;/p&gt;

&lt;p&gt;OWASP now has a draft for this: the Agentic Skills Top 10 (AST10). It is separate from both the LLM Top 10 and the Agentic AI Top 10. It extends LLM03 (supply chain) into the skills layer, and the project's framing is the best one-liner in it: MCP is how the model talks to tools, AST10 is what those tools actually do.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Skill Is a Workflow Holding Your Credentials
&lt;/h2&gt;

&lt;p&gt;Most devs still file skills under "prompt snippets." Wrong category. A skill encodes planning and tool orchestration, and it can carry file system, network, and shell access plus persistent memory. When you install one, a stranger's workflow logic gets the keys your agent already holds.&lt;/p&gt;

&lt;p&gt;Packaging tells you the risk. OpenClaw uses SKILL.md with YAML frontmatter. Claude Code uses skill.json. Cursor and Codex use manifest.json. VS Code uses package.json, which means a skill there is literally an npm-style package, with everything that implies about install-time execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Risks That Actually Bite
&lt;/h2&gt;

&lt;p&gt;The list has ten items, but a few ideas do most of the work.&lt;/p&gt;

&lt;p&gt;The Lethal Trifecta (Simon Willison and Palo Alto Networks, 2026): access to private data, exposure to untrusted content, and the ability to communicate externally. A skill holding all three is an exfiltration channel waiting for instructions. Any skill that reads email, tickets, or web pages feeds attacker-controlled text straight into the planner, so prompt injection (AST05) rides along. OWASP's paired mitigation is prompt sanitization, and I think that's the weakest control on the list. Nobody has a sanitizer that reliably works. You can't filter your way out, so control capability instead: a skill that ingests untrusted content should not also get network egress.&lt;/p&gt;

&lt;p&gt;Isolation matters more than consent dialogs. Check Point disclosed two Claude Code vulns (CVE-2025-59536, CVSS 8.7, and CVE-2026-21852, CVSS 5.3) where cloning and opening an untrusted repo triggered remote code execution and API key theft before any consent prompt appeared. If a skill runs anywhere near production credentials, it runs in a sandbox.&lt;/p&gt;

&lt;p&gt;And the cheapest control in the whole list is the one almost nobody does: pin your versions. You reviewed 1.4.2. The updater pulled 1.4.5 last night, and 1.4.5 does something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vet Skills Like Dependencies, Because They Are
&lt;/h2&gt;

&lt;p&gt;Order of operations, tuned for a team that ships:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify the publisher, not just the skill. A clean skill from a two-day-old account with one upload is a no.&lt;/li&gt;
&lt;li&gt;Read the permission manifest before the code. Network access for a local task like formatting: reject. Write access outside a designated workspace: reject. All three Trifecta capabilities in one skill: block by default. No manifest at all: that absence is a finding.&lt;/li&gt;
&lt;li&gt;Pin versions and hash artifacts. Lockfile committed next to your agent config, auto-update off.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# skills.lock.yml&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;pdf-report-builder&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.4.2&lt;/span&gt;
  &lt;span class="na"&gt;sha256&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;9f2c44a1...&lt;/span&gt;   &lt;span class="c1"&gt;# hash of the exact artifact you vetted&lt;/span&gt;
  &lt;span class="na"&gt;publisher&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;verified:acme-tools&lt;/span&gt;
  &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;file_read&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./workspace"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;file_write&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./workspace/reports"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;risk_tier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;L1&lt;/span&gt;
  &lt;span class="na"&gt;reviewed_by&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;j.doe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Sandbox-test every new or updated skill in a container with no network and a read-only root filesystem. Snyk's ToxicSkills research pulled 76-plus confirmed malicious payloads out of an ecosystem that already had scanning, so scan locally even when the registry does.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The proposed Universal Skill Format (explicit permission paths, a risk_tier from L0 to L3, ed25519 signatures) is worth watching, but don't wait for registries to mandate it. Use its fields as your internal vetting template now.&lt;/p&gt;

&lt;p&gt;Things you can do today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treat every unsigned skill as hostile by default until your registry requires signatures and your client verifies them.&lt;/li&gt;
&lt;li&gt;Block any skill that combines private data access, untrusted content, and network egress.&lt;/li&gt;
&lt;li&gt;Turn off auto-update for skills. A version change means a re-review.&lt;/li&gt;
&lt;li&gt;Read YAML frontmatter with the same suspicion you'd give a shell script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's actually in your skill install flow right now: any vetting at all, or is it still "the agent suggested it"?&lt;/p&gt;

&lt;p&gt;Longer writeup if you want the full argument: &lt;a href="https://axeploit.com/blog/five-of-the-top-seven-skills-were-malware-a-working-guide-to-owasp-s-agentic-skills-top-10" rel="noopener noreferrer"&gt;https://axeploit.com/blog/five-of-the-top-seven-skills-were-malware-a-working-guide-to-owasp-s-agentic-skills-top-10&lt;/a&gt;&lt;/p&gt;

</description>
      <category>owasp</category>
      <category>agenticai</category>
      <category>aisecurity</category>
      <category>supplychainsecurity</category>
    </item>
    <item>
      <title>CircleCI's MCP Server RCE: Header Checks Are Not Authentication</title>
      <dc:creator>Jason Miller</dc:creator>
      <pubDate>Tue, 25 Aug 2026 16:45:24 +0000</pubDate>
      <link>https://dev.to/secbyjasonmiller/circlecis-mcp-server-rce-header-checks-are-not-authentication-2gkc</link>
      <guid>https://dev.to/secbyjasonmiller/circlecis-mcp-server-rce-header-checks-are-not-authentication-2gkc</guid>
      <description>&lt;p&gt;Getting remote code execution in CircleCI's MCP server took two HTTP headers and zero credentials. Send &lt;code&gt;Host: localhost&lt;/code&gt; with no &lt;code&gt;Origin&lt;/code&gt; header and you walk through the origin allowlist, call the run-pipeline tool with a config you wrote, and execute inside someone's CI under their org-wide API token. The researchers at Remedio, who found it, gave it an expected CVSS of 10.0.&lt;/p&gt;

&lt;p&gt;The mechanism is worth understanding because you'll meet this pattern again in other AI tooling. The allowlist checks &lt;code&gt;Host&lt;/code&gt; against an allowed set and explicitly passes requests with no &lt;code&gt;Origin&lt;/code&gt; header. That design has teeth against browser-based attacks, where a malicious page can't forge those headers. But nothing forces an attacker to use a browser. curl picks every header on the wire.&lt;/p&gt;

&lt;p&gt;The defaults made it worse: the server listened on all interfaces out of the box, and the request-token requirement could be switched off. A tool built with localhost trust assumptions, shipped with the posture of a public service. And running it as a shared team server holding an org token is a supported use case, not an abuse.&lt;/p&gt;

&lt;p&gt;Also: there are three advisories for this package, not one. GHSA-xv5j-cwgj-22r4 is the header bypass. GHSA-m9x7-h9px-p447 is an unauthenticated command injection in the &lt;code&gt;run_evaluation_tests&lt;/code&gt; tool, also RCE, and it got a fraction of the coverage. GHSA-8xjg-jpfh-5257 is a third issue. None of the materials I reviewed listed CVE IDs, so track by GHSA. The quiet command injection is the one most likely to still be unpatched somewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check your exposure in ten minutes
&lt;/h2&gt;

&lt;p&gt;Where is it listening?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; node
&lt;span class="c"&gt;# 127.0.0.1:&amp;lt;port&amp;gt; = loopback only (good)&lt;/span&gt;
&lt;span class="c"&gt;# 0.0.0.0:&amp;lt;port&amp;gt; = every interface (reachable)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Docker, check &lt;code&gt;docker ps&lt;/code&gt; for published &lt;code&gt;0.0.0.0:...-&amp;gt;&lt;/code&gt; ports. In Kubernetes, look for NodePort or LoadBalancer Services in front of it. Don't skip dev machines. A shared box with a published port is network-reachable.&lt;/p&gt;

&lt;p&gt;Is a token required?&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="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\0'&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &amp;lt; /proc/&lt;span class="si"&gt;$(&lt;/span&gt;pgrep &lt;span class="nt"&gt;-f&lt;/span&gt; mcp-server-circleci | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/environ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; REQUIRE_REQUEST_TOKEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unset or false, plus a 0.0.0.0 bind, is the worst case. Then test the allowlist against your own deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: localhost"&lt;/span&gt; http://&amp;lt;server-ip&amp;gt;:&amp;lt;port&amp;gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the MCP endpoint responds instead of rejecting you, the allowlist is decorative. Compare your installed version against the patched versions in all three GHSAs.&lt;/p&gt;

&lt;h2&gt;
  
  
  If it was reachable, hunt before you patch
&lt;/h2&gt;

&lt;p&gt;Patching first feels productive and destroys evidence. Spend an hour on detection.&lt;/p&gt;

&lt;p&gt;Pull proxy and firewall logs for requests to the MCP port where &lt;code&gt;Host&lt;/code&gt; says &lt;code&gt;localhost&lt;/code&gt; but the source IP isn't loopback. Almost nothing legitimate produces that pattern. Then check CircleCI pipeline history for runs nobody triggered or configs with steps you don't recognize. The attack goes through the run-pipeline tool, so the execution record lives in CircleCI, not on your host. Review the org token's activity too, because its activity is the attacker's activity.&lt;/p&gt;

&lt;p&gt;If you find something, or your logging is too thin to rule it out, rotate. CircleCI token first, then whatever it could reach: project environment variables and contexts, plus any cloud identity your CI assumes. The blast radius isn't the box running the server. It's everything your CI can touch.&lt;/p&gt;

&lt;p&gt;Then patch, and plan the migration. The standalone server is deprecated, so follow CircleCI's current guidance rather than investing further in it.&lt;/p&gt;

&lt;p&gt;What I'd do today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inventory every MCP server running in your org: where it listens, whether it requires a token, and which credentials it holds. Scope those tokens like production credentials, because they are.&lt;/li&gt;
&lt;li&gt;Patch all three CircleCI advisories, not just the famous one. Can't this week? Bind to 127.0.0.1, set &lt;code&gt;REQUIRE_REQUEST_TOKEN=true&lt;/code&gt;, and verify with &lt;code&gt;ss&lt;/code&gt;. Trust the socket, not the config file.&lt;/li&gt;
&lt;li&gt;If any instance was network-reachable, hunt first, patch second, then rotate the org token and everything downstream of it.&lt;/li&gt;
&lt;li&gt;Treat any MCP server holding credentials as internet-facing, whether you meant it to be or not. Threat-model it that way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Honest question for the comments: if someone asked right now, could you produce a list of every MCP server running in your org and the tokens attached to each?&lt;/p&gt;

&lt;p&gt;Longer writeup with the full defender's playbook: &lt;a href="https://axeploit.com/blog/circleci-s-mcp-server-rce-a-defender-s-playbook-for-all-three-advisories" rel="noopener noreferrer"&gt;https://axeploit.com/blog/circleci-s-mcp-server-rce-a-defender-s-playbook-for-all-three-advisories&lt;/a&gt;&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>mcp</category>
      <category>rce</category>
      <category>aisecurity</category>
    </item>
  </channel>
</rss>
