<?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: RedCapra</title>
    <description>The latest articles on DEV Community by RedCapra (@redcapra).</description>
    <link>https://dev.to/redcapra</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%2F4106778%2F5b2037ee-e511-4ce6-8447-13e4adc31572.png</url>
      <title>DEV Community: RedCapra</title>
      <link>https://dev.to/redcapra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/redcapra"/>
    <language>en</language>
    <item>
      <title>The secret was correct. The first byte wasn't.</title>
      <dc:creator>RedCapra</dc:creator>
      <pubDate>Sun, 20 Sep 2026 09:53:07 +0000</pubDate>
      <link>https://dev.to/redcapra/the-secret-was-correct-the-first-byte-wasnt-6p9</link>
      <guid>https://dev.to/redcapra/the-secret-was-correct-the-first-byte-wasnt-6p9</guid>
      <description>&lt;p&gt;Our deploy tool pushed a fresh API token to production. It reported success. The token was correct. Every request then failed with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cannot convert argument to a ByteString because the character at
index 7 has a value of 65279 which is greater than 255.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Character 65279 is U+FEFF, a byte-order mark. Index 7 is the first character after &lt;code&gt;Bearer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Something had prefixed a BOM onto our token, between reading it out of the vault and storing it at the platform. The value was right. The bytes were not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we could not just look
&lt;/h2&gt;

&lt;p&gt;The obvious move is to open the dashboard and read the variable. You cannot. The variable is marked &lt;strong&gt;Sensitive&lt;/strong&gt;, which means it is write-only: the dashboard shows nothing, the CLI shows nothing, and the API returns the row with the value omitted entirely.&lt;/p&gt;

&lt;p&gt;That is good security. It is also a total audit blind spot, and it is the reason this took an hour instead of a minute. We had a credential that was wrong in a way nothing could show us, in a store designed so that nobody — including us — could read it back to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  The repro is two lines
&lt;/h2&gt;

&lt;p&gt;The push script read the secret from the vault and piped it to the platform CLI. That pipe is the bug. Windows PowerShell 5.1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="s1"&gt;'SECRETVALUE'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"process.stdin.on('data',d=&amp;gt;console.log(JSON.stringify(d.toString())))"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# "﻿SECRETVALUE\r\n"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There it is. Piping a string to a native command prefixes U+FEFF, because &lt;code&gt;[Console]::OutputEncoding&lt;/code&gt; is UTF-8 &lt;strong&gt;with a 3-byte preamble&lt;/strong&gt; in a non-interactive session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;OutputEncoding.GetPreamble&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Length&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c"&gt;# 3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI passed those bytes through faithfully. The platform stored them faithfully. Everything downstream was correct about a value that was already wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two fixes that do not work
&lt;/h2&gt;

&lt;p&gt;The obvious fix is to set the output encoding to a UTF-8 that emits no preamble:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$OutputEncoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;System.Text.UTF8Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s1"&gt;'SECRETVALUE'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# "﻿SECRETVALUE\r\n"   &amp;lt;-- still there&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still there. So try the console encoding instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;OutputEncoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;System.Text.UTF8Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s1"&gt;'SECRETVALUE'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# "﻿SECRETVALUE\r\n"   &amp;lt;-- still there&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still there.&lt;/p&gt;

&lt;p&gt;Both of those are the fixes you will find if you search for this, and we measured both of them failing before writing any code. That mattered: the first patch we wrote was the &lt;code&gt;$OutputEncoding&lt;/code&gt; one, and it shipped a comment confidently explaining a fix that did nothing. A control run caught it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix that does work
&lt;/h2&gt;

&lt;p&gt;Stop using the pipe. Write the value to a file with an encoding you control, and redirect that file into the process's stdin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$stdin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;TEMP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;guid&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.in'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;try&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="n"&gt;IO.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;WriteAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$plain&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="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;System.Text.UTF8Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$proc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Start-Process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;ComSpec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;-ArgumentList&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="s1"&gt;'/c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'thecli'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'env'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'update'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'production'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'--yes'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;-RedirectStandardInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$stdin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NoNewWindow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Wait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-PassThru&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExitCode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-ne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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="kr"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"push failed (&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExitCode&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&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="kr"&gt;finally&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="n"&gt;Remove-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$stdin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&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;Verified at the byte level, which is the only verification that means anything here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$stdin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-join&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# 83,69,67,82   &amp;lt;-- "SECR", no preamble&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things we hit on the way, in case you are doing the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The CLI needs &lt;code&gt;--yes&lt;/code&gt; to overwrite an existing variable, or it exits 1 with &lt;code&gt;confirmation_required&lt;/code&gt; — and you cannot answer the prompt, because stdin is carrying the secret.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Start-Process&lt;/code&gt; cannot launch an npm shim directly (&lt;code&gt;%1 is not a valid Win32 application&lt;/code&gt;), hence going through &lt;code&gt;%ComSpec%&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we actually got wrong
&lt;/h2&gt;

&lt;p&gt;The bug is a one-character encoding quirk. The reason it cost an hour is not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A write-only secret cannot be audited by reading it.&lt;/strong&gt; Sensitive storage removes the only check most people have. If you use it — and you should — then the verification has to be &lt;em&gt;behavioural&lt;/em&gt;, not textual: after any push, make a real call with the stored credential and assert the response. Not "the CLI said Updated". Not "the row's &lt;code&gt;updatedAt&lt;/code&gt; moved". An actual request.&lt;/p&gt;

&lt;p&gt;We had that backwards. We trusted a success message from a tool that was faithfully transmitting corruption, about a value we had deliberately made unreadable, and we only found out when something unrelated fell over with an error about character 65279.&lt;/p&gt;

&lt;p&gt;The encoding bug will bite someone else. The blind spot is the part worth fixing.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>powershell</category>
      <category>security</category>
      <category>debugging</category>
    </item>
    <item>
      <title>We audited our AI coding agent's own config. It failed.</title>
      <dc:creator>RedCapra</dc:creator>
      <pubDate>Wed, 02 Sep 2026 22:07:36 +0000</pubDate>
      <link>https://dev.to/redcapra/we-audited-our-ai-coding-agents-own-config-it-failed-450a</link>
      <guid>https://dev.to/redcapra/we-audited-our-ai-coding-agents-own-config-it-failed-450a</guid>
      <description>&lt;p&gt;Your AI coding agent runs with your permissions. All of them.&lt;/p&gt;

&lt;p&gt;If it can read a file, it reads with your account. If it can run a shell command, that command can touch everything you can touch. Most of us set up these tools in five minutes, click "allow" a few times to make the prompts stop, and never look at the resulting config again.&lt;/p&gt;

&lt;p&gt;This week we audited our own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea came from a 246,000-star repo
&lt;/h2&gt;

&lt;p&gt;We spent an evening reviewing &lt;a href="https://github.com/affaan-m/ecc" rel="noopener noreferrer"&gt;ECC&lt;/a&gt;, the viral agent-harness kit. Our verdict on installing it was no — for our setup, ~90 scripts executing on every tool call is more supply-chain surface than we'll accept, and its flagship learning system is a documented no-op on native Windows, which is what we run.&lt;/p&gt;

&lt;p&gt;But buried in it was one idea worth more than the whole repo: &lt;strong&gt;your agent tooling is part of your threat model.&lt;/strong&gt; The settings files, the hooks, the MCP server definitions, the permission allowlists — that's an attack surface, and almost nobody audits it.&lt;/p&gt;

&lt;p&gt;We ship a security scanner for a living. We had audited our web apps relentlessly. We had &lt;em&gt;never&lt;/em&gt; audited our own agent configs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we found in our own house
&lt;/h2&gt;

&lt;p&gt;Five parallel audit passes over every harness config on our build machine. Findings, in descending order of embarrassment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One repo's local settings contained &lt;code&gt;"Bash(*)"&lt;/code&gt;&lt;/strong&gt; — a blanket shell allow. Any prompt injection reaching a session in that project could run arbitrary commands with zero approval prompt. It had been sitting there since some long-forgotten session where someone (fine: we) allowed it to make a prompt go away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Another repo's settings allowed unprompted &lt;code&gt;Read&lt;/code&gt; of the entire user profile&lt;/strong&gt; — SSH keys, token caches, browser profiles, password-manager stores. Plus a &lt;code&gt;python -c&lt;/code&gt; allow, which is arbitrary code execution wearing a lab coat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth token caches were readable &lt;em&gt;and writable&lt;/em&gt; by every local account&lt;/strong&gt; on the machine — inherited NTFS permissions nobody had ever looked at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A global allow rule contradicted our own database doctrine&lt;/strong&gt; — granted once in some session, applying forever, in every project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The one that made us laugh: when our agent tried to &lt;em&gt;fix&lt;/em&gt; the global permission file, the permission classifier &lt;strong&gt;blocked the agent from editing its own permissions&lt;/strong&gt;. Correct behavior. The guard guarded the guardian, and the fix went through a human paste instead.&lt;/p&gt;

&lt;p&gt;Everything above is closed now. Total time from "let's audit" to "all HIGHs fixed": about two hours. The &lt;code&gt;Bash(*)&lt;/code&gt; had been live for weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  We turned the checklist into a free tool
&lt;/h2&gt;

&lt;p&gt;The rule set from that audit is now a scanner you can run in your browser: &lt;strong&gt;&lt;a href="https://redcapra.com/agent-scan" rel="noopener noreferrer"&gt;redcapra.com/agent-scan&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Paste your &lt;code&gt;settings.json&lt;/code&gt;, &lt;code&gt;.mcp.json&lt;/code&gt;, or hooks config and it grades what it finds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blanket and &lt;code&gt;sudo&lt;/code&gt; shell wildcards, arbitrary-exec allows (&lt;code&gt;python -c&lt;/code&gt;, &lt;code&gt;sh -c&lt;/code&gt;, &lt;code&gt;eval&lt;/code&gt;…), destructive-command allows&lt;/li&gt;
&lt;li&gt;profile-wide &lt;code&gt;Read&lt;/code&gt; grants and root-level &lt;code&gt;additionalDirectories&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;missing &lt;code&gt;.env&lt;/code&gt; read-deny nets&lt;/li&gt;
&lt;li&gt;unpinned auto-installing MCP servers (&lt;code&gt;npx -y something@latest&lt;/code&gt; executes whatever the registry serves next)&lt;/li&gt;
&lt;li&gt;credentials sitting inline in MCP/env config&lt;/li&gt;
&lt;li&gt;hook commands that interpolate tool input into shell strings, post to external hosts, or pipe downloads into &lt;code&gt;sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a few hundred lines of plain JavaScript running entirely in the page. Nothing you paste is uploaded, logged, or stored — credential-shaped values are masked before they even appear in the findings text. No account, no email gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things to check tonight, no tool required
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Grep your settings files for &lt;code&gt;Bash(*)&lt;/code&gt;&lt;/strong&gt; — and for interpreter allows like &lt;code&gt;python -c&lt;/code&gt; or &lt;code&gt;sh -c&lt;/code&gt;, which are the same thing in disguise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Look at every &lt;code&gt;npx -y&lt;/code&gt; in your MCP config.&lt;/strong&gt; Pin versions. &lt;code&gt;@latest&lt;/code&gt; means "whatever ships next runs on my machine automatically."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read your hooks like an attacker.&lt;/strong&gt; Anything interpolating &lt;code&gt;${...}&lt;/code&gt; tool input into a shell string is command injection waiting for a crafted filename. Anything posting to a non-localhost URL is an exfiltration channel — transcripts contain secrets more often than you think.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your agent is probably fine. Its config might not be. Ours wasn't — and we do this for a living.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;RedCapra is a local-first security workbench: a real 47-check scan on your site, free, findings tracked in your browser. If the agent scanner is useful, &lt;a href="https://redcapra.com" rel="noopener noreferrer"&gt;the workbench&lt;/a&gt; is the same philosophy pointed at your web app.&lt;/em&gt;&lt;/p&gt;

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