<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="https://katiekodes.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://katiekodes.com/" rel="alternate" type="text/html" /><updated>2026-07-14T21:10:31+00:00</updated><id>https://katiekodes.com/feed.xml</id><title type="html">Katie Kodes</title><subtitle>Bringing technical clarity to the unknown</subtitle><author><name>Katie</name></author><entry xml:lang="en"><title type="html">New computer day game plan</title><link href="https://katiekodes.com/new-computer-2026/" rel="alternate" type="text/html" title="New computer day game plan" /><published>2026-07-07T09:00:00+00:00</published><updated>2026-07-07T09:00:00+00:00</updated><id>https://katiekodes.com/new-computer-2026</id><content type="html" xml:base="https://katiekodes.com/new-computer-2026/"><![CDATA[<p>My PC’s been in limp mode for two years, and I finally ordered a new-to-me replacement.  Given the equipment I have on hand, and the impracticality of buying much more in 2026’s era of price gouging, here’s the plan.  <em>(How lucky that I’ve gotten to learn a lot about enterprise “endpoint” management over the last few years.  Potentially a game changer.  This will be my first round of trying to do “new laptop day” in a repeatable, low-pain fashion.)</em></p>

<!--more-->

<h2 id="day--2--before-machine-arrives">Day -2:  before machine arrives</h2>

<ol>
  <li>✔️ Learn the F-keys, so I can bootup as indicated below.  Memorize, write down, tape to monitor, or whatever.
    <ul>
      <li>Google search LLM summary says:
        <ul>
          <li>Windows in general:
            <ul>
              <li>Safe Mode:  <code class="language-plaintext highlighter-rouge">F8</code>
                <ul>
                  <li><em>(But <a href="https://us.informatiweb.net/tutorials/it/windows/windows-8-8-1-10-reactivate-the-f8-menu.html" target="_blank">first you have to reactivate it</a> from a running OS, logged in w/ admin rights.)</em></li>
                </ul>
              </li>
            </ul>
          </li>
          <li>Acer:
            <ul>
              <li>Boot Menu:  <code class="language-plaintext highlighter-rouge">F12</code> or <code class="language-plaintext highlighter-rouge">Esc</code></li>
              <li>BIOS/UEFI:  <code class="language-plaintext highlighter-rouge">F2</code> or <code class="language-plaintext highlighter-rouge">Del</code>del</li>
            </ul>
          </li>
          <li>Asus:
            <ul>
              <li>Boot Menu:  <code class="language-plaintext highlighter-rouge">F8</code> or <code class="language-plaintext highlighter-rouge">Esc</code></li>
              <li>BIOS/UEFI:  <code class="language-plaintext highlighter-rouge">F2</code> or <code class="language-plaintext highlighter-rouge">Del</code></li>
            </ul>
          </li>
          <li>Dell:
            <ul>
              <li>Boot Menu <em>(e.g. <code class="language-plaintext highlighter-rouge">WinRE</code> access)</em>:  <a href="https://www.dell.com/support/kbdoc/en-us/000113309/how-to-access-the-windows-recovery-environment-in-windows-10" target="_blank"><code class="language-plaintext highlighter-rouge">F12</code></a> <em>(when the Dell logo appears)</em></li>
              <li>BIOS/UEFI:  <code class="language-plaintext highlighter-rouge">F10</code> <em>(but maybe also hidden below <code class="language-plaintext highlighter-rouge">F12</code>?)</em></li>
            </ul>
          </li>
          <li>HP:
            <ul>
              <li>Boot Menu:  <code class="language-plaintext highlighter-rouge">F9</code> or <a href="https://h30434.www3.hp.com/t5/Notebooks-Archive-Read-Only/Change-Boot-Sequence-and-How-to-Boot-from-USB/td-p/6132655" target="_blank"><code class="language-plaintext highlighter-rouge">Esc</code></a></li>
              <li>BIOS/UEFI:  <code class="language-plaintext highlighter-rouge">F10</code></li>
            </ul>
          </li>
          <li>Lenovo:
            <ul>
              <li>Boot Menu <em>(e.g. <code class="language-plaintext highlighter-rouge">WinRE</code> access)</em>:  <a href="https://support.lenovo.com/us/en/solutions/ht104668" target="_blank"><code class="language-plaintext highlighter-rouge">F12</code></a> <em>(when the Lenovo logo appears)</em></li>
              <li>BIOS/UEFI:  <code class="language-plaintext highlighter-rouge">F1</code> or <code class="language-plaintext highlighter-rouge">F2</code>, depending on model</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>✔️ Have two spare flash USB drives handy.</li>
  <li>✔️ Have a spare USB WiFi card handy.</li>
  <li>✔️ Have enough desk space, power outlets, monitors, keyboards, mice, etc. handy for ergonomics.  Set up the desk.</li>
  <li>✔️ Have two spare USB external drives handy <em>(for sizes, see day -1:  physical reboxability)</em>.
    <ul>
      <li>✔️ <strong>Format</strong> the matchy-matchy-sized spare USB external drive meant as a “day -1” clone target.</li>
      <li>✔️ Validate the quality of that new one I’ve got sitting around.</li>
    </ul>
  </li>
  <li>✔️ Make a bootable Win11-ready backup-management flash USB and label it so I remember which one it is.</li>
  <li>✔️ Decide what I desire in my <code class="language-plaintext highlighter-rouge">autounattend.xml</code> and populate it <em>(Schneegans can help)</em>.
    <ul>
      <li>☐ Throw my favorite PowerShell scripts from version control onto it, too.  Might as well have them handy the moment the clean install is done, since the clean-install USB just turns into a normal file USB after clean-install and first-login.</li>
      <li>☐ Ditto the installer <code class="language-plaintext highlighter-rouge">.exe</code> for my favorite backup-scheduling software – might as well have it handy; there’s probably plenty of room to spare on the clean-install USB flash drive.</li>
      <li>✔️ Biggest outstanding question:  exactly how much drive formatting of the new PC’s internal disk will I want Win11-unattended-install to perform?
        <ul>
          <li><em>(It could be nice to leave the recovery partition the way the new PC vendor had it set up for me.)</em>
            <ul>
              <li><em>(Decided:  looks like I already had it making its own recovery partition.  Leaving it as it was.)</em></li>
            </ul>
          </li>
        </ul>
      </li>
      <li><em>(Loaded old file back into Schneegans’s tool and proofread it.  Looks good to me.)</em>
        <ul>
          <li>‼️ WARNING!  I keep my version-controlled copy set with a product key prepopulated that’s all 0s, which is good for that, but bad for install.
            <ul>
              <li>On “day -2,” when making this USB, actually bother to set it to the real license key I want to use or the clean-install will take its version from the UEFI-stored key.
                <ul>
                  <li><em>(Fix:  just clean-install again once I have the real product key in there, this time with the USB set up correctly.)</em></li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>‼️ Another consideration:  this computer was easy because I’m rocking a 1-big-disk <code class="language-plaintext highlighter-rouge">C:\</code> drive setup and hoping for the best, but if I’d had 2 internal disks, I’d want this, as well as some of my “day 0” steps, to deal w/ getting user accounts’ documents and stuff set up onto a secondary <code class="language-plaintext highlighter-rouge">D:\</code> drive.</li>
    </ul>
  </li>
  <li>🤷‍♀️ Make a bootable Win11-clean-install <em>(download latest from Microsoft to reduce later update lag)</em> flash USB with my <code class="language-plaintext highlighter-rouge">autounattend.xml</code> on it in the appropriate way.
    <ul>
      <li>✔️ Burn it, using my <code class="language-plaintext highlighter-rouge">prepare-oscleaninstall-bootdrive.ps1</code> script I already wrote.</li>
      <li>✖️ <strong>Validate</strong> that it works as desired by clean-installing a VM with it, using a spare Win11 key of my own, on one of my spare computers that’s already rocking an all-purpose hypervisor.
        <ul>
          <li><em>(Skipped; felt lazy)</em></li>
        </ul>
      </li>
    </ul>
  </li>
  <li>✔️ Have “my usual daily backup” USB external drive handy <em>(needed on day 0+)</em>.</li>
</ol>

<hr />

<h2 id="day--1--make-physical-machine-reboxable">Day -1:  make physical machine reboxable</h2>

<p>My new computer’s under warranty, so if I realize, at some point, that I’ve got a lemon, I might need to be able to restore it back into the exact shape in which I got it.</p>

<p><em>(Note:  “day -1” involves a lot of waiting on disk I/O against hacky old disks and USB adapters that are all I’m willing to pay for in this era of price gouging, particularly if anything goes wrong and has to be repeated or done in a slower sector-by-sector way, so, seriously, expect it to take a whole day, if not more.  Do not get excited about moving on to “day 0” today, and perhaps not even tomorrow or the next day.  Schedule a lot of long walks outside and chopping vegetables / folding laundry inside.)</em></p>

<h3 id="-1a--physical-inspection">-1A:  physical inspection</h3>

<ol>
  <li>✔️ Unbox.</li>
  <li>✔️ Pop the case but don’t touch anything.</li>
  <li>✔️ Open a support ticket if anything visually looks wrong.
    <ul>
      <li><em>(It didn’t.)</em></li>
    </ul>
  </li>
  <li>✔️ Put the lid back on.</li>
  <li>✔️ Plug in power, and a keyboard, mouse, and monitor.</li>
</ol>

<h3 id="-1b--disk-backup">-1B:  disk backup</h3>

<ol>
  <li>✔️ Plug in two USB external storage drives:
    <ol>
      <li>✔️ A just-formatted drive of equal size to the drive shipped inside new PC.</li>
      <li>✔️ A big ol’ drive with at least as much space free as the drive shipped inside the new PC.</li>
    </ol>
  </li>
  <li>✔️ Plug in my bootable USB flash drive that comes w/ my backup-management software on it.</li>
  <li>✔️ Power up the new PC and quickly press the appropriate F-key to make it boot into the backup-management flash USB.</li>
  <li>🤷 Clone the new PC’s internal disk onto the USB drive of equal size.
    <ul>
      <li><em>(Stymied, haven’t figured out how to make it happen.  Something’s reporting as wrong with the master file table (“MFT”) of the <code class="language-plaintext highlighter-rouge">C:\</code> partition of the drive shipped inside the new PC.  Best I could do was restore from the full-image, which seems to report slightly different partition sizes, but oh well.  Further compressed imaging works against the restore pseudo-clone as a source, but no compressed imaging works against the internal drive.)</em></li>
    </ul>
  </li>
  <li>🤷‍♀️ Image the new PC’s internal disk as a file on the free space of the big USB drive.
    <ul>
      <li><em>(Not thrilled about doing a no-compression every-sector image, because I hate the idea of having to leave this much space occupied on my spare USB disk for the whole time the warranty’s valid, and it’s taking so much longer than it needs to when the factory disk is only about 60GB full across all its partitions put together, but at least it doesn’t fail as soon as it starts, so it might be the only thing I can get to work!  Will definitely want to skip to <strong><code class="language-plaintext highlighter-rouge">-1E</code></strong> VM validation right away, if this is the only backup I’m going to be able to preserve of the “just-unboxed” internal drive state.)</em>
        <ul>
          <li>✔️ Big-image succeeded.  Now using it to “restore” onto the “equal-sized disk”, as the next-best thing to a clone.  I just noticed that the equal-sized disk is actually a few GB smaller than the internal disk, so maybe that was the problem with the clone.
            <ul>
              <li>✔️ See if compressed images will work <em>now</em>, either from the internal disk or this freshly-pseudo-cloned one, using the “big” USB thing as the file target.
                <ul>
                  <li><em>(Only from the restored pseudo-clone, which backup tool shows isn’t exactly the same occupied size per partition.  Dang.)</em></li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>✔️ Power down the new PC and unplug both USB storage drives.</li>
</ol>

<h3 id="-1c--os-license-backup-postponed">-1C:  OS license backup (postponed)</h3>

<p>Note:  no luck, can’t seem to find a way to get into it.  Will just have to table until “day 0” at end of clean install.</p>

<ol>
  <li>☐ Leave the backup-management flash USB in for now, in case it helps w/ the PowerShell below.</li>
  <li>☐ Power up the new PC and quickly press the appropriate F-key to get into a PowerShell CLI that can help me extract the OEM Win11 key shipped by the new PC’s vendor.  <em>(Might be booting into my backup-management flash USB; might be booting into the internal hard drive’s recovery mode or something.)</em>
    <ul>
      <li>WinRE from <code class="language-plaintext highlighter-rouge">X:\</code> just has <code class="language-plaintext highlighter-rouge">cmd.exe</code> with a lot of commands missing or incompatible with WinRE/WinPE modes, so haven’t been able to get it off that on the backup-management flash USB.  Waiting for backup attempts to complete so I can reboot into system boot menu &amp; see if there’s some sort of GUI copy of the OS license key, or to see if anything that came w/ the computer’s WinRE/WinPE works any better than the one from my backup-management flash USB.</li>
    </ul>
  </li>
  <li>☐ Write down the OEM Win11 key on paper, and also put it into a cloud-based secrets vault.</li>
  <li>☐ Power down the new PC and pop out the backup-management flash USB.</li>
</ol>

<h3 id="-1d--validate-os-license-backup-quality-cancelled">-1D:  validate OS license backup quality (cancelled)</h3>

<ol>
  <li>(cancelled:)  Validate that the OEM Win11 key works by trying it out in an autounattended clean-install Win11 VM, on one of my spare computers that’s already rocking an all-purpose hypervisor.
    <ul>
      <li>Update:  Don’t do this!  My colleague thinks they recall that Windows user licenses shipped with PCs are somewhat bound to hardware, so testing them on a different computer (or VM) could either:
        <ul>
          <li>invalidate it for my new PC, or at least</li>
          <li>remove one allowed hardware update of the new computer from the license.</li>
        </ul>
      </li>
    </ul>
  </li>
</ol>

<h3 id="-1e--validate-disk-backup-quality">-1E:  validate disk backup quality</h3>

<ol>
  <li>✖️ Validate that the big-USB-drive image works as expected by seeing what happens when I boot it up in a VM, on one of my spare computers that’s already rocking my backup-management vendor’s specialized hypervisor.
    <ul>
      <li>Maybe repeat a few times to make sure that even if I proceed into setup, if I start up a fresh VM w/ that image, it always loads into the first-boot sequence and always lets me set up Windows as a clean first-boot sequence.</li>
      <li><em>(Skipped; felt lazy when it didn’t finish bootup right away.)</em></li>
    </ul>
  </li>
</ol>

<h3 id="-1f--organization">-1F:  organization</h3>

<ol>
  <li>☐ Label the two backups with sticky notes, etc. as being what I’ll need before initiating any sort of new-PC return if I have to make a warranty claim.</li>
  <li>☐ Put the two backups into appropriate long-term storage <em>(airgapped, cloud, etc.)</em>.</li>
</ol>

<h3 id="-1g--sleep-peacefully-reboxably">-1G:  sleep peacefully (reboxably)</h3>

<p>Congratulations, me!</p>

<p>This physical machine can now feel comfortably “mine” <em>(because I now have a “vendor’s” restoration plan)</em>.</p>

<hr />

<h2 id="day-0--install-clean-os">Day 0:  install clean OS</h2>

<h3 id="0a--prepare-the-internal-disk-if-desired">0A:  prepare the internal disk if desired</h3>

<ol>
  <li>✖️ If I don’t have my clean-unattended-install’s <code class="language-plaintext highlighter-rouge">autounattend.xml</code> configured to do drastic formatting of the new PC’s internal disk, consider booting off my backup-management flash USB and using its PowerShell to wipe the new PC’s internal disk clean and format it.
    <ul>
      <li><em>(Unsure if I really want to do this.  It could be nice to leave the recovery partition the way the new PC vendor had it set up for me.)</em></li>
      <li><em>(Looks like it’ll wipe for me, based on Schneegans’s reinterpretation of how I have my file set up.)</em></li>
    </ul>
  </li>
</ol>

<h3 id="0b--clean-install">0B:  clean install</h3>

<ol>
  <li>✔️ Plug in my bootable unattended-clean-install USB flash drive.</li>
  <li>✔️ Power up the new PC and quickly press the appropriate F-key to make it boot into the unattended-clean-install flash USB.</li>
  <li>✔️ Do the install, and any weird little things that had to be done manually, e.g.
    <ul>
      <li>✔️  I think I remember that I prefer not to hardcode in passwords for secondary OS user accounts into <code class="language-plaintext highlighter-rouge">autounattend.xml</code>, so I need to do those manually</li>
      <li>✖️ <em>(If I had 2 internal drives, I’d want documents and such for all user accounts on the <code class="language-plaintext highlighter-rouge">D:\</code> drive.)</em>.</li>
    </ul>
  </li>
  <li>Power down the new PC and pop out the unattended-clean-install flash USB.</li>
</ol>

<h3 id="0c--online-updates">0C:  online updates</h3>

<ol>
  <li>✔️ Power up the new PC…
    <ul>
      <li>Optional:  …and quickly press the appropriate F-key to make it boot into the internal disk, if I’d rather leave it on that as primary</li>
    </ul>
  </li>
  <li>✔️ Log into my clean install.</li>
  <li>⌛ Give it internet access and let it run Windows Update, etc.
    <ul>
      <li>Note:  keep a USB wifi card handy.  Clean-install might’ve knocked out the OS having a driver for, &amp; being able to see, the built-in WiFi card.
        <ul>
          <li><em>(Alternatively, I can probably get a <code class="language-plaintext highlighter-rouge">.exe</code> on another computer for the new PC’s serial number and throw it onto a thumb drive, if I don’t want to have to deal with my WiFi card being named “WiFi 2” after you get that <code class="language-plaintext highlighter-rouge">.exe</code> with the USB Wi-Fi card.)</em></li>
        </ul>
      </li>
      <li>Note:  open a browser, go to the vendor’s web site, enter the serial number, get told to download and install their creepware, and be too tired to decide to do everything manually and just let it creep on my computer because its splash page promised it wouldn’t.  Well, and then do the “download all” of all the manual drivers, too, for good measure, out of paranoia.
        <ul>
          <li>☐ Well, that didn’t go so well, and I don’t know in what order to run all these downloaded <code class="language-plaintext highlighter-rouge">.exe</code> files.  I should probably put them into version control, and also should probably script running them as I figure it out, in case I ever need to do a fresh clean install, and put that into version control, too.  That or I should add a step to the top of this “day 0” to use Schneegans to modify <code class="language-plaintext highlighter-rouge">autounattend.xml</code> to do the driver installation after grabbing them all once the hardware arrives and I know my service tag number.  <em>(Actually, I suppose that could also be in parallel on “day -1” alongside unbox-backup.)</em></li>
        </ul>
      </li>
    </ul>
  </li>
</ol>

<h3 id="0d--validate-secure-boot-certificates">0D:  validate secure boot certificates</h3>

<ol>
  <li>✔️ Reboot and quickly press the appropriate F-key and see if that one June 2026 UEFI issue with Microsoft certificates needs attention.  Fix if so.
    <ul>
      <li><em>(Was already up-to-date as shipped; yay.)</em></li>
    </ul>
  </li>
</ol>

<h3 id="0e--clean-up-clean-install-usb">0E:  clean up clean-install USB</h3>

<ol>
  <li>✔️ Set the product key in my <code class="language-plaintext highlighter-rouge">autounattend.xml</code> file on the clean-backup USB back to all 0s.</li>
</ol>

<h3 id="0f--nap-peacefully-cleanly">0F:  nap peacefully (cleanly)</h3>

<p>Congratulations, me!</p>

<p>I am now bootable into my accounts on a cleanly-installed Win11 operating system.</p>

<h3 id="0g--schedule-recurring-backup">0G:  schedule recurring backup</h3>

<ol>
  <li>✔️ Install, and punch my license key into, my backup-management desktop software, on the new PC.
    <ul>
      <li>Note:  to figure out which installation settings to check in my backup-management software, do add or remove programs -&gt; modify on an old computer’s installation and see what I had it as</li>
    </ul>
  </li>
  <li>Plug in the USB drive I plan to use for “my usual daily backup” and give it its usual drive letter mapping.</li>
  <li>Set up, and kick off a first run of, regularly scheduled backup imaging of the new PC’s internal disk.</li>
</ol>

<h3 id="0h--validate-recurring-backup">0H:  validate recurring backup</h3>

<ol>
  <li>Eject the “usual daily backup” drive.</li>
  <li>Validate whether the just-made image’s file contents are explorable from one of my spare computers that has my backup-management desktop software also installed.</li>
  <li>If not, troubleshoot until they are.</li>
</ol>

<h3 id="0i--resume-recurring-backup">0I:  resume recurring backup</h3>

<ol>
  <li>Plug the “usual daily backup” drive into the new PC <em>(and possibly velcro it onto the case)</em>, so that it’ll be ready for the next scheduled run.</li>
  <li>Power down the new PC; day 0 is done.</li>
</ol>

<h3 id="0j--sleep-peacefully-cleanly-and-managedly">0J:  sleep peacefully (cleanly and managedly)</h3>

<p>Congratulations, me!</p>

<p>I’ve now basically got this lump of metal set up like “new-laptop-day” feels in an enterprise.  It’s cleanly imaged, and it’s auto-managed appropriately.</p>

<hr />

<h2 id="day-1--customize-and-restore-personality">Day 1:  customize and restore personality</h2>

<p>Congratulations, me!  I’ve just been issued a well-managed “new laptop” by my “enterprise endpoint management” department <em>(heh – me)</em>.</p>

<p>Time to make it more than an OS – time to make it a <strong>system</strong> that I can truly call <strong>MINE</strong>.  💃</p>

<p>Remember, I’m working off a <strong>clean OS install</strong>, so I’ve got a little bit more to do than I might in, say, a “rollback” to an old backup of a well-worn image.</p>

<ol>
  <li>I’ve got <strong>meaningful executables</strong> to install before bringing over files.</li>
  <li>When I bring over <strong>meaningful files</strong> from wherever they currently live, I’ll need both:
    <ul>
      <li>a lot of config-related files <em>(e.g. for all those executables)</em> &amp; commands-to-be-run that might already be present/configured in, say, a “rollback” to an old backup of a well-worn image</li>
      <li>“the usual” <em>(my pictures &amp; documents, etc.)</em></li>
    </ul>
  </li>
</ol>

<p>If I want to get really paranoid, I can manually back up the new PC’s internal disk after each major piece of work, but remember, I’ve also already got dailies going.</p>

<p><strong>IMPORTANT:</strong>  write things down into remote-backed-up version control.  Preferably automating as I go w/ a “GitOps” / “paper plates, not fine china; cattle, not pets” mentality, as, say, idempotent PowerShell scripts.  But at the very least as Markdown files / PowerShell comments / etc. <em>(lol, the notes as the Git; my hands and eyes as the Ops.)</em></p>

<ul>
  <li>Why:  This computer, too, will blue-screen-of-death on me one day, and a major life improvement I hope to start engaging in with this new-computer process is to make “<strong>clean install to full personality</strong>” far less <strong>toil</strong> &amp; <strong>duration</strong> than it’s been historically.</li>
</ul>

<h3 id="notes-as-i-work">Notes as I work</h3>

<ul>
  <li>Saving things not on thumb drives to <code class="language-plaintext highlighter-rouge">%USERPROFILE%/tempyyyymm</code> folder for now, to make it easier to just lift-and-shift <code class="language-plaintext highlighter-rouge">Documents</code> and such <em>(trying to leave those empty)</em>.</li>
  <li>Notepad:  turn Copilot off, autocorrect off, spell check off, autosave off, word wrap off.</li>
  <li>For some reason, even though this computer totally has a WiFi card, I must have managed to destroy Windows’s awareness of it with my <code class="language-plaintext highlighter-rouge">autounattend.xml</code> or something.  <code class="language-plaintext highlighter-rouge">Network &amp; Internet</code> settings -&gt; <code class="language-plaintext highlighter-rouge">Advanced Network Settings</code> -&gt; <code class="language-plaintext highlighter-rouge">Network reset</code> and letting it restart didn’t help.  Hmmmm, maybe the clean install didn’t pick up on this hardware’s driver.  🙁</li>
</ul>

<hr />

<h2 id="week-2--decommission-the-old-computer">Week 2:  decommission the old computer</h2>

<ol>
  <li>At some point, make my final backup image of the old computer’s disks and label them well.
    <ul>
      <li><em>(Try booting the image up in a VM on a spare computer with a backup-management vendor’s hypervisor, if I want to validate that they really-really work.)</em></li>
    </ul>
  </li>
  <li>To force my hand, boot the old computer off my backup-management flash USB and use its PowerShell to wipe its internal disks clean and format them.  Yes, all the way – even recovery partitions.  I want to completely sever <em><strong>all</strong></em> attachment to this computer’s former personality.  I have a new computer now, and its personality is my new daily-driver PC-personality.</li>
  <li>Power down the old computer, pull out the backup-managent flash USB, and put the old computer into a closet until I figure out what exactly it’s “for.”
    <ul>
      <li><em>(Theoretically, I might be able to clean-image it and get the stupid thing to stop blue screen of deathing, and then have a spare computer for … unsure what, but … something.)</em></li>
      <li><em>(Maybe if I get my “days -1 to 1” work automated enough, I can occasionally practice doing full “clean install and re-personality-population” failover drills on it, and have it handy in case the new PC, or some other PC in my care, starts BSOD-ing?)</em></li>
    </ul>
  </li>
  <li>Clean up legacy backup images from the old PC, keeping just the final validated backup image.  The rest are no longer needed; that computer’s personality no longer exists, so older editions of that personality no longer need restoration ever again.  And in today’s disk prices, I need to free up unused gigabytes for keeping my active fleet backed up!</li>
  <li>Clean up the desk from being such a “job site” – get everything all tidied up the way I “normally” like having it.
    <ul>
      <li><em>(Including getting visually appealing new side tables, or mounting equipment if it seems like the desk can handle the weight, or whatever, since I switched form factor when I picked my new PC.)</em>
        <ul>
          <li>It looks like the vendor made a VESA monitor stand that holds the new PC.  Find one <em>(<strong>buy</strong>)</em>, as well as a monitor in the size I like with additional fast USB ports aplenty, as well as built-in speakers, mic, and webcam <em>(<strong>buy</strong>)</em>, to attach onto the VESA stand.</li>
        </ul>
      </li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="aftermath-miscellany">Aftermath miscellany</h2>

<ol>
  <li>Speaking of my Win11 keys, <strong>write down</strong> all those spare Win11 keys I own but haven’t taken the time to write down yet, before something happens to destroy the originals.
    <ul>
      <li><em>(Put it on the backlog with the crafts for my relatives and the website migrations for my friends.)</em></li>
    </ul>
  </li>
  <li>Vaguely keep an eye out for parts deals <em>(memory, internal drives, external drives, DVD drive, etc.)</em> and possibly hoard a smidge.
    <ul>
      <li>One day, after it’s already out of warranty anyway, I’m going to want to upgrade the new PC, or add better backup to more PCs, or build a NAS or something, and parts ain’t what they used to be, in terms of price.</li>
    </ul>
  </li>
  <li>Vaguely keep an eye out for deal-of-the-millennium PC deals, since while this was a decent new PC, it was a little bit of a desperation PC, and for the right price, it could be nice to start this all over again yet again but be happier with the setup for longer.</li>
  <li>Remember to stay on top of all my various backup &amp; recovery drills that I decide are worth keeping myself engaged in.  All PCs can suddenly blue screen of death, and this new PC is no exception.
    <ul>
      <li>Ditto for all the other PCs in my care.</li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="related-links">Related links</h2>

<ul>
  <li>My “<a href="https://katiekodes.com/terraform-vs-ansible/" target="_blank">Choosing Terraform vs. Ansible</a>” article, where I also mulled over the “Day (insert number here)” concepts, and some Gartner articles from which I learned them:
    <ul>
      <li>Gartner’s “<a href="https://www.gartner.com/en/documents/5647823" target="_blank">How to Automate Server Provisioning and Configuration Management</a>”</li>
      <li>Gartner’s “<a href="https://www.gartner.com/en/documents/5962139" target="_blank">Reference Architecture Brief: Infrastructure Automation and Orchestration</a>”</li>
      <li>Gartner’s “<a href="https://www.gartner.com/en/documents/6796834" target="_blank">Best Practices for Infrastructure as Code Management and Governance</a>”</li>
    </ul>
  </li>
</ul>]]></content><author><name>Katie</name></author><category term="windows" /><category term="devops" /><summary type="html"><![CDATA[Fleet-managing new hardware]]></summary></entry><entry xml:lang="en"><title type="html">Microsoft 365’s Agent Registry should list tools</title><link href="https://katiekodes.com/m365-agent-registry-needs-tools/" rel="alternate" type="text/html" title="Microsoft 365’s Agent Registry should list tools" /><published>2026-06-29T09:00:00+00:00</published><updated>2026-06-29T09:00:00+00:00</updated><id>https://katiekodes.com/m365-agent-registry-needs-tools</id><content type="html" xml:base="https://katiekodes.com/m365-agent-registry-needs-tools/"><![CDATA[<p>Microsoft’s new Agent 365 <a href="https://learn.microsoft.com/en-us/microsoft-365/admin/manage/agent-registry" target="_blank">Agent Registry</a> should list desktop IDE client tools like the GitHub Copilot CLI, GitHub Copilot VSCode Chat pane, etc.  Anything less sells enterprises a security story that isn’t meaningful.</p>

<!--more-->

<p>Microsoft Entra Agent ID product manager <a href="https://entra.news/p/from-windows-core-to-leading-agent" target="_blank">Vince Smith just came on episode 64 of Merrill Fernando’s “Entra Chat” podcast</a> and shouted out a colleague’s project, the <a href="https://learn.microsoft.com/en-us/microsoft-365/admin/manage/agent-registry" target="_blank">M365 Agent Registry</a>.</p>

<p>Problem is, the M365 Agent Registry’s built-in Microsoft-authored agent listings don’t include client-side “chat UI tools” like GitHub Copilot CLI and the GitHub Copilot VSCode Chat pane.</p>

<p>Which means your average enterprise customer can’t <em>actually</em> get a good view of what’s <strong>behaving</strong> “agentically” on their staff members’ behalf.</p>

<p>Over a year ago in May 2025, I didn’t write my “<a href="https://katiekodes.com/securing-authenticated-ai/" target="_blank">securing authenticated agentic AI</a>” post about the kinds of computer processes Microsoft 365 seems to be considering “agents” – I wrote it the moment it hit me just how bad of “<a href="https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/" target="_blank">lethal trifecta</a>” trouble everyday corporate-employee <em><strong>software developers</strong></em> could get themselves into with the <strong>GitHub Copilot VSCode Chat pane</strong>, their usual enterprise productivity SaaS accounts like email or JIRA, and an MCP server logged into those accounts.</p>

<h2 id="the-threat-model">The threat model</h2>

<p>While I was thinking about data integrity’s resistance to malice, George Fletcher, an identity specialist, gave a great example of the need for data integrity in the face of mistakes, in his June 2026 article “<a href="https://www.linkedin.com/pulse/authorization-problem-we-keep-half-solving-george-fletcher-hueee" target="_blank">The Authorization Problem We Keep Half-Solving</a>:”</p>

<blockquote>
  <p>I want to start by considering the following hypothetical. Alice asked her AI travel assistant to book a long weekend in Lisbon for her and her husband. Flights, a hotel near Alfama, a dinner reservation on Saturday night, a rental car for a day trip to Sintra.</p>

  <p>Imagine it works. Mostly. The hotel booking goes through. The flight doesn’t, because the airline’s website rejects the agent’s session as “unrecognized device.” The restaurant reservation lands at the wrong restaurant (a similarly named place across town), and there’s no clean way to know whether the agent has exceeded Alice’s budget along the way, because no one has actually told it what its budget is. Alice just said “book us a nice weekend.” The agent inferred the rest.</p>
</blockquote>

<p>I can’t remember where, but people followed up with all sorts of interesting comments and quote-posts, including, for example, the idea that when figuring out how we got to a point where suddenly Alice has overdraft fees in her bank account, 2 nonrefundable tickets to the north side of Portugal and no car booking yet a weekend’s nonrefundable reservation at the most expensive middle-of-nowhere boutique B&amp;B on the south side of Portugal, there’s a ton of stuff besides “it was this agent” and “it was Alice’s account” that would be helpful during root cause analysis to have logged.</p>

<p>For example:</p>

<ul>
  <li>Had Alice granted the agent read access double-check her bank account balance before booking things?</li>
  <li>Even if so, could that have helped – that is, did the agent even have a “do arithmetic” tool available to it?</li>
  <li>What likely went into the agent deciding that Alice’s word “<strong><code class="language-plaintext highlighter-rouge">nice</code></strong>” should trump other things, like Alice’s actual funds left?  For example:
    <ul>
      <li>What model was the agent trained on?</li>
      <li>While the agent ran, did it go out and read travel blogs, where one blog post said “land in northern Portugal – there’s light rail from the airport to everywhere you could want to go and you won’t even need a car!” while another blog post said “there’s nowhere in all of Portugal going except for this one southern Portuguese rural B&amp;B”?</li>
    </ul>
  </li>
</ul>

<h2 id="tools-can-act-agentically-too">Tools can act agentically too</h2>

<p>Unfortunately for Microsoft’s enterprise customers, there’s nothing about this Portugal nightmare that needs Alice’s “<strong>AI travel assistant</strong>” to be whatever it is that M365 might have decided “counts” as “an agent.”</p>

<p>Alice’s Portugal disaster <em><strong>totally</strong></em> could’ve happened through a basic desktop productivity tool like GitHub Copilot!</p>

<p>In other words, Microsoft’s omission of GitHub Copilot and its variants from the M365 Agent Registry’s listing of “Microsoft-authored” agents means that enterprise customers aren’t actually getting the <strong>observability</strong> into threats that Microsoft leadership is going around on podcasts promising M365 Agent Registry provides.</p>

<p>Yikes.</p>

<p>As Vince pointed out on episode 64 this weekend, the “lobsters” / “claws” as in “OpenClaw” proved to Microsoft’s leadership that they needed to avoid thinking of “agents” as services that only execute on <strong>servers</strong> that are <strong>remote</strong> to Alice.</p>

<p>But I challenge Vince and his colleagues at Microsoft to keep going.  I challenge Microsoft’s leadership to stop thinking of “agents” as compute processes that only begin execution in response to events that happen when a human has long since walked away from the machine on which the agent is executing <em>(e.g. a scheduled operating system task waking OpenClaw back up to re-check flight prices, because an earlier run of OpenClaw decided it seemed like a good idea to schedule that task)</em>.</p>

<p>Hyperscaler product managers, please pay attention:  even a <strong>highly interactive</strong> desktop client chat UI “<strong>tool</strong>” like the GitHub Copilot CLI or the GitHub Copilot VSCode chat panel can, with Alice sitting <em>right there</em> patiently sipping coffee and waiting for the chat prompt’s “send” button to stop spinning, <strong>book the wrong trip to Portugal</strong>.  And your enterprise customers <strong>need to know that</strong> when they look through products like M365 Agent Registry – that’s precisely what they turn to M365 Agent Registry to learn.</p>

<p>GenAI “tools” can behave <strong>agenticALLY</strong> <em>(even at their most basic, the IDEs write content to OS files!)</em>, which means they 100% belong listed in “agent registries.”  They are 100% part of what your enterprise leadership want to sleep well at night knowing they learned about when they poke through an “agent registry” trying to observe the threat landscape.</p>

<h2 id="distinguishing-tools-vs-agents-is-not-useful-here">Distinguishing tools vs agents is not useful here</h2>

<p>I just learned that <a href="https://www.tomshardware.com/tech-industry/artificial-intelligence/bots-have-now-passed-human-traffic-online-cloudflare-boss-laments-says-agentic-traffic-wasnt-expected-to-eclipse-real-people-until-next-year">CloudFlare reported 57.5% of web traffic they screen coming from bots instead of humans</a>, to which <a href="https://x.com/CurtTigges/status/2062303274380972087">Curt Tigges commented</a>:</p>

<blockquote>
  <p>“I think it’s worth distinguishing between ‘bots’ and ‘agents’; most bot traffic is definitely not agents, it’s (deterministic screen-scraping) scripts.”</p>
</blockquote>

<p>But then <a href="https://x.com/eastdakota/status/2062304365264752642">CloudFlare’s CEO defended</a> focusing on the supercategory, saying:</p>

<blockquote>
  <p>“Bot / Crawler / Agent are all synonyms depending on whether you want them to be a good or bad thing, normatively.”</p>
</blockquote>

<p>I think we’ve got a similar thing going on here – this is not the time to be pedantic and miss out on exposing crucial business information because it “didn’t count.”</p>

<p>Yes, I understand that creating fine-grained <a href="https://en.wikipedia.org/wiki/Taxonomy">taxonomies</a> have their <a href="https://en.wikipedia.org/wiki/Celestial_Emporium_of_Benevolent_Knowledge">use in human thinking</a>, I really do.  <em>(Heck, it’s the core of what George Fletcher tries to name in his followup post, “<a href="https://www.linkedin.com/pulse/framework-delegated-authorization-george-fletcher-ubcxe" target="_blank">A Framework for Delegated Authorization</a>.)</em></p>

<ul>
  <li><em>(Aside:  shoutout to my French teacher for making us read Michel Foucault’s “Order of Things” preface.  I swear I link to that “Celestial Emporium” article monthly in these times of rapid change naming the ways humans solve IT problems.  The humanities are such awesome foundational training for adulthood.)</em></li>
</ul>

<p>Yes, I get that there are times when it’s important to come up with names that break up the whole world of “LLM-driven software that can nondeterministically, at machine speed, cause ‘write’ side effects that might not have been the actual intention of whoever thought LLM-driven computation might be a great way to solve a given problem” along questions like:</p>

<ol>
  <li>Which of the following types of invocation typically kick off the LLM-driven computation’s execution?
    <ul>
      <li>Something potentially unattended, like a webhook / clock?  <strong>or</strong></li>
      <li>Something tightly and more or less actively “attended” by a human through a UI like a chat where the human is sitting around waiting for the computation to complete within a matter of seconds or minutes, before issuing the next instruction?  <strong>or</strong></li>
    </ul>
  </li>
  <li>On what kind of machine does the LLM-driven computation kick off?
    <ul>
      <li>A “client” <em>(e.g. laptop / smartphone operating system software; e.g. a web application as visited through a web browser, etc.)</em>? <strong>or</strong></li>
      <li>A “server”?</li>
    </ul>
  </li>
</ol>

<p>But I don’t think this is one of those times.</p>

<p>Deciding which <strong>agentic-behavior-capable</strong> products authored by Microsoft belong in the “Microsoft-authored agents” section of the M365 registry has only one right answer to me – <strong>all of them.</strong></p>

<p>Microsoft – call them <strong>all</strong> “agents,” because they can <strong>all</strong>, nondeterministically and at machine speed, drain a company bank account on booking the wrong nonrefundable trip to Portugal.</p>]]></content><author><name>Katie</name></author><category term="security" /><category term="iam" /><summary type="html"><![CDATA[They can do as much damage as agents]]></summary></entry><entry xml:lang="en"><title type="html">GitHub Actions Agentic Workflows</title><link href="https://katiekodes.com/github-actions-agentic-workflow/" rel="alternate" type="text/html" title="GitHub Actions Agentic Workflows" /><published>2026-06-16T15:00:00+00:00</published><updated>2026-06-16T15:00:00+00:00</updated><id>https://katiekodes.com/github-actions-agentic-workflow</id><content type="html" xml:base="https://katiekodes.com/github-actions-agentic-workflow/"><![CDATA[<ol>
  <li><a href="https://github.com/kkgthb/ansible-02/blob/main/.github/workflows/demo_github_actions_workflow.yml" target="_blank">This is a <strong>deterministic CI/CD pipeline</strong></a>, authored in YAML <em>(a classic GitHub Actions “workflow”)</em>.</li>
  <li><a href="https://github.com/mnkiefer/juice-shop/blob/main/.github/workflows/dependabot-burner.md" target="_blank">This is a <strong>nondeterministic CI/CD pipeline</strong></a>, authored in Markdown <em>(a public-preview GitHub Actions “agentic workflow”)</em>.</li>
</ol>

<p>I’m not sure how to feel about that.  Lots of “lethal trifecta” <em>(see <a href="https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/" target="_blank">Simon Willison’s blog</a>)</em> and “software supply chain security” <em>(see <a href="https://nesbitt.io/" target="_blank">Andrew Nesbitt’s blog</a>)</em> issues to be explored, that’s for sure.</p>

<!--more-->

<hr />

<h2 id="agentic-ops">Agentic ops</h2>

<p>Update:  I got to have a great conversation with some other developers about the promises and threats of LLM GenAI-based approaches to troubleshooting operational issues.</p>

<p>First, I clarified:</p>

<blockquote>
  <p>“Like this?</p>

  <ol>
    <li>“Letting an LLM nondeterministically use its embedded powers of probability to <a href="https://www.usenix.org/publications/loginonline/ai-pipeline-reliability-lessons-adding-llm-cicd" target="_blank">decide</a> amongst the following options for how a given error in <a href="https://devops.com/cdevents-simplifies-ai-ready-developer-platforms/" target="_blank">CI/CD pipeline</a> logs is best handled:
      <ul>
        <li>by quietly running diagnostics and authoring a pull request and running regression tests against the pull request it just authored, <strong>vs.</strong></li>
        <li>by Slack-pinging a repo owner</li>
      </ul>
    </li>
    <li>“Rather than, say, hard-coding a deterministic rule of:
      <ul>
        <li><strong>if</strong> this error, and if repeated 5 times or more in 30 seconds,</li>
        <li><strong>then</strong> Teams-ping a repo owner”</li>
      </ul>
    </li>
  </ol>
</blockquote>

<h3 id="history-of-ai-ops">History of AI ops</h3>

<p>I pondered, about the idea of programming such things using English as a programming language:</p>

<blockquote>
  <p>“Yeah, I mean, probability-based approaches to troubleshooting have definitely existed as <strong>service operations</strong> techniques used for the last decade+ at adequate levels of <strong>scale</strong>.</p>

  <p>“Having a bit of ‘machine learning’ <a href="https://www.plural.sh/blog/ai-powered-anomaly-detection-kubernetes/" target="_blank">helping constantly readjust the threshholds</a> at which a questionably performing container in a Kubernetes cluster, for example, gets destroyed and recreated, rather than just setting and forgetting it at ‘XYZ must be &lt;90%.’</p>

  <p>“I think it was previously mostly seen at massive scale of service traffic, though, because <em>programming</em> older probability-based tools was a lot harder than writing plain English, so you had to have a bunch of data science PhDs embedded in the ops teams to get it to work right, or whatever.</p>

  <p>“I suppose an advantage to having all of those probability and statistics PhDs running around, though, is that they’ve got that deep level of familiarity with when a nondeterministic probability-based solution ain’t the right solution.</p>

  <p>“It’ll probably be both a blessing and a curse for it to be accessible to the rest of us to try to make that architectural/design decision, for any given solution implementation.”</p>
</blockquote>

<h3 id="dangers-of-ai-ops">Dangers of AI ops</h3>

<p>I also think that as a culture, we haven’t yet latched onto widespread understanding of what it means to be <strong>deterministic</strong> vs. <strong>nondeterministic</strong>, so most of us tend to presume if it’s a computer, it behaves more or less deterministically, because that’s how they <em>did</em> behave for decades.</p>

<ul>
  <li>We’ll get there – formerly highly technical jargon makes its way into common usage all the time once wider audiences suddenly have a reason to understand a tricky subject at a conceptual level.</li>
  <li>But in the meantime, I think we’re facing down a lot of potentially confused people trying to make generative AI to do things that would be better solved with a deterministic approach.</li>
</ul>

<h2 id="statistical-methods-as-social-sciences">Statistical methods as social sciences</h2>

<p>One person in the conversation had this absolute gem:</p>

<blockquote>
  <p>“‘AI’ appears to be reinventing people but worse.”</p>
</blockquote>

<p>Speaking of trying to reinvent the human by using probability and statistics math, check out Chris Wiggins and Matthew Jones’s “<a href="https://wwnorton.com/books/how-data-happened" target="_blank">How Data Happened:  a History from the Age of Reason to the Age of Algorithms</a>.”  It turns out that “data-driven” decisionmaking about how to organize ourselves, as groups of people, is only about 500 years old.  Before that, you had philosophers Aristotle and Machiavelli just arguing.  <em>(The book covers the ways in which it’s debatable whether data-driven decisionmaking is actually an improvement to human life.  Which Annalee Newitz’s “<a href="https://wwnorton.com/books/9780393881516" target="_blank">Stories Are Weapons:  Psychological Warfare and the American Mind</a>” makes a great companion piece to, by the way – they both touch on early-20th-century American advertising’s impacts on the social sciences, and vice-versa.)</em></p>

<h2 id="naming-ai">Naming AI</h2>

<p>Also, remember:</p>

<blockquote>
  <p>“<a href="https://quoteinvestigator.com/2024/06/20/not-ai/" target="_blank">As soon as it works, no one calls it AI anymore.</a>”</p>
</blockquote>

<p><em>(As I heard on, I believe it was the .NET Rocks podcast, once we know what it’s “for,” we instead give it a name like “machine learning,” “natural language processing,” “optical character recognition,” “automatic speech recognition,” “data mining,” “heuristic search,” etc.  And then “AI” gets recycled to describe the next thing we don’t quite understand.)</em></p>

<p>We still don’t actually know <em>everything</em> about what LLM-based GenAI is and isn’t good at.</p>]]></content><author><name>Katie</name></author><category term="security" /><category term="devops" /><summary type="html"><![CDATA[CI/CD pipelines become nondeterministic]]></summary></entry><entry xml:lang="en"><title type="html">Supply chain consumption tips</title><link href="https://katiekodes.com/package-consumption-starter/" rel="alternate" type="text/html" title="Supply chain consumption tips" /><published>2026-06-04T15:00:00+00:00</published><updated>2026-06-04T15:00:00+00:00</updated><id>https://katiekodes.com/package-consumption-starter</id><content type="html" xml:base="https://katiekodes.com/package-consumption-starter/"><![CDATA[<p>I was just doing some developer education about how to safely use end-to-end testing SDKs such as Microsoft Playwright.</p>

<p>While, for authN and authZ, I still love my old “<a href="https://katiekodes.com/test-identities-considered-harmful/">E2E and Synthetic Testing Considered Harmful</a>” advice, I’d also like to add on some supply chain compromise tips.</p>

<p>I’m probably not the best at this, but here are some quick wins I think I’ve collected so far about how to import SDKs and other open-source libraries/packages/modules/software/etc. onto your computer / into your codebases, in this Sha1-Hulud / package-registry native worm era.</p>

<!--more-->

<h2 id="intro">Intro</h2>

<p>While many SDKs are widely respected, their authors are not infallible or immune to phishing <em>(nor are the authors of the SDKs upon which those widely respected SDKs, in turn, “transitively” depend – which could compromise the contents of various versions of widely-respected SDKs through a “supply chain worm” in the style of Sha1-Hulud)</em>.</p>

<p>Patching codebases to use the latest and greatest version numbers of widely-respected SDKs is generally desirable, because new releases typically offer security patches and improved features.</p>

<p>However, any given brand new version number for an SDK could, despite its authors’ best efforts, theoretically have been compromised and also contain malware.</p>

<p>Following tips below can, hopefully, reduce the probability of developer laptops, developer VDIs, enterprise servers, or enterprise CI/CD runtimes becoming infected by such malware.</p>

<h2 id="bundle-separation">Bundle separation</h2>

<p>If the programming language that a web developer is using offers the ability to import “during development only” SDKs separately from “necessary to make the web application run” SDKs, then SDKs should be imported using the “during development only” mechanism.</p>

<ul>
  <li>For example, end-to-end testing libraries such as Playwright should be part of <code class="language-plaintext highlighter-rouge">devDependencies</code>, not <code class="language-plaintext highlighter-rouge">dependencies</code>, in the <code class="language-plaintext highlighter-rouge">package.json</code> file for a Node.js JavaScript codebase.</li>
</ul>

<h2 id="exact-version-number-pinning">Exact version number pinning</h2>

<p>Web developers should specify the exact intended version number (e.g. <code class="language-plaintext highlighter-rouge">1.2.3</code>) of each SDK that they currently intend their source code to use, rather than specifying a range (e.g. <code class="language-plaintext highlighter-rouge">1.2.x</code> or <code class="language-plaintext highlighter-rouge">latest</code>) of acceptable version numbers.</p>

<p>Many programming languages offer built-in helper tooling.</p>

<ul>
  <li>For example, Node.js JavaScript’s <code class="language-plaintext highlighter-rouge">npm install</code> and <code class="language-plaintext highlighter-rouge">npm update</code> commands offer a <code class="language-plaintext highlighter-rouge">--save-exact</code> option, in any of the following ways:
    <ul>
      <li>Inline, and</li>
      <li>Through <code class="language-plaintext highlighter-rouge">.npmrc</code> configuration files that can be checked into version control so that no developer ever forgets to use the option inline, and</li>
      <li>Through <a href="https://docs.npmjs.com/cli/v12/using-npm/config#environment-variables" target="_blank">operating system environment variables</a> so that no developer ever forgets to use the inline or <code class="language-plaintext highlighter-rouge">.npmrc</code> file, though as in package cooldown below, while it could help in a hurry, I don’t like the long-term maintainability of not saying what you mean &amp; meaning what you say in source code itself.</li>
    </ul>
  </li>
</ul>

<p><strong>Important:</strong>  Don’t forget that you probably have “auxiliary” dependencies <em>(e.g. 3rd-party steps like <code class="language-plaintext highlighter-rouge">actions/checkout</code> that are found in your CI/CD pipeline’s scripting)</em> that also need to start getting exact-version-number-pinned.</p>

<h2 id="frequent-version-number-patching">Frequent version number patching</h2>

<p>The specific versions of the SDKs used within a given codebase should be kept up-to-date and patched.</p>

<ul>
  <li>Automatically scanning source code with a static application security testing <em>(“SAST”)</em> or software composition analysis <em>(“SCA”)</em> tool, upon each check-in into version control, is an excellent way for web developers to discover when an SDK version has fallen out-of-date.</li>
  <li>Many programming languages also offer built-in tooling.
    <ul>
      <li>For example, Node.js JavaScript offers an <code class="language-plaintext highlighter-rouge">npm audit</code> command.</li>
    </ul>
  </li>
</ul>

<h2 id="version-number-age-cooldown">Version number age cooldown</h2>

<p>While it is crucial to keep SDK versions up-to-date, keeping them <em><strong>too</strong></em> up-to-date can be a problem in the era of widespread SDK supply chain compromises.</p>

<p>If their programming language allows it, web developers should strongly consider setting a “package cooldown” / “minimum release age” when patching SDK version numbers within their codebase.</p>

<p>As of mid-2026, recent “supply chain” compromises seem to be ending up removed from major package registries within a few hours to a few days, so while industry consensus might further change, a cool-off period of 7 days seems to be the generally recommended window before treating a recently-released SDK version number as “safe enough” to try installing.</p>

<p>Many programming languages offer built-in helper tooling.</p>

<ul>
  <li>For example, Node.js JavaScript’s <code class="language-plaintext highlighter-rouge">npm install</code> and <code class="language-plaintext highlighter-rouge">npm update</code> commands offer a <code class="language-plaintext highlighter-rouge">--min-release-age=SOME_NUMBER</code> option, in any of the following ways:
    <ul>
      <li>Inline, and</li>
      <li>Through <code class="language-plaintext highlighter-rouge">.npmrc</code> configuration files that can be checked into version control so that no developer ever forgets to use the option inline, and</li>
      <li>Through <a href="https://docs.npmjs.com/cli/v12/using-npm/config#environment-variables" target="_blank">operating system environment variables</a> so that no developer ever forgets to use the inline or <code class="language-plaintext highlighter-rouge">.npmrc</code> file.
        <ul>
          <li><em>(Note:  I’m not a big fan of this, overall, because I think it’s more long-term maintenance-friendly to say what you mean and mean what you say inside of the files on your verison-controlled source code repository.  However, if you’re in a super-big rush to lock down thousands of repositories’ CI/CD pipelines and thousands of developers’ workstations, looping over all repositories’ and endpoints’ and servers’ OS variables and adding an <code class="language-plaintext highlighter-rouge">npm_config_min_release_age</code> environment variable whose value is set to, say, <code class="language-plaintext highlighter-rouge">7</code>, could definitely <strong>help in a hurry</strong> – and then you can go back and do the more code-editing-intensive versions later.)</em>
            <ul>
              <li><em>(Additional note:  Google Search summary says the highest to lowest precedence of NPM config options comes first from inline at-CLI-invocation-time flags, then OS environment variables, then <code class="language-plaintext highlighter-rouge">.npmrc</code> files in the OS shell’s “working directory” from which the NPM CLI was invoked, then any per-OS-user-home-directory <code class="language-plaintext highlighter-rouge">.npmrc</code> file that might exist, then any “global” <code class="language-plaintext highlighter-rouge">.npmrc</code> file that might exist, and finally the NPM CLI’s installation’s built-in <code class="language-plaintext highlighter-rouge">npmrc</code> file – no preceding dot)</em>.</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>Careful, though, to check whether the computer on which you’re running your programming language actually has a recent enough version of the programming language installed to recognize the package cooldown flag everyone’s talking about!
    <ul>
      <li>For example, GitHub Actions’s built-in <code class="language-plaintext highlighter-rouge">ubuntu-latest</code> runtime is, as of 7/14/26, <a href="https://github.com/actions/runner-images/blob/main/README.md" target="_blank">still just Ubuntu 24</a> and, in turn, <a href="https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md" target="_blank">still just Node 10</a>, which doesn’t know what the <code class="language-plaintext highlighter-rouge">--min-relase-age</code> flag even means <em>(it came out in Node <code class="language-plaintext highlighter-rouge">11.10</code>)</em>.
        <ul>
          <li>So unless you’ve got a step within your GitHub Actions Workflow’s YAML file that invokes <a href="https://github.com/actions/setup-node" target="_blank">GitHub’s <code class="language-plaintext highlighter-rouge">@actions/setup-node</code> workflow</a> to force installation of a more recent version of Node+NPM onto your <code class="language-plaintext highlighter-rouge">ubuntu-latest</code> runtime, your <code class="language-plaintext highlighter-rouge">min-release-age</code> settings are useless – yikes!
            <ul>
              <li><em>(Luckily, there’s an older <code class="language-plaintext highlighter-rouge">--before</code> flag that’s actually just what’s under the hood of <code class="language-plaintext highlighter-rouge">--min-release-age</code>, but then you need to add code to do the math to get a timestamp to work with it, which is annoying, but anyway, right now, you either need to force <code class="language-plaintext highlighter-rouge">ubuntu-latest</code> to update NPM, or you need to compute a value and use <code class="language-plaintext highlighter-rouge">--before</code>, on 7/14/2026.)</em></li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<p>If your programming language doesn’t <a href="https://nesbitt.io/2026/03/04/package-managers-need-to-cool-down.html" target="_blank">include package cooldown</a>, please help by chiming in and complaining until it does:</p>

<ul>
  <li><a href="https://github.com/microsoft/vscode/issues/316867" target="_blank">VSCode extensions cooldown GitHub Issue</a>
    <ul>
      <li>Update 7/1/26:  VSCode did it; great job advocating, everybody!  <a href="https://code.visualstudio.com/docs/configure/extensions/extension-marketplace#_extension-auto-update" target="_blank">New setting</a> <code class="language-plaintext highlighter-rouge">extensions.autoUpdateDelay</code>’s value should be an integer representing hours.  Current default is just <code class="language-plaintext highlighter-rouge">2</code> hours, which personally I think is assuming superhuman speed of the VSCode Extension’s Marketplace team to get compromised extensions pulled down.  I’d probably go for more like 3 or 7 days’ worth of hours, but even better, your company can pick a number greater than <code class="language-plaintext highlighter-rouge">2</code> and <a href="https://code.visualstudio.com/docs/enterprise/policies" target="_blank">set it enterprise-wide</a>, so let your leadership know.</li>
    </ul>
  </li>
  <li><a href="https://github.com/NuGet/Home/issues/14657" target="_blank">NuGet cooldown GitHub Issue</a></li>
</ul>

<h2 id="version-number-lockfiles">Version number lockfiles</h2>

<p>If their programming language allows it, web developers should generate, and check into source code version control history, “lock files” that specify exact version numbers not only for the web developers’ intended SDKs, but also exact version numbers for all of the “transitive dependencies” that those SDKs in turn depended upon, at the exact time that the developer generated such a “lock file.”</p>

<ul>
  <li>For example, check Node.js JavaScript’s <code class="language-plaintext highlighter-rouge">package-lock.json</code> file into source code version control.</li>
</ul>

<h3 id="installation-from-lockfiles">Installation from lockfiles</h3>

<p>If their programming language allows it, web developers <a href="https://github.com/npm/cli/issues/8938#issuecomment-4297852301" target="_blank">should</a> almost always install SDKs onto a machine by using a mechanism that installs them from the above “lock file.”</p>

<p>For example, as seen in <a href="https://cheatsheetseries.owasp.org/cheatsheets/NPM_Security_Cheat_Sheet.html#2-enforce-the-lockfile" target="_blank">OWASP’s NPM security cheat sheet</a>, use Node.js JavaScript’s <strong><code class="language-plaintext highlighter-rouge">npm ci</code></strong> command, rather than the <code class="language-plaintext highlighter-rouge">npm install</code> <em>(a.k.a. <code class="language-plaintext highlighter-rouge">npm i</code>)</em> command.</p>

<ul>
  <li>Similarly, I believe for .NET, you’d want to use its **<code class="language-plaintext highlighter-rouge">dotnet restore**</code> command, rather than some sort of installation/updating command.</li>
</ul>

<p>This is particularly important in the following contexts:</p>
<ol>
  <li>The automation scripts comprising a CI/CD pipeline (always).</li>
  <li>After downloading a codebase from version control onto a developer laptop or VDI.</li>
</ol>

<p>The only exception is when a web developer, on their laptop or VDI, is explicitly in the process of SDK version maintenance as mentioned in “frequent version number patching” above.</p>

<ul>
  <li>For example, this is the only time when it would be appropriate for a Node.js JavaScript developer to run <code class="language-plaintext highlighter-rouge">npm install</code> or <code class="language-plaintext highlighter-rouge">npm update</code> <em>(or for a .NET developer to run <code class="language-plaintext highlighter-rouge">dotnet tool install</code> or <code class="language-plaintext highlighter-rouge">dotnet tool update</code> or <code class="language-plaintext highlighter-rouge">dotnet package add</code> or <code class="language-plaintext highlighter-rouge">dotnet package update</code>)</em>.
    <ul>
      <li>Even then, the developer would still want to leverage options such as NPM’s <code class="language-plaintext highlighter-rouge">--save-exact</code> and <code class="language-plaintext highlighter-rouge">--min-release-age</code> options.</li>
      <li>The developer should also remember to check any successfully updated dependcy-tracking files <em>(such as <code class="language-plaintext highlighter-rouge">package.json</code> and <code class="language-plaintext highlighter-rouge">package-lock.json</code> for NodeJS/NPM)</em> back into source code version control.</li>
    </ul>
  </li>
</ul>

<h3 id="sboms">SBOMs</h3>

<p>Perhaps <em>especially</em> if your programming language doesn’t offer lockfiles <em>(but arguably even if it does, just to get various programming languages’ lockfiles standardized into a single machine-readable format)</em>, consider also generating, and storing somewhere organized, a software bill of materials <em>(“SBOM”)</em>, for each version-control commit of your codebase.</p>

<p>Be sure to include both:</p>

<ol>
  <li>Your codebase’s “primary” SDK dependencies <em>(for example, the ones in <code class="language-plaintext highlighter-rouge">package.json</code> and <code class="language-plaintext highlighter-rouge">package-lock.json</code> if you are a Node.js JavaScript developer)</em>, and</li>
  <li>Any “auxiliary” dependencies <em>(e.g. 3rd-party steps like <code class="language-plaintext highlighter-rouge">actions/checkout</code> that are found in your CI/CD pipeline’s scripting)</em>.</li>
</ol>

<p>It probably doesn’t help you, the developer, much.</p>

<p>But when central IT comes knocking, asking if you got hit by the latest worm, being able to send them all SBOMs from all commits during that timeframe can probably help ease their worries.</p>

<ul>
  <li><strong>Tip:</strong>  If major SBOM-generating SDKs don’t seem to be able to generate SBOMs for your programming language, maybe <a href="https://nesbitt.io/2026/03/08/if-it-quacks-like-a-package-manager.html" target="_blank">it’s failing to have a proper package manager</a>; please help by chiming in on your programming language’s “GitHub Issues” page or wherever they interact with the community and complaining until it includes a proper package manager.</li>
</ul>

<h3 id="basic-audit">Basic audit</h3>

<p>Another benefit of checking a lockfile into your source code version control repository is that your programming language might offer a command for auditing whether any of your direct and transitive dependency versions have been published as already known to be malicious.</p>

<p>If you were to always <em>(e.g. in your CI/CD, or out of habit on laptops)</em> run such a command <em>before</em> running the command to install those packages onto the host machine, then you could pretty easily refuse to proceed to installation <em>(e.g. <code class="language-plaintext highlighter-rouge">npm ci</code> or <code class="language-plaintext highlighter-rouge">dotnet restore</code>)</em> if you found any alerts.</p>

<p>For example, you can run <code class="language-plaintext highlighter-rouge">npm audit</code> against a NodeJS codebase, or <a href="https://learn.microsoft.com/en-us/nuget/concepts/auditing-packages" target="_blank">leverage automatic auditing of your .NET codebase</a>, or run a third-party <a href="https://en.wikipedia.org/wiki/Software_composition_analysis" target="_blank">software composition analysis</a> <em>(“SCA”)</em> tool against your codebase.</p>

<p>Such tooling will <em>always</em> work better if you’ve had the coding discipline to install dependencies <em>only</em> from lockfiles that are <em>checked into version control</em>.</p>

<p>Audit tooling probably won’t catch your random in-CI/CD-shell-script <code class="language-plaintext highlighter-rouge">npm install @some-publisher/some-tool@1.2.3</code> invocation <em>(and therefore they’ll miss the fact that version <code class="language-plaintext highlighter-rouge">1.2.3</code> of <code class="language-plaintext highlighter-rouge">@some-publisher/some-tool</code> resolved at runtime to a malicious version of <code class="language-plaintext highlighter-rouge">@some-other-publisher/some-recently-hacked-tool</code>!)</em>.</p>

<p>So, as mentioned under “installation from lockfiles” above, please avoid writing such inline installer invocations anymore, if you want to enjoy the full strength of programming languages’ built-in audit tools and 3rd-party SCA tools.</p>

<h3 id="provenance-validation">Provenance validation</h3>

<p>Another benefit of checking a lockfile into your source code version control repository is that your programming language might offer a command for verifying each direct and transitive dependency’s provenance.</p>

<p>If you were to always <em>(e.g. in your CI/CD, or out of habit on laptops)</em> run such a command <em>before</em> running the command to install those packages onto the host machine, then you could pretty easily refuse to proceed to installation if you found any alerts.</p>

<p>Whether this helps is hit or miss, but since it <em>sometimes</em> helps, it’s probably better than nothing:</p>

<ul>
  <li>Apparently running <code class="language-plaintext highlighter-rouge">npm audit signatures</code> against a <code class="language-plaintext highlighter-rouge">package-lock.json</code> <a href="https://www.armorcode.com/blog/defending-against-npm-supply-chain-attacks-a-practical-guide#h-verify-package-provenance-before-installing" target="_blank">would’ve caught</a> the malicious <code class="language-plaintext highlighter-rouge">1.14.1</code> version of <code class="language-plaintext highlighter-rouge">axios</code> in March 2026, giving you a chance to refuse to run <code class="language-plaintext highlighter-rouge">npm ci</code>, since the attackers only compromised Axios’s NPM account, not Axios’s GitHub account.</li>
  <li>But running <code class="language-plaintext highlighter-rouge">npm audit signatures</code> against a <code class="language-plaintext highlighter-rouge">package-lock.json</code> likely wouldn’t have caught July 2026’s malicious <code class="language-plaintext highlighter-rouge">6.13.5</code> version <code class="language-plaintext highlighter-rouge">@asyncapi/specs</code> and you likely would’ve blithely proceeded to run <code class="language-plaintext highlighter-rouge">npm ci</code> anyway, since <a href="https://www.reddit.com/r/node/comments/1uw5pdn/comment/oxgcdbx/" target="_blank">the attackers seem to have compromised AsyncAPI’s GitHub account</a>.</li>
</ul>

<p>If you’re following my advice to always install only from lockfiles <em>(e.g. <code class="language-plaintext highlighter-rouge">npm ci</code>)</em> except when explicitly deliberately in the middle of trying to generate/update a lockfile <em>(e.g. with <code class="language-plaintext highlighter-rouge">npm install</code>, <code class="language-plaintext highlighter-rouge">npm i</code>, or <code class="language-plaintext highlighter-rouge">npm update</code>)</em>, never fear – you can still do provenance validation if your programming language lets you split apart lockfile updates from installation!  You just have to break your work up into two parts.  For example, NodeJS’s <a href="https://docs.npmjs.com/cli/v12/using-npm/config#package-lock-only" target="_blank">NPM has a <code class="language-plaintext highlighter-rouge">--package-lock-only</code> flag</a>, so you might do a deliberate update like this:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">npm update --package-lock-only</code> to update the files</li>
  <li><code class="language-plaintext highlighter-rouge">npm audit</code> to find out if there are security vulnerabilities</li>
  <li><code class="language-plaintext highlighter-rouge">npm audit signatures</code> to validate provenance</li>
  <li><code class="language-plaintext highlighter-rouge">npm ci</code> if everything went well in the previous 3 steps.</li>
</ol>

<h2 id="installation-without-auxiliary-scripts">Installation without auxiliary scripts</h2>

<p>If their programming language allows it, web developers should almost always install SDKs onto a machine using a mechanism that prevents the SDK installation process from running <a href="https://nesbitt.io/2026/04/15/the-tuesday-test.html" target="_blank">arbitrary scripts</a> on that machine.</p>

<p>This is because execution of arbitrary scripts during SDK installation has been a major compromise vector in recent supply chain compromises such as Sha1-Hulud.</p>

<ul>
  <li>For example, the Node.js JavaScript’s <code class="language-plaintext highlighter-rouge">npm ci</code>, <code class="language-plaintext highlighter-rouge">npm install</code>, and <code class="language-plaintext highlighter-rouge">npm update</code> commands all offer an <code class="language-plaintext highlighter-rouge">--ignore-scripts</code> option, in any of the following ways:
    <ul>
      <li>Inline, and</li>
      <li>Through <code class="language-plaintext highlighter-rouge">.npmrc</code> configuration files that can be checked into version control so that no developer ever forgets to use the option inline, and</li>
      <li>Through <a href="https://docs.npmjs.com/cli/v12/using-npm/config#environment-variables" target="_blank">operating system environment variables</a> so that no developer ever forgets to use the inline or <code class="language-plaintext highlighter-rouge">.npmrc</code> file, though as in package cooldown above, while it could help in a hurry, I don’t like the long-term maintainability of not saying what you mean &amp; meaning what you say in source code itself.</li>
      <li><em>(Update 7/14/26:  <a href="https://github.blog/changelog/2026-06-09-upcoming-breaking-changes-for-npm-v12/" target="_blank">NPM version 12</a> has <code class="language-plaintext highlighter-rouge">--ignore-scripts</code> set to <code class="language-plaintext highlighter-rouge">true</code> by default, but it’s quite new, so you probably have to hand-upgrade all of your laptops, CI/CD pipelines, etc. to take advantage of that.)</em></li>
    </ul>
  </li>
</ul>

<h2 id="clutter-management">Clutter management</h2>

<h3 id="executable-binaries-clutter">Executable binaries clutter</h3>

<p>Specifically for build-time / test-time SDKs such as Playwright, clutter might accumulate that is undesirable.</p>

<p>The most common machine type in which an SDK such as Playwright would be installed and executed is a CI/CD pipeline.  In the case of the built-in CI/CD runtimes that come with major cloud-based Git version control hosts, these machines are ephemeral and self-destruct the moment a CI/CD pipeline finishes executing, so no extra cleanup would be needed.</p>

<p>However, when a clutter-producing SDK such as Playwright is installed onto a long-lived machine such as a developer laptop, developer VDI, or enterprise-hosted CI/CD runtime, the following clutter can build up that would be wise <em>(because, really, who wants extra <code class="language-plaintext highlighter-rouge">.exe</code> files sitting around ready for malware to latch onto and use against you?)</em> to periodically delete altogether:</p>

<ul>
  <li>Logs, screenshots, and recordings from past runs of the automated test suite.</li>
  <li>Copies of automation-friendly (“headless”) versions of web browsers that were needed by older test automation code, but that are no longer relevant.
    <ul>
      <li>For example, the Playwright SDK <a href="https://www.browserstack.com/guide/uninstall-playwright" target="_blank">offers</a> a <code class="language-plaintext highlighter-rouge">npx playwright uninstall --all</code> command that cleans out copies of old web browser executables that previous Playwright runs had put into a Windows machine’s <code class="language-plaintext highlighter-rouge">%LOCALAPPDATA%\ms-playwright</code> folder <em>(or a Linux machine’s <code class="language-plaintext highlighter-rouge">~/.cache/ms-playwright</code> folder)</em>.</li>
    </ul>
  </li>
</ul>

<h3 id="authentication-clutter">Authentication clutter</h3>

<p>Maybe run some CLI commands on your computer like <code class="language-plaintext highlighter-rouge">aws logout</code> or <code class="language-plaintext highlighter-rouge">az logout</code>, or something, before running any third-party SDKs <em>(which, if you have VSCode extensions auto-updating, includes “before opening VSCode”)</em>.</p>

<p>That way, if you get infected, maybe you’ll notice that the malware is trying to query AWS for secrets and whatnot from your machine when it prompts you to log your CLI in or something.</p>

<p><a href="https://cheatsheetseries.owasp.org/cheatsheets/GitHub_Actions_Security_Cheat_Sheet.html#minimize-github_token-permissions" target="_blank">OWASP’s GitHub Actions cheat sheet</a> has a similar trick:  explicitly set every single GitHub Actions YAML file you write to have <code class="language-plaintext highlighter-rouge">permissions: {}</code> <em>(no permissions)</em>, rather than just leaving the <code class="language-plaintext highlighter-rouge">permissions</code> property out altogether, and see if it breaks, and then rebuild the <code class="language-plaintext highlighter-rouge">permissions</code> block’s values permission by permission <em>(e.g. adding back <code class="language-plaintext highlighter-rouge">content: "read"</code> manually if your YAML file needs to run an <code class="language-plaintext highlighter-rouge">actions/checkout</code> step)</em>.</p>

<h4 id="relinquish-your-privileges">Relinquish your privileges</h4>

<p>Following on that <code class="language-plaintext highlighter-rouge">logout</code> theme, here’s another idea:  push your company’s leadership to adopt a “zero standing privileges” <em>(“ZSP”)</em> approach to granting <strong>human</strong> identities any access <em>(“authorization” / “authZ”)</em> to sensitive cloud resources.</p>

<p>For example, tell them that you don’t want your computer, while <code class="language-plaintext highlighter-rouge">az login</code> is active, able to run <code class="language-plaintext highlighter-rouge">az keyvault secret show</code> unless you, within the last few hours, have intentionally and manually engaged in a just-in-time <em>(“JIT”)</em> privilege escalation to activate your <code class="language-plaintext highlighter-rouge">Key Vault Secrets User</code> <a href="https://katiekodes.com/azure-rbac-role-assignment/" target="_blank">Azure RBAC Role Assignment</a> against that particular Azure Key Vault.  If someone granted you, or a group to which you belong, <code class="language-plaintext highlighter-rouge">Key Vault Secrets User</code> in “active” status rather than in “eligible” status, push for them to fix it and <a href="https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-resource-roles-discover-resources" target="_blank">assign it as “eligible” instead</a>.</p>

<p>Your company’s identity provider might even make it possible to do this for cloud secrets that live in non-hyperscaler-sized clouds.  For example, even if Hashicorp Vault doesn’t have an option for requiring that you do JIT authZ escalation before performing <code class="language-plaintext highlighter-rouge">vault kv get</code>, perhaps it has an option for requiring that you be a member of a certain Microsoft Entra ID security group for <code class="language-plaintext highlighter-rouge">vault kv get</code> to work against a given secret.  And guess what?  Microsoft has <a href="https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/groups-discover-groups" target="_blank">options for your membership in Entra Security Groups</a> to be “zero standing privilege,” and for you to have to JIT activate your membership in that group using Entra ID PIM!  So, seriously – push your company to get creative.</p>

<p>Convenience and security are often at odds <em>(if something is more convenient for you to do, it’s also more convenient for a virus that’s infected your computer to do as if it were you)</em>.  Slow supply chain package worms like VSCode extension compromises down by making sure that your cloud accounts <strong>cannot</strong>, by default, perform sensitive actions.  It’s a great compromise – adding an extra 2 minutes of inconvenience to the days in which you <em>actually</em> need to access a given cloud secret/certificate, so as to harden security for your computer on all the days you <em>don’t</em>.</p>

<p>This isn’t a particularly big ask, either.  Companies don’t need to do this for all of the access you’ve ever been granted to any cloud resource.  Just the particularly sensitive ones that these kinds of supply chain worms target, like reading secrets out of AWS Secrets Manager, AWS KMS, AWS ACM, Azure Key Vault, GCP Secret Manager, GCP KMS, or GCP Certificate Manager.</p>

<p>An ounce of prevention is worth a pound of cure, and retrofitting humans’ existing sensitive authZ grants to ZSP can massively stop the bleeding when – not if – your “endpoint” <em>(laptop, virtual desktop infrastructure (“VDI”), etc.)</em> gets infected by a supply chain worm.</p>

<p>At the very least, push hard for your company to, going forward, issue new sensitive authZ grants in a ZSP approach.</p>

<h2 id="burner-compute">Burner compute</h2>

<p>Tomas Listiak’s “<a href="https://listiak.dev/blog/how-to-safely-approach-a-javascript-interview-test-project" target="_blank">How to safely approach a JavaScript interview test project</a>” takes “reduce clutter” to the extreme and focuses a lot on following the sort of “burner phone” approaches to running strange code that I’ve seen security researchers adopt for years <em>(I get the impression they’re constantly reimaging their laptops and possibly even changing out hard drives altogether)</em>.</p>

<ul>
  <li>For individuals, I wonder if a brand new account on GitHub.com and using a few hours of free included GitHub Codespaces time as your “burner laptop/VDI” could be a quick-and-dirty version of Tomas’s tips.</li>
  <li>For enterprises, I think things get tricky and expensive fast, and I don’t have great answers, so if you’re an enterprise that doesn’t already have hyper-ephemeral, hyper-constrained developer “workstations,” I can’t say I’d run out and focus on that.  I’d probably focus more on enterprise-wide developer education and governance about the tips above, for now.</li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li><a href="https://www.linkedin.com/pulse/your-cicd-pipeline-just-became-accomplice-robbery-pi%C3%B1ero-estrada-da1nf#:~:text=What%20to%20change%20before%20the%20next%20deployment" target="_blank">This quote from Fernando Piñero Estrada</a> is great:
    <blockquote>
      <p>The cloud industry has spent more than a decade optimizing for developer velocity. We made dependency installation fast. We made CI/CD pipelines automatic. We made SaaS build platforms beautifully simple. We taught ourselves to trust registries because the alternative was slow, manual, and socially unpopular.</p>

      <p>Mini Shai-Hulud is not the end of that model. It is the invoice.</p>

      <p>The convenience of <code class="language-plaintext highlighter-rouge">npm install</code> is not free. It is a line of credit against your security posture, and the interest <strong>rate just went up</strong>.</p>

      <p>This does not mean we should retreat into caves and compile everything by candlelight, although some incident response teams have looked into it. It means we need to stop treating dependency installation as a harmless clerical step. It is code execution. It happens early. It happens often. It happens in places where secrets live.</p>
    </blockquote>
  </li>
  <li>A lot of this post is based on tricks I learned from <a href="https://phoenix.security/npm-sha1-hulud-supply-chain-compromise-explained/#h-how-to-remediate-prevention-measures-against-shai-hulud-npm-campaigns-and-follow-up" target="_blank">Phoenix Security’s post-Sha1-Hulud article</a>.</li>
  <li>If you’re interested in bigger-picture philosophical questions about where package management should be heading, <a href="https://nesbitt.io/" target="_blank">Andrew Nesbitt’s blog</a> pretty much exclusively talks about that.</li>
</ul>]]></content><author><name>Katie</name></author><category term="security" /><category term="web development" /><summary type="html"><![CDATA[I'm probably wrong, but it seems better than nothing]]></summary></entry><entry xml:lang="en"><title type="html">LLMs, rubber ducks, and doubt</title><link href="https://katiekodes.com/rubber-duck-doubt/" rel="alternate" type="text/html" title="LLMs, rubber ducks, and doubt" /><published>2026-06-03T15:00:00+00:00</published><updated>2026-06-03T15:00:00+00:00</updated><id>https://katiekodes.com/rubber-duck-doubt</id><content type="html" xml:base="https://katiekodes.com/rubber-duck-doubt/"><![CDATA[<p>Two LLM-related things that reminded me of “doubt” this morning:</p>

<ol>
  <li>I played with the GitHub Copilot CLI tool’s <a href="https://docs.github.com/en/copilot/concepts/agents/copilot-cli/rubber-duck" target="_blank">new <code class="language-plaintext highlighter-rouge">/rubber-duck</code> mode</a> this morning and was not impressed, but I think that’s because I <em>already</em> word most of my prompts in rubber-duck “change my mind” fashion.</li>
  <li>I stumbled upon a <a href="https://www.astralcodexten.com/p/next-token-predictor-is-an-ais-job" target="_blank">blog post</a> by some guy named Scott Alexander, and am pretty sure he forgot that, unlike LLMs, our genes are simultaneously encoded with <em>lots</em> of algorithms of similar complexity to “next-sense-datum prediction” <em>(the ones that I swear must be hugely behind <strong>doubt</strong>)</em> under the hood, whereas LLMs are more or less <em>only</em> “next-token prediction” under the hood.</li>
</ol>

<!--more-->

<hr />

<h2 id="rubber-duck-mode">Rubber duck mode</h2>

<p>Copilot said that rubber duck mode:</p>

<blockquote>
  <p>“is purpose-built for adversarial critique – explicitly tuned to find bugs, logic errors, and design flaws – and explicitly not to comment on style, formatting, or other trivial things.”</p>
</blockquote>

<p>Whereas it said ask mode:</p>

<blockquote>
  <p>“answers whatever you ask, in whatever tone you set; no special ‘adversarial’ framing – it’ll critique if you ask, but it may also compliment, hedge, or drift into style suggestions.”</p>
</blockquote>

<p>Got it.  So … rubber-duck mode is just letting me write your “ask-mode” prompts.</p>

<p>Seriously, here are some quotes pulled straight from one of my recent chats with an LLM in “ask mode:”</p>

<ul>
  <li>
    <blockquote>
      <p>“Same question, <strong>but</strong> now with me clarifying to you: I meant around (name-of-system) modernization, specifically.”</p>
    </blockquote>
  </li>
  <li>
    <blockquote>
      <p>“In your response to my last prompt, you wrote both of these two quotes:</p>

      <ol>
        <li>”‘(censored; private)’</li>
        <li>”‘(also censored; private)’</li>
      </ol>

      <p>“Are these two quotes referring to the same thing <strong>or</strong> different?”</p>
    </blockquote>
  </li>
  <li>
    <blockquote>
      <p>“If (censored; private) modernizes (name-of-system) as planned, what do you think (also censored; private) will turn all these old (name-of-other system) apps into instead <em>(<strong>or</strong>, alternatively, why would they deprecate them altogether)</em>? What would (also censored; private) likely replace them with, <strong>if</strong> anything?”</p>
    </blockquote>
  </li>
  <li>
    <blockquote>
      <p>“Yes, go ahead and tell me about the published modernization roadmaps. Only about the actual coming (censored; private), <strong>though</strong>, not looking back at the (also censored; private).”</p>
    </blockquote>
  </li>
  <li>
    <blockquote>
      <p>“If you had tons of (censored; private) to squander … which parts of the modernization roadmaps you just told me about would you consider such practices optimized to accelerate <strong>versus</strong> a potential time-wasting distraction?”</p>
    </blockquote>
  </li>
  <li>
    <blockquote>
      <p>“Same question, <strong>except</strong> now imagine that the (censored; private) modernization ain’t going so hot and you work for (also censored; private) and are still stuck on (name-of-other-system) strangler fig best efforts and whatnot for a few years longer than expected.  <strong>But</strong> you are now the one with all the (yes, also censored; private).  Same question about which parts of your responsibilities benefit <strong>versus</strong> are wasted with such resources.”</p>
    </blockquote>
  </li>
</ul>

<p>“But,” “or,” “if,” “though,” “versus,” “except” – I kid you not, in a 12-prompt chat transcript, I jumped into the middle, looked at 8, and that’s what I see in 6 of those 8.  I rubber duck the world as a matter of personality.  🤣</p>

<p>I think this harnessing of <strong>doubt</strong> is why I feel pretty satisfied with my results when I prompt LLMs, which are, mathematically under the hood, sycophantic because their math is about “next-token prediction” <em>(not “next if there is a next” – just “next”)</em>.  My animal neurons’ parallel algorithms for <strong>doubt</strong> is how I add the “<strong>if</strong> there is a next” and steer it as best I can.</p>

<p>I heard an <a href="https://www.npr.org/2026/01/14/nx-s1-5674741/ai-schools-education" target="_blank">NPR broadcast this winter</a> with the following amazing quotes on the value of <strong>doubt</strong>:</p>

<blockquote>
  <p>Winthrop says that if children are building social-emotional skills largely through interactions with chatbots that were designed to agree with them, “it becomes very uncomfortable to then be in an environment when somebody doesn’t agree with you.”</p>

  <p>Winthrop offers an example of a child interacting with a chatbot, “complaining about your parents and saying, ‘They want me to wash the dishes — this is so annoying. I hate my parents.’ The chatbot will likely say, ‘You’re right. You’re misunderstood. I’m so sorry. I understand you.’ Versus a friend who would say, ‘Dude, I wash the dishes all the time in my house. I don’t know what you’re complaining about. That’s normal.’ That right there is the problem.”</p>

  <p>A (report accompanying a) recent survey from the Center for Democracy and Technology, a nonprofit that advocates for civil rights and civil liberties in the digital age, … warns that AI’s echo chamber can stunt a child’s emotional growth: “We learn empathy not when we are perfectly understood, but when we misunderstand and recover,” one of the surveyed experts said.</p>
</blockquote>

<p>A friend once showed me his LLM chat logs trying to sentiment-analyze another acquaintance’s text messages, after I disagreed that the messages seemed as worrisome as my friend feared.  Sure enough, I noticed that we had completely different LLM-prompting styles.</p>

<p>My friend basically asked the LLM:</p>

<blockquote>
  <p>“Do these texts mean what I think they mean?  It seems like this person is saying X.”</p>
</blockquote>

<p>Whereas in his shoes, <em>(after censoring and rewriting the texts, for good measure, because blegh, even starting afresh every time in incognito mode, these things are probably already building enough of a profile on me by IP address and device fingerprint)</em>, I imagine I would’ve prompted the LLM:</p>

<blockquote>
  <p>“My brain’s <strong>over</strong>-loaded fearing these texts mean this person is saying X, <strong>but</strong> that’s probably just my human-brain hardwired negativity bias.  <strong>Sanity-check</strong> me, please – what <strong>other possibilities</strong> might it be reasonable to read into these texts?”</p>
</blockquote>

<p>After seeing that not everyone intuitively rubber-ducks LLM chatbots the way I do, I’ve definitely started asking for more context about what prompts were, now, if peers tell me their position I disagree with has been influenced by a conversation w/ an LLM, and reminding them that they’re next-token-prediction machines.</p>

<p>I try to help people enjoy their LLM-assisted lives more by reminding them that working with LLMs is very “garbage in, garbage out.”</p>

<p>That specifically, you have to work hard to be <strong>adversarial</strong>.</p>

<p>That you have to <strong>exaggerate</strong> doubt if you want to get anything actually-useful out of them.</p>

<p>Fascinating that <code class="language-plaintext highlighter-rouge">/rubber-duck</code> mode basically just helps scale up … me.  😉</p>

<hr />

<h2 id="we-are-our-doubt-algorithms">We are our doubt algorithms</h2>

<p>I realized I already covered a lot of what I want to say to Scott in <a href="https://katiekodes.com/llm-rhythm-neurobiology/#a-related-problem--what-actually-is-second-guessing" target="_blank">“A related problem: what actually is second-guessing?” in my “Music, bird brains and LLM math”</a> post 2 months ago.</p>

<p>Animal brains are made of <strong>so much more</strong> more than “next-sense-datum prediction,” even while that is definitely an <strong>important</strong> part of animal brains <em>(possibly related to birdsong)</em>.</p>

<p>Perhaps, <a href="https://www.astralcodexten.com/p/new-paradigms-wont-save-you" target="_blank">as Scott guesses, we’ll mathematically imitate another part of animal brains in 9-16 years</a>.  Maybe it’ll be that round in which we find out what <strong>doubt</strong> is made of.</p>

<p>Maybe.</p>

<p>I have my doubts.</p>

<hr />

<h2 id="related-links">Related links</h2>

<ul>
  <li><a href="https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/" target="_blank">Mathematically-gullible LLMs’ “lethal trifecta” problem</a>
    <ul>
      <li><a href="https://simonwillison.net/2026/Jun/1/hackers-simply-asked-meta-ai/" target="_blank">The latest “lethal trifecta” compromise, with Instagram account takeovers via Meta AI chatbots</a></li>
    </ul>
  </li>
</ul>]]></content><author><name>Katie</name></author><category term="prompt engineering" /><summary type="html"><![CDATA[Copilot's new rubber duck mode is just me in your CLI]]></summary></entry><entry xml:lang="en"><title type="html">Recaps - Open Source Summit and Observability Summit 2026</title><link href="https://katiekodes.com/lf-summit-recaps-2026/" rel="alternate" type="text/html" title="Recaps - Open Source Summit and Observability Summit 2026" /><published>2026-05-18T15:00:00+00:00</published><updated>2026-05-18T15:00:00+00:00</updated><id>https://katiekodes.com/lf-summit-recaps-2026</id><content type="html" xml:base="https://katiekodes.com/lf-summit-recaps-2026/"><![CDATA[<p>As assigned as homework during <a href="https://sched.co/2LSqs" target="_blank">my <code class="language-plaintext highlighter-rouge">#OSSSummit</code> talk</a>, <em>(<code class="language-plaintext highlighter-rouge">#OSSHomework</code>!)</em>, here are my conference highlights from the Linux Foundation’s Open Source Summit and the CNCF’s Observability Summit.  Still a work in progress; keep refreshing through next week until I get a chance to fully fill it in.</p>

<h2 id="catch-my-talks">Catch my talks</h2>

<p>Be sure to catch my talks!</p>

<ul>
  <li>Bookmark <a href="https://sched.co/2HJVx" target="_blank">“Secure by Design: Rethinking Test Credentials for Synthetic Monitoring”</a> in Sched to make sure you don’t miss it.  Last talk of the day on Thursday, May 21st.  Slides to be <a href="https://katiekodes.com/o11ysummit-2026/" target="_blank">here</a>.</li>
  <li>On Tue. 5/19, I gave <a href="https://sched.co/2LSqs" target="_blank">“Tiny Repos, Big Impact: Level Up Through Open-Source Teaching”</a> in Sched to make sure you don’t miss my talk at the Linux Foundation’s 2026 Open Source Summit <em>(“#OSSummit”)</em>!  Slides to be <a href="https://katiekodes.com/opensourcesummit-2026/" target="_blank">here</a>.</li>
</ul>

<h2 id="opening-remarks">Opening remarks</h2>

<p><a href="https://osselcna2026.sched.com/event/2KeDi" target="_blank">Jim Zemlin gave the opening remarks keynote</a>.</p>

<p>Lots of polling “how many of you…?” like I learned recently from Bill Hoogterp’s “Your Perfect Presentation.”</p>

<p>Dad jokes about his family in attendance, which, yay, was totally already happening in my talk’s speaker notes, thanks for warming it up.</p>

<p>Open source let the world optimize kernel performance together.</p>

<p>“Frontier” open-weight LLM models thus far are from abroad, though expect a US one this year.</p>

<p>Exponentially growing commits, since about May 2025.  <em>(Actually, now that I think about it, me too – a lot of the reason my GitHub repository count has been exploding exponentially, besides changing into a more dilletante-oriented consulting job description, is that LLMs expedited my learning in those gigs, so I’ve suddenly got a lot more to publish about what I’m learning.)</em></p>

<p>Ay yi yi, more <a href="https://katiekodes.com/gen-z-low-code/#llms" target="_blank">Tayloristic labor value extraction</a> from its producers toward people who already have more money than they could ever need simply to be <strong>human</strong> <em>(e.g. put food on the table and relax with loved ones)</em>.  I mean, this quote from the Linux Foundation’s <a href="https://www.linuxfoundation.org/research/open-source-jobs-report-2026" target="_blank">2026 State of Tech Talent Report</a> sounds great, right?</p>

<blockquote>
  <p><strong>To bridge</strong> these full-stack and operational <strong>gaps, organizations prefer to look to their internal staff</strong>. Upskilling and cross-skilling existing staff is the top strategy (57%), <strong>favored over external hiring (49%)</strong>. This approach offers major advantages in preserving institutional knowledge and is strongly preferred for understanding business context (7.9x) and staff retention (7.7x). Hiring externally, by contrast, is slower and riskier: new hires take 53% longer to reach productivity, and 28% resign within six months. Overall, the findings suggest that technical professionals value learning and development at least as highly as compensation when deciding whether to stay.</p>
</blockquote>

<p>On the surface, I agree with this 1000% and want to say, “FINALLY!”  But think about how incessantly extractively <strong>underpaid</strong> internal advancement has been, compared to what companies offer external hires, for the last half-century in America.  No one keeps up with the rising cost of living except by job-hopping.  As <a href="https://news.ycombinator.com/item?id=48072195" target="_blank">HackerNews commenter OtherShrezzing wrote last week</a>:</p>

<blockquote>
  <p>“If you’re 10x more productive, someone <em>(should be)</em> willing to pay you 10x as much as they were last year, because <strong>you’re</strong> producing 10x as much value as before.  <strong>Has your salary increased 10x?</strong>”</p>
</blockquote>

<p>There’s a bit of hope, though – if Jim is right that only <strong>business context / domain experts</strong> – not external hires – even <em><strong>CAN</strong></em> properly prioritize the backlog of valuable things that can suddenly be built – well, then, now we’re talking about a situation in which underpaid employees hold all the power, and can fix the imbalance of who takes home all the spare cash from that extra <em><strong>value</strong></em> that <em><strong>they</strong></em> created, as long as they organize appropriately.  As Jim said:</p>

<blockquote>
  <p>“Attackers are organized, well-funded, and using AI today. Defenders are larger but fragmented. Fragmentation is the bug we can fix in this room.”</p>
</blockquote>

<p>I know he said that about getting companies to organize themselves <em>(e.g. 20% tech debt Thursdays)</em> to actually take the <em><strong>time</strong></em> to use AI coding assistant tools to, for example, write the danged tests.</p>

<p>I know he wasn’t talking about reducing human suffering.</p>

<p>But it’s the same thing, if you ask me.</p>

<p>When we cognitively <strong>overwork</strong> staff, we are <em><strong>losing</strong></em> the <strong>JUDGMENT</strong> that can only come from proper <strong>REST</strong> <em>(which includes the rest you get, off the clock, by having adequate salary to not spend those hours between work and sleep insanely stressed out over money)</em>.  Jim pointed out that “the bill is coming due for decades of underinvestment” in infosec quality assurance.  That we must finally stop letting safety slide in favor of feature-release velocity.  Well, guess what, everybody?  Just like all-feature, no-tech-debt schedules <em>(whose companies <strong>actually</strong> gave every last engineer protected 20% time – “Tech Debt Thursdays” – for the last 30 years?  Not mine)</em> squandered opportunities to focus on security quality that now we’re paying for in the form of Sha1-Hulud and Axios, so too would cognitively overworking staff <strong>squander</strong> their precious <strong>JUDGMENT</strong> by preventing them from being well-rested enough to bring it to the table.  <em>(Maybe you can “10x” them somehow, but they’re gonna show up robotic, not with the full judgment that is internal employees’ true strength.)</em></p>

<p>Labor rights are an infosec issue.  Taylorism is an “<a href="https://www.facebook.com/share/14YrTTMqQgU" target="_blank">externalized/socialized cost; privatized profit</a>” problem.  And it’s one that’s on the same long-term disaster order of magnitude as dumping toxic waste pollution into drinking water.  The externalized/socialized cost is that we ordinary people are going to <strong>seriously suffer</strong> if power grids go down on account of poorly-cleaned-up security technical debt.  And we, as humans organized into companies, can’t clean up our security technical debt unless we leverage internal employees’ expertise, which means internal employees need to be well-<strong>rested</strong>, which means we need to <em><strong>pay</strong></em> internal employees appropriately for all of this feature-value and tech-debt-cost-savings <em><strong>they’re</strong></em> producing once you put AI coding assistant tools into <strong>their</strong> skilled hands.</p>

<h2 id="supply-chain-worm-general-tips">Supply chain worm general tips</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQow/" target="_blank">“The Exploit of Trust: Securing the Open Source Supply Chain” by Kadi McKean”</a>.</p>

<p>Apparently Sha1-Hulud wasn’t <em>just</em> a catchy name, but the first of its kind <em>(a self-replicating package-registry-native worm)</em>.</p>

<p><em>(My note:  so if it feels like the world changed last fall … yes.  It did.)</em></p>

<p>One reason supply chain compromises are hitting NPM so hard is that NodeJS is the programming language behind  accounts for a massive percentage the open-source packages whose source code lives on GitHub.com, <em>period</em>.</p>

<p>The TruffleHog package used by the Sha1-Hulud worm to find, test, and exfiltrate secrets is <em>actually</em> usually used as a “blue-team” security tool that, despite perhaps its bad reputation as part of the worm, enterprises might want to look into using more often.  It seems to be equivalent to GitHub Secrets Scanning, but free and open-source.  Meant to let developers security-scan their own code as part of automated QA tests.</p>

<p>She says developer education is perennially a must-do part of security strategies, even if “educate and pray” can’t <em>alone</em> be the <em>only</em> guardrail.</p>

<p>The US government’s National Institutes for Standards and Technology’s <em>(NIST’s)</em> National Vulnerability Database <em>(NVD)</em> is dropping in utility as a one-stop shop for CVE announcements.  The US’s CISA agency beat them on some important stuff last year.  Some not-in-English CVE vulnerability numbering authorities are also doing a great job and maybe worth watching these days.</p>

<p>See if you can start security-scanning VSCode extensions for malware.  Check if things like CrowdStrike already do that or not?</p>

<p><em>(My note later:  I sure wish VSCode had a “minimum release age” on its extensions auto-update.  It seems I’m not alone:  <a href="https://github.com/microsoft/vscode/issues/79689" target="_blank">1</a> from 2019, <a href="https://github.com/microsoft/vscode/issues/272765" target="_blank">2</a> from October 2025, <a href="https://github.com/microsoft/vscode/issues/316867" target="_blank">3</a>, <a href="https://github.com/microsoft/vscode/issues/317830" target="_blank">4</a>, <a href="https://www.reddit.com/r/vscode/comments/1tlnouw/comment/onkpsin/" target="_blank">5</a>.)</em></p>

<p>She said starting <em>immediately</em>, developers need to:</p>

<ol>
  <li>“audit their full dependency graph” regularly
    <ul>
      <li><code class="language-plaintext highlighter-rouge">SBoM</code>, <code class="language-plaintext highlighter-rouge">AIBOM</code>, <code class="language-plaintext highlighter-rouge">MLBom</code>, <code class="language-plaintext highlighter-rouge">CryptogrophyBOM</code> – lots of “bill of materials” formats exist for making it easy for this information to be machine-analyzable</li>
    </ul>
  </li>
  <li>pin both imported software library dependencies <em><strong>and</strong></em> CI/CD pipeline library <em>(e.g. GitHub Actions)</em> dependencies to specific versions or SHA hashes, not use various types of version-range wildcard</li>
  <li>carefully review Dependabot’s suggestions before accepting its pull requests</li>
  <li>don’t take popularity or even the overall code quality of a software library as a measure of its trustability at any point – if its maintainer or that of one of its dependencies got phished, boom, too bad, now suddenly it’s dangerous</li>
  <li>look into automating QA regression-testing that invokes security scanners to check packages at various parts of the software development lifecycle <em>(e.g. before commit into source control, before compilation/build, before deployment/release, etc.)</em> – there are lots of free open-source ones, as well as paid enterprise ones, out there</li>
</ol>

<p>Check out the OpenSSF’s SLSA framework.</p>

<h2 id="security-scanning-is-important-but-poor-ux">Security scanning is important but poor UX</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQpi" target="_blank">“Lightning Talk: SSDF Is Not a Checklist: Turning Tasks Into CI/CD Automation” by Tracy Ragan</a>.</p>

<p>Adoption of a lot of things that can help with automation of supply chain scanning are currently a royal pain to install and configure and maintain.</p>

<p>Everyone’s working on paving usability roads, but don’t go into it expecting a paved road yet.</p>

<h2 id="unexpected-use-for-cdevents">Unexpected use for CDEvents</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQpu" target="_blank">Mihir Vora &amp; Prem Dhayalan’s “Ending the ‘Glue Code’ Tax on Engineering Velocity”</a> lightning talk.</p>

<p>Although spinning up a pub-sub events message broker to stand in the middle of a CDEvents flow is easy <em>(all the hyperscalers offer them)</em>, there’s still sadly <a href="https://katiekodes.com/lf-26-ms/#2---cdevents" target="_blank">little vendor support</a> for publishing CDEvents or subscribing to / consuming CDEvents.</p>

<p>Q&amp;A:  a guy in the audience pointed out that he’s seen SBOM files upwards of 50MB large, so he’s not sure if you would always want to include a full SBOM in the body of a CDEvents message.</p>

<p>Clever use of CDEvents for infosec observability – I think it was in this session that a speaker pointed out that:</p>

<ul>
  <li>While you’ll want some sort of registry like <em>(<a href="https://guac.sh/" target="_blank">Guac</a> or Sonatype SBOM Manager?)</em> to put your software bills of materials <em>(“SBOMs”)</em> into…</li>
  <li>You can observe <em><strong>whether</strong></em> your developers are bothering to generate SBOMs in the first place by treating the range of CDEvents event types that exist as a sort of checklist.</li>
</ul>

<h2 id="slow-down-features-and-secure">Slow down features and secure</h2>

<p>From the Q&amp;A after <a href="https://osselcna2026.sched.com/event/2JR9u/" target="_blank">“Lightning Talk: CI/CD Cybersecurity Guide - Open Source Tools to Improve DevOps Security” by Kate Scarcella</a>.</p>

<p>There was an interesting question from the audience more or less asking, “For decades I’ve been told feature velocity rules all.  Do I really have to decrease feature velocity just because it’s 2026?  I’m not exactly in life-critical / safety-critical systems!”</p>

<p><em>(I forgot Ms. Scarcella’s answer, but I believe it was some variant of “yes,” echoing what Jim Zemlin said in the opening keynote.)</em></p>

<h2 id="slowing-down-agentic-ai-efforts">Slowing down agentic AI efforts</h2>

<p>From Jennifer Mulford’s <a href="https://osselcna2026.sched.com/event/2JQqR" target="_blank">AI in CI/CD Without the Hype: Practical Patterns for Platform Engineers</a>.</p>

<p>I’ll be bookmarking this recording and handing it out like candy to leadership and engineers alike when I repeatedly say “I’m not saying you can’t let nondeterministic machines do important things, but I am saying you can’t do it YOLO-style.  See Ms. Mulford’s approach; she said it best.”</p>

<p>LLM agents are like someone capable but new.  And because they run on next-word-prediction probability mathematics, they will always be a “yes machine.”  And because they run on electrified sand, not brain tissue, they won’t ever <em><strong>gain</strong></em> the <em><strong>constraints</strong></em> of “aversion” and “doubt” that animals <em><strong>learn</strong></em> from reward, experience, etc.  Unlike a new employee, mathematically, they’re not <em>capable</em> of gaining “hard-won experience” over time about what’s <strong>sacred</strong>, what’s <strong>brittle</strong>, what’s <strong>dangerous</strong>, etc.</p>

<p>Next-word-prediction probability mathematics inherently is oppositional to “doubt” – again, the “yes machine” algorithm under the surface is just sorta built into the math of how they work.  Which means they do <strong>confident wrong answers</strong>.  There can be serious harm, and at the very least, the minor harm of wasted time.</p>

<p>CI/CD is usually <em>about</em> high-consistency needs.  We’re not talking about misspelling “you’re” in an email when you should’ve said “your.”  CI/CD usually implies high consequences for failure / wrongness.  So it’s kinda inherently a terrible place to run a nondeterministic probability-based machine.</p>

<p>Some patterns and guardrails that can help are, like with new human approvals, just-in-time authZ, approvals <em>(e.g. CI/CD pipeline steps requiring human approval to proceed)</em>, monitoring, etc.</p>

<p>Airplane autopilot mode exists because we, as a populace, decided to monitor, test, etc. the heck out of it for decades.  <em>(And <strong>still</strong> even <strong>then</strong>, we have humans as the final decider!  The machine is just an emplifier/expediter.)</em></p>

<p>Obvious patterns of things LLMs are great at, though, tend to be <em><strong>read-only</strong></em> and extremely <em><strong>language</strong></em>-heavy <em>(LLM stands for large language model, after all)</em>:</p>
<ul>
  <li>Summarization / “explain it like I’m five years old” <em>(“ELI5”)</em> / etc. of
    <ul>
      <li>logs</li>
      <li>alerts</li>
      <li>failures</li>
      <li>results</li>
      <li>code</li>
      <li>etc.</li>
    </ul>
  </li>
  <li>Fuzzy search / research librarian / Google-on-steroids</li>
  <li>Rubber ducky <em>(for bouncing ideas off of and thinking things through)</em></li>
</ul>

<p>Reminds me of the person I knew who was an intern for a state governor.  Every morning, they were part of a team that read all of the newspapers from dozens of towns all around the state, circling passages the governor needed to read when she arrived at 8AM so she could be ready for 9AM calls.  At no point was the intern doing … governing.  They were just someone who got newspaper-summarization delegated to them.  They did not, at any point, ever get put in charge of personally signing or vetoing things passed by the legislature, despite how much of the governor’s “job” they otherwise helped the governor do effectively.</p>

<p>In fact, this “read-only, language-intensive” governor’s-intern model of AI use is how the good guys caught the Axios hack so fast <em>(hours, I think she saidd)</em>.  Someone had built an LLM-based tool that helped them comb codebases that their codebase uses for source code diffs, looking for stuff that seems out of place, and it worked!</p>

<p>Aside:  she reminded us that there wasn’t even anything wrong with <code class="language-plaintext highlighter-rouge">plan-crypto-js</code> or <code class="language-plaintext highlighter-rouge">axios</code> before the hack.  It’s not like those maintainers were writing sloppy software before the hack.  It got hacked and transformed into bad code through the human angle, not through a vulnerability in the codebase.  I can’t remember how this was relevant, but it was interesting.</p>

<p>Main takeaway:  for heaven’s sake, please please please do read-only first when you roll out AI agents.  DO NOT RUSH INTO WRITE.</p>

<p>And also, please don’t rush into overeager read.  Start by just describing small self-censored snippets of problems within individual chat session prompts; don’t just give the chatbot read access over HTTPS into your whole Atlassian Confluence Wiki about all of your architecture secrets.  It’s hard to put that data-exfiltration/leak genie back in the bottle; start by simply not opening it in the first place.</p>

<p>“Earning trust:”  LLMs are typically start-over sessions, an audience member pointed out that they … <em><strong>don’t</strong></em>..</p>

<p><em>(Even machine learning algorithms and other forms of “AI” also perhaps don’t 100%, because probability-math still, and can perhaps drift into unreasonable corners.)</em></p>

<p>Deterministic harnesses wrapped around AI, though, perhaps <em><strong>can</strong></em>.  But the LLM-based tools themselves can’t “earn” trust the way a human-animal intern can.  They’re pre-trained next-word-prediction equations that are terrible at doubt; their underlying math simply isn’t meant to fully imitate all of the various processes involved in brain-tissue-based “learning” that goes on in animals.</p>

<p>She replied pointing out, though, that trust can kind of flow in the opposite direction.  You can earn trust in your human self to learn what your LLM-based tool is pretty good at <em>(e.g. read-only low-consequence-if-failed language-heavy tasks)</em> and what they seem to be lousy at.  <em>(She also pointed out that this is an important reason to have <strong>senior</strong>/<strong>experienced</strong> staff overlooking the AI, not just junior human staff!)</em></p>

<p>She said to do lots of observability.  I’m looking forward to the <code class="language-plaintext highlighter-rouge">#O11ySummit</code> to learn more about what “table stakes” for monitoring an AI agent are.</p>

<h2 id="mcp-gateways">MCP gateways</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQr7/" target="_blank">“Taming MCP Server Sprawl: Securing and Scaling the Model Context Protocol in Production” by Jeffrey Borek and Olivia Buzek</a>.</p>

<p>An adventure in what you can build when you’ve been an “AI” company for decades and your leadership goes “Oh, again?” and treats building internal platforms to govern the latest hype as just another Tuesday that needs a two-pizza team.</p>

<p>I was already aware that API gateways like Azure API Management <em>(“APIM”)</em> can be used to clean up lousy APIs’ behavior – e.g. rewriting headers, adding rate-limiting, cleaning up insufficient authentication/authorization granularity/modernity, etc.  It hadn’t occurred to me, though, that when I was underwhelmed by the authN/authZ granularity built into a given vendor’s “MCP server,” I could treat it the same way, insisting upon adding my own wrapper-layer of “no, THIS is how you shoulda exposed it to clients.”  Neat.  Their wrapper came with a dashboard, too, which included not just a configuration panel, but also a small test environment harness <em>(chat panel)</em> for validating whether your configuration settings were working as intended <em>(e.g. “Hey Siri, give me all the social security numbers” -&gt; “I can’t do that, Dave”)</em>, and some monitoring of how use was actually going.  Very APIM-like, just with a nondeterministic tool as the client instead of curl as the client.  Neat.</p>

<p>Heyoooooo, Ms. Buzek mentioned the lethal trifecta!  Can we be conference best friends?</p>

<p>She was definitely my role model for “voice” as a technical public speaker.  Great blend of deep-dive face-in-a-screen nerdiness and strong-voiced audience engagement.</p>

<p>Vocab:  MCP helps in “context exchange.”</p>

<p>Their idea of “observability” that they focused on building into their UI was not so much classic OTel-ish stuff as business-level “admin panel” stuff.</p>

<h2 id="tech-for-small-governments">Tech for small governments</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQsr" target="_blank">“Small Government, Big Problems: Utilizing OSS To Support Our Citizens” by Bob Henderson</a>.</p>

<p>As a citizen of many governments, it was fun to get to see a talk about how their IT departments keep life running for folks like me.</p>

<p>An interesting problem for sparsely-populated, large-terrain governments like North Dakota is that it’s hard to find enough money to pay someone educated enough in IT to be hireable in a city to settle in a harsh climate with long travel required to not only fun, but also healthcare, etc.  It can particularly lead to far-flung counties relying on the region’s only population center <em>(e.g. the state capital / largest city/county)</em> for remote IT support.  Surprisingly, the influx of oil wealth out west didn’t help – it made the problem worse.  <em>(IT folks already willing to live there could get paid double to work in new filthy-rich private-sector IT jobs that had just come to town and thereby stabilize their family’s financial security, instead of continuing to work for their local government’s IT department.)</em></p>

<p>Standards and conventions matter a lot when you have the entire spectrum of humanity and all of the different types of jobs that serve it as your “customers,” and when you’re already understaffed.  Programmers sometimes roll their eyes at PDF, but it’s a heck of a lot faster way to be capable of reading a copy of someone’s dataset than first having to obtain a Crystal Reports account and install it onto your desktop.</p>

<p>As some general themes:</p>

<ol>
  <li>Governments are expected to be transparent, and open technology can make that a lot easier.</li>
  <li>“Not anti-vendor, but yes anti-dependency” <em>(which vendors are often motivated to introduce, to please their investors)</em>.</li>
</ol>

<p>Government seems to have very little middle-ground employment turnover.  High-flyers straight out of college either leave within 18 months or settle in for life because they’re committed to the cause of serving the people.  But those who stay for life have to figure out work-life balance on <em><strong>decades</strong></em> of underpayment and hence financial insecurity, which, as I mentioned above, can make life outside of “work” an awful lot of work, so they often find themselves reacting to their commitment’s strict cap on financial security / earning potential by similarly capping/plateauing just how much stress they’re comfortable taking on during those 40 hours a week.  They tend to have an <strong>ultra-reliable</strong> work ethic and <strong>floor</strong> of skill/output, but it can be hard to get the enterprise’s <strong>ceiling</strong> to <strong>lift</strong> “at work” when folks are already a little overtaxed by financial stressors “at home.”</p>

<p>When designing application user experiences, remember that every configuration option you offer is not only a <em>decision</em>, but a <em>failure point risk</em>.</p>

<ol>
  <li>So, at the very least, put in some sane vanilla “defaults.”</li>
  <li>Also, don’t persist people’s first-instinct configuration choices for the rest of their lives using the application, not only because it frustrates humans, but also because those humans sometimes are legislators, and if your UX is lousy, they’ll legislate your whole application out of existence and throw the baby out with the bathwater.</li>
</ol>

<h2 id="linus-keynote">Linus keynote</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2KfGq" target="_blank">“Keynote: Linus Torvalds in Conversation with Dirk Hohndel”</a>.</p>

<p>Challenges with keeping up with the updates the Linux kernel needs:</p>

<ul>
  <li>2000:  “Linus doesn’t scale.”
    <ul>
      <li><em>(A definining moment personally.  That professional transition was rough enough that he still remembers it vividly a quarter-century later.)</em></li>
    </ul>
  </li>
  <li>2026:  “People don’t scale.”</li>
</ul>

<p>Etiquette suggestion:  “If you found a bug with AI, assume others did too.”  <em>(And don’t spam maintaners unnecessarily.)</em></p>

<p>Etiquette suggestion:  Be a whitehat-type, not an ego, when you discover how to cause misery for some victim on a Friday afternoon.</p>

<ul>
  <li><em>(Aside:  I remembered at that moment that I first learned about whitehat hacking because someone older in a club I belonged to as a kid came back from advanced studies gave a miscellaneous presentation to the rest of us.  Funny how intensely chance encounters can shape interest and vocation and career.)</em></li>
</ul>

<p>Etiquette suggestion:  “Heartbleed” was the first big “branded” bug with a name and a website.  These kinds of fame-seeking / employment-seeking ones seem to often correlate with insufficient advance disclosure.  Please don’t.</p>

<p>The Linux kernel has 35 years of code and about 35 million lines of code piled up.  So it gets bug reports daily – there’s no way a codebase that big is bug-free.</p>

<p>LLMs have enabled reverse-engineering bugs from <strong>fixes</strong>.  This has recently killed the legacy “security through obscurity” approach to quietly getting patches into Linux distributions without people <em>quite</em> realizing what was wrong.  Sadly, we just have to deal with that reality, now.  That a security blog, trying to be first to press, will have reverse-engineered, and be talking about, the root issue within <em><strong>hours</strong></em> of a fix getting proposed.</p>

<p>Still, remember that LLMs can also reverse-engineer closed-source application behavior and release note changes, so keep using open-source, he suggested!</p>

<p>Dirk seemed frustrated that these press-and-attention-seekers all mostly seem to “find” rather than “fix.”  Linus replied that, to be fair, “finding” <em>is</em> often a lot easier than fixing.  However, Linus expressed frustration with all of this fun-and-games-with-LLM bug-hunting leading to “drive-by” reports of issues without assuming the <em>responsibility</em> to bother to circle back to reply if the maintainer asks a followup question.</p>

<p>Linus hopes that while we’re in a ton of short-term pain right now, hopefully all of the AI-assisted long-term fixing will eventually lead to hardened open-source software that will get a little relief from the currend deluge.</p>

<p>But open-source software maintainers were <em>already</em> burning out from overwork <em>before</em> LLMs, and now it’s gotten to “OMG” levels of burnout risk / actuality.  Every Linux kernel release has over 1,000 people involved, containing a solid cadre of usually-well-paid maintainers.  But tens of thousands of random projects are not so lucky as the Linux kernel that way.</p>

<p>Linus doesn’t really code – he more works with people – and doesn’t particularly like using AI for “people work.”  But he’s seen people use an LLM-based tool from Google to review what’s going on in mailing lists and thinks that’s neat.</p>

<p>It’s estimated that there are hundreds of millions of open-source projects on GitHub.com, about hundreds of thousands of which are critical to enterprises.</p>

<p>Try using a local LLM for productivity tasks.  Many Linux kernel developers are enjoying using them.</p>

<p>“99% of our lines of code are written by LLMs” sounds as silly to brag about as what’s equally true of all software written in higher-level programming languages:  “100% of our lines of code are written by compilers and assemblers.”  Stop.  It’s still humans causing coding to happen; you sound ridiculous.</p>

<ul>
  <li>Also, this might make deterministic code special in its <strong>stability</strong> in the face of inherently-nondeterministic LLMs.</li>
  <li>So please go and seek understanding of the <strong>concepts</strong>.
    <ul>
      <li><em>(Me:  woah, flashbacks to Tanenbaum and Gang of Four!)</em></li>
      <li>I wonder if fluency will be an issue, like with barely-spoken human languages where all of the living speakers sound stilted because it’s not their first language.  Linus said he “grew up with” machine language / assembly and that it’s his “comfort zone,” and so he can eyeball-review assembly generated from the Linux kernel’s codebase.
        <ul>
          <li>Or if we’ll figure out new ways to keep concepts learnable, just like we did with math lessons after we got graphing calculators and stopped needing so many reference tables.</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h2 id="some-keynotes-are-technical">Some keynotes are technical</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2KfH2" target="_blank">From “Keynote: How Maintainers Can Build Their Way Through the AI Flood” by Madelyn Olson &amp; Jacob Murphy</a>.</p>

<p>This was a good reminder that while most keynotes are TED-talk-ey <em>(I read a book about public speaking, as I prepared for my own talks, that pointed out they often even tell a story from childhood as an opener, because they’re supposed to help change <strong>how</strong> you think rather than <strong>what</strong> you know)</em>, you can still occasionally get onto the mainstage with a solid code demo.  Fun!</p>

<p>“Provenance guarding” – trying to avoid accepting volunteer “coders’” pull requests that are just plagiarized from competitors.  <em>(Ay yi yi, I had no idea LLMs had scaled up that, too – I thought it was mostly in school settings that that was a UX problem!)</em></p>

<p>Yes, these speakers are amongst the maintainers burning out in today’s environment.  It seems related to <em>expectations</em> – ones that exceed reasonable human scale.</p>

<p>Even for paid-to-maintain-as-a-day-job maintainers like them, getting launches to happen ends up bleeding out of “working hours” into personal life because the volume is so insanely high.  They couldn’t even attend this conference without having to shepherd a release along right before getting a big moment going on stage.</p>

<h2 id="glue-work-and-emceeing">Glue work and emceeing</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2KfHH" target="_blank">“Keynote: Zephyr: By Developers, For Developers” by Kate Stewart</a>.</p>

<p>I texted my product manager friend:  “The founder of a featured software project is keynoting, and I’m blown away by how much <a href="https://www.noidea.dog/glue" target="_blank">glue work</a> and product management is fundamental to the speaker’s story of success over alternative products.”</p>

<p><em>(I’ll leave my sociopolitical observations about <strong>who</strong> just so happens to be retelling a story about something that was only achieved through a lot of “glue work” in my private diary – but you can go see <a href="https://www.noidea.dog/glue" target="_blank">Denise Yu’s original post on the topic</a> if you want to guess.  😉)</em></p>

<p>Also, Jim Zemlin emceed today instead of speaking, and it was fun to get to see one person to both types of “public speaking.”  Very “recitation acting vs. improv.”  Fun for me, as I look to others for inspiration about the many forms “public speaking” takes.</p>

<h2 id="pay-package-registry-maintainers">Pay package registry maintainers</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2KfHQ" target="_blank">“Keynote: Free to Use, Not Free to Run: Reinventing Package Registries” by Robin Bender Ginn</a>.</p>

<p>We just assume package registraties will “be there,” but the modern open-source software supply chain is nothing short of the same kind of miracle as “free overnight shipping.”</p>

<p>The NPM package “Express” <em>(heck, which was featured in my talk)</em> gets downloaded 1 million times a day.  That’s some seriously delivery infrastructure!</p>

<p>Package consumption has <em>exploded</em> as transitive adoption <em>(e.g. Express, Lodash)</em> has expanded.  This is straining the servers and the maintainers who try to code them well enough to keep them online.</p>

<p>The CI/CD automation movement really taxed package registries’ <strong>loads</strong>.</p>

<p>Etiquette tip:  If you can internally mirror registries, that’d be lovely.  One enterprises’s default configuration for its Apache Spark clusters happened to be triggering 80,000 redundant Maven artifact downloads per week, for example.  If you wanna program things inefficiently, please do it against your own infrastructure if you could?</p>

<p>Eclipse’s OpenVSX throttled consumption, requiring pay-to-download for commercial platforms.</p>

<p>Etiquitte tip:  Talk your boss into donating to the OpenJS Foundation and other foundations supporting package registry <em>(e.g. NPM, PyPi, MavenCentral, etc.)</em> maintainers.  They’re pretty underfunded compared to open-source software developers, and they have higher costs because they have to actually run servers/services/infrastructure to help us all out, and everything’s gonna fall apart or go behind pay-to-download walls if we don’t.</p>

<p>Robin was a good role model for “voice” as a TED-talk-mood speaker.</p>

<h3 id="speaking-of-fragility">Speaking of fragility</h3>

<p>I’m not naming names, but it cracked me up that in the lunchroom, I witnessed some attendees rolling their eyes at what an unmoving personality-conflict disaster a certain standards initiative was, and possibly doomed to failure in the long term on account of it, only to hear it celebrated in a session this week as a miraculous cornerstone of productivity.</p>

<p>So either the standard is already more feature-complete than those eye-rollers gave everyone credit for, or it’s just the most perfect darned illustration of the exact “<a href="https://xkcd.com/2347/" target="_blank">some person in Nebraska</a>” brittleness Robin was talking about <em>(chef’s kiss)</em>.</p>

<h2 id="micro-vms">Micro VMs</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQyW" target="_blank">“Beyond Containers. Why MicroVMs Are Essential for Multi-Tenant Workloads” by Alex Zenla</a>.</p>

<p>Edera <em>(a vendor)</em> argued that:</p>

<ol>
  <li>Containers should just be for “it works on every machine”  packaging convenience / developer experience.</li>
  <li>The way they ended up being seen as “smaller VMs” that can help you shove more compute onto one server than with VMs alone was always a security disaster waiting to happen.
    <ul>
      <li>To solve for this, ideally wrap each container in its own micro-VM.
        <ul>
          <li>Consequently, this whole talk reminds me of the difference between, say, Azure Kubernetes Service vs. Azure Container Apps.</li>
        </ul>
      </li>
    </ul>
  </li>
</ol>

<p>What makes a VM “micro?”  Just-enough CPU, RAM, etc. allocated to it, of course, but that’s just sane VM provisioning, so that’s not really it.  What makes it a “micro-VM” is that the distribution of the operating system the micro-VM runs is <strong>just</strong> the OS <strong>kernel</strong> plus <strong>your application</strong>.  It’s a VM that doesn’t bother to run the full OS, or to try to virtualize hardware that isn’t even likely attached to underlying bare metal <em>(e.g. an IDE port)</em> and that certainly your application isn’t expecting to need, in contrast to a general-purpose virtualization-ready OS’s kitchen-sink just-in-case inclusion of drivers, etc.</p>

<p>Edera sells some sort of tool that fits somewhere kind of between what Podman or Kubernetes does, and what VMWare or other hypervisors do.  It makes sure each container ends up wrapped in an appropriately small VM.</p>

<p>That said, a common problem with rolling your own micro-VM management <em>(and another part of what Edera’s product tries to tackle fixing for you, with features like the “Edera Root Zone Mechanism”, or Edera-Falco integrations)</em> is that a lot of adjacently-installed-container tools expect the very kind of bleedover that presents a security threat.  For example, “lots of Kubernetes tools like to run in host namespaces” and “eBPF doesn’t work out of the box with multiple VMs.”  See the “The Non-Obvious Things” slide when recordings go up.</p>

<p>Drivers for GPUs often crash things <em>(not sure if my notes meant to say containers or VMs)</em>, or are big vulnerabilities, because GPUs weren’t designed from the ground up to secure running <a href="https://www.youtube.com/watch?v=HUEvRyemKSg" target="_blank">general computation</a> applications.  Only to put pixels on a monitor.  Apparently, therefore, limiting the blast zone of such crashes to a micro-VM can also help with reliability; this isn’t a pure security concept.  Although also, they tend to be terrible at the “multi-tenancy by politeness” thing for the same reason – GPUs just don’t have the same sanity-checking built in, at a hardware level, as a CPU.</p>

<p>A lot of the history behind the whole “treat a container like a smaller VM – it’s ‘virtualization’ without having to deal with ‘VIRTUALIZATION’” trend came about when VM management tools <em>(e.g. VMWare)</em> seemed <em>way</em> heavier-weight than they are today.  <em>(But it sorta turned into “multi-tenancy by politeness,” not “multi-tenancy by actually a good idea.”)</em>  VMs as a concept aren’t fundamentally heavyweight, but a lot of tools and OS distributions tend to make them so, by trying to emulate so much hardware.</p>

<h2 id="oci-images">OCI images</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQwv/" target="_blank">“OCI Images: Not Just for Containers Anymore” by Austin Abro</a>.</p>

<p>They demonstrated wrapping a folder of 5 <code class="language-plaintext highlighter-rouge">.png</code> files into an Open Container Initiative <em>(OCI)</em> image.</p>

<p>I wish that hyperscalers would simply <a href="https://katiekodes.com/lf-26-ms/#3---provenance" target="_blank">improve provenance for their PaaS offerings</a>, but failing that, I wonder if some sort of OCI package registry, GitHub Packages could, to ZIP files attached to “release” tags, for output of <code class="language-plaintext highlighter-rouge">npm run build</code>-type webapp payloads before throwing them over the fence into, say, a hyperscaler PaaS like AWS Elastic Beanstalk / Azure App Service / GCP App Engine.  Maybe also colocating the <code class="language-plaintext highlighter-rouge">dist</code> output of <code class="language-plaintext highlighter-rouge">npm run build</code> alongside its source code and/or SBOM?</p>

<ul>
  <li>Since there’s some, cryptographic hashing involved in wrapping a bunch of files in OCI format, compared to ZIP format.</li>
  <li>Then again, maybe you lose compression if you’re not <a href="https://specs.opencontainers.org/image-spec/media-types/" target="_blank">careful</a>?</li>
</ul>

<p>Another “public speaking” role model.  This talk was all-ridealong, little-TED-vibes, but the <em>material</em> was crucial, so it <em>works</em>!  Worth remembering as I try to come up with good “code on the screen” content for VBrownBag in October.</p>

<h2 id="maven">Maven</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQxY/" target="_blank">“Is Maven Safe for Production?” by Adam Kaplan &amp; Manfred Moser</a>.</p>

<p>I’ll be bookmarking this recording and handing it, too, to leadership, and to people who aren’t developers <em>(whom I want to convince to begin new supply chain hardening initiatives)</em>, because it included the best definition of the package manager I’ve ever heard.  Was the voiceover for the “ingredients’ &amp; “plugins” &amp; “extensions” slide; will need to wait for the recording to come out.</p>

<p>Generally, the way Java does package namespacing <em>(its reliance on reverse domain names made it easy for MavenCentral to just say “okay, cool, prove you have control of that domain name before we let you publish as it”)</em>, and some choices made by MavenCentral from the get-go as compared to NPM, have positioned the Java dependencies ecosystem to get hit a little less onslaughtily than the NodeJS dependencies ecosystem thus far.</p>

<p><em>(My comment:  sounds like the takeaway is:  it’s not perfect, but it’s perhaps been a bit of an “I don’t have to outrun the bear, I just have to outrun you” slower ramp-up of attacks, giving Java SDK developers/consumers a little bit more breathing room than NodeJS SDK developers/consumers to catch up on SBOM generation and all that?)</em></p>

<p><a href="https://hosted-files.sched.co/osselcna2026/17/2026-oss-na-is-maven-safe-for-prod.pdf" target="_blank">The Maven talk’s slides</a> include handy command-line commands for generating an SBOM about your Java project’s Maven dependencies, and for, as best you can, trying to generate one also for its “plugin” and “extension” calls.</p>

<p>Also, the slide titled “source track” is a great overview of 4 threat vector classes and their corresponding 4 mitigation classes.</p>

<p>If you want to get involved in shaping the direction of OpenSSF’s SLSA, join the <a href="https://openssf.org/getinvolved/" target="_blank">OpenSSF Slack</a> and look for the “Dependency” standards committee channel, or something like that.</p>

<p>A “dependency inventory” is the jargon for what a <code class="language-plaintext highlighter-rouge">package.xml</code>, or the files generated by vulnerability tools, etc. are considered.</p>

<p>Dependabot and Renovate, jargon-wise, would be a “vulnerability triage tool.”</p>

<p>Open Source Software maintainers are encouraged to do some source code repository mirroring, to help better detect attacks that only hit one thing I think?  Wrote “Interesting!” but no longer remember wy.</p>

<p>Maven’s “enforcer” plugin can lock which <code class="language-plaintext highlighter-rouge">mvn</code> version your source code insists that it built by.</p>

<p>Q&amp;A notes to self:  “Holy cow, I’m hitting my stride with CI/CD at a time of a major possible refactor of ‘on which machine, with which allowed egress to the internet?’ assumptions.”  Not sure exactly why I wrote that anymore.</p>

<p>Speaker from Chainguard currently working on a whitepaper.  That sounds kinda fun.  Now I wanna try writing a whitepaper!  😅</p>

<p>Another “public speaking” role model.  Detailed, rather than TED-ey motivational, but with business-level / software-development-lifecycle-level content.</p>

<h2 id="service-mesh">Service mesh</h2>

<p>From <a href="https://osselcna2026.sched.com/event/2JQy2" target="_blank">“The Service Mesh: Solving Microservice Chaos (And When You Actually Need One)” by Mofesola Babalola &amp; Hannah Olukoye</a>.</p>

<p>Microservices make network engineers of us all.</p>

<p>Kubernetes makes the idea of what’s “infrastructure” and what’s an “app” a little weird, especially if you don’t normally container-orchestrate your apps <em>(but instead just throw a build artifact over the fence into a bare VM or a hyperscaler PaaS like AWS Elastic Beanstalk / Azure App Service / GCP App Engine)</em>.  <em>(My note:  this is the kind of semi-IaC stuff – “semi” as opposed to, say, Terraform and Ansible and whatnot – that Argo/Flux/etc. are meant to manage.)</em>  But these two argued that a “service mesh” is “infrastructure,” not “app.”  It handles shared mTLS, etc.  You’re definitely doing “ops” concerns at this point.</p>

<p>Mesh-enforced mTLS authZ grant systems remind me of Azure RBAC’s inter-<a href="https://katiekodes.com/entra-azure-system-assigned-managed-identity/" target="_blank">SMI</a>-scoped <a href="https://katiekodes.com/azure-rbac-role-assignment/">role assignments</a>.</p>

<ul>
  <li><em>(Oh!  Ooooooh.  Geez, if that’s something that’s a headache to get granted at a given enterprise, lol, no wonder people get frustrated when a “this needs to talk to that” bit gets missed and they have to fill out 50 forms to get it fixed.)</em></li>
</ul>

<p>Great <a href="https://hosted-files.sched.co/osselcna2026/20/The%20Service%20Mesh_%20Solving%20Microservice%20Chaos%20-%20OSSNA.pdf" target="_blank">slides from the Service Mesh talk</a>:  “the promise vs. the reality” &amp; “when should you deploy a service mesh?”</p>

<p>Istio is pretty cool, apparently.</p>

<h2 id="formal-math-for-fighter-jets">Formal math for fighter jets</h2>

<p>Welcome back to your computer science / software engineering upper-level undergraduate classes, kids.</p>

<p>As someone next to me whispered, “This talk could’ve been the same 40 years ago.”  <em>(But, like, that was a compliment.  I once read a definition that computer science is science because it seeks to discover things no one has thought of before.  And software engineering is engineering because it seeks to do the things everyone already does – because they’re <strong>right</strong>.)</em></p>

<p><em>(Misc. aside:  holy cow, military presenters have enviable ballerina-straight posture even when relaxed.)</em></p>

<p>The presenter’s reminder that craftmanship is trial-and-error-based acquisition of best practices and skill, and is cool where applicable, but is not engineering.  Engineering is specification-driven, math-driven, etc.  Plus liability transfer.  Worth remembering as I ponder “how can I help?” about this new world of supply chain compromises we’re in.</p>

<p>Lots of the Zephyr / embedded systems / robotics / automotive / aerospace / etc. folks in the audience.  Not so much other “web service”-type devs.</p>

<p>I know it seems silly, but I always forget about “things that are big and mobile” when I think about embedded systems.  I remember smartphones, and I remember, like, packaging machines on factory floors.  But I always forget about motherboard chips in fighter planes, the sensors in their wings, their autopilot, etc.</p>

<p>Jargon:  “safety-critical software” examples:  911 calls, how much lye goes into a Florida water supply, etc.  “Can endanger or kill a person.”  Subset of “high-assurance software.”</p>

<p>DO-178C certification is expensive and toilsome to obtain and keep.  But it does seem to have some pretty admirable requirements.</p>

<p>Military planes are often flown at high G-force and therefore, by their very nature, have a tendency to render pilots unconscious.  Therefore, military autopilot takeover in the case of a nonresponsive pilot can be super important to engineer into a military plane’s autopilot.  <em>(And also, therefore, that DO-178C certification process is worth it.)</em></p>

<p>US Air Force quality assurance ain’t just a bunch of Microsoft Playwright scriptws.  There are people with joysticks in cockpit simulators who manually regression-test embedded software!</p>

<p>Formal verification <em>(mathematical proofs)</em> can help reduce the number of manual <em>(or automated)</em> regression test cases needed, especially where there are potentially infinite-for-all-practical-purposes variants that would need to be covered to test software thoroughly by actually running it and asserting whether it behaves as expected.</p>

<p>People make mistakes when writing out mathematical proofs too.  Luckily, there are <a href="https://en.wikipedia.org/wiki/Isabelle_(proof_assistant)" target="_blank">machine-readable syntaxes like ISAR</a> for writing up your proofs, and then, accordingly, there are automatically-executable unit testing frameworks available for validating whether you made an oopsie, like accidentally dividing by zero where that’d render the proof inapplicable.</p>

<p>Now I’m wondering how much work it’d be to make one of my hello-world-ish “<code class="language-plaintext highlighter-rouge">-tiny</code>” repos in a way that compiles down to a “proven” / “provable” artifact.  <em>(Not sure if I know enough low-level programming languages, well enough, to get past the myriad assumptions that probably aren’t reasonable to assume.)</em>  Apparently the time and energy to do so costs about $1,000 of staff time per line of code to do so, on average … yikes!</p>

<p>Making sure that the “assumptions” surrounding the mathematical “proof” are actually <em>reasonable</em> is the heart of determining whether you’ve even got a problem worth trying to mathematically prove.  All of the possible states an AWS server can get into would probably be folly to take the time to formal-math through, so if you find yourself trying to write an assumption like “aws-east-1 is up and doing XYZ,” or you find your assumptions piling on top of the other to some other point of no longer being <em>reasonable</em>, then you might have gotten back out of the realm of business problems where mathematically-proven software engineering can really help you much.</p>

<ul>
  <li>Luckily, smart people at the USAF tend to consider it unreasonable to assume aws-1-east availability at 8 G-forces.</li>
  <li>Similarly, gosh darnit, please stop putting the Bluetooth audio on the CAM bus in a car so that it could be a little more rasonable to assume something like “freedom from signals interference.”  🤷‍♀️</li>
</ul>

<p>Formal methods provide you some guarantees that the system will meet its specifications.  Whether those were the right requirements is another question.</p>

<p>Formal methods, like test case authoring, can only validate things you modeled in the first place.  If you forgot to model a cosmic ray flipping a bit in the fighter plane’s chip, then, well, that could be a problem.</p>

<p>A Raspberry Pi overheating would be a violation of a “the hardware works” assumption.  That said, “the hardware works” is often pretty reasonable to assume in a military software engineering formal methods proof, because the electrical engineers in charge of the chip can typically be trusted to have done <em>their</em> hardware verification formal methods homework.</p>

<p>Generally, yes, it’s okay to make assumptions about phenomena that are nondeterministic in the real world <em>(though they lend themselves particularly well to deterministic variables)</em> – just make sure it’s <strong>reasonable</strong> to do so.  Yes to your USAF electrical engineers who also did FM.  Not so much to aws-east-1.</p>

<p>Satellites are very difficult to patch, so formal methods proofs are pretty great for their embedded software, too.</p>

<p>By design, SEL4 isn’t POSIX, and lacks <code class="language-plaintext highlighter-rouge">sleep()</code>, <code class="language-plaintext highlighter-rouge">malloc</code>, etc.  75% of a 35-million-LoC Linux kernel is probably device drivers.  Whereas the SEL4 microkernel has about 10,000 lines of code and 900,000 lines of proofs <em>(spec probably about 1% that size?)</em>.</p>

<p>Generally, “protected procedure calls” are meant for synchronous communications between OS protection domains.  <em>(OS “notifications” are more for asynchronous communications.)</em></p>

<p>He showed sample code which, according to my notes, maps out which OS protection domains get access to which memory and with what kind of access.”  Whooof, it’s been a while since I read my Tannenbaum and assembly language memory allocation and whatnot books!  Fun trip down memory lane, though.</p>

<p>Hardware industry changes might bring that $1k/LOC cost down, which would be cool, though sadly it might still be a while.  Price is when we’ll start to see “proven” chips end up in coffee makers, not just fighter jets.</p>

<p>I wonder if the “formally proven” software library supply chain is nonetheless having similar worm problems to the rest of the open-source software library supply chain.  Because, again, phishing isn’t about whether the code <em>was</em> bad when its legitimate author wrote it – it’s about someone bad <em>changing</em> it to <em>become</em> bad.</p>

<p>Speaker says:  probably suffers the same risk, though when it comes to source code edits, it’s a heck of a lot easier to notice something amiss in SEL4’s 10,000 lines of code than in Linux’s 35 million.  And $1,000/LOC with tight assumptions and the desire to minimize the “trusted computing base” tends to lead to rather small codebases.</p>

<h2 id="todo-o11ysummit">TODO o11ysummit</h2>

<p>Finished the Open Source Summit notes; phew!</p>

<p>TODO:  Observability Summit.</p>

<h2 id="i-love-being-a-polymath">I love being a polymath</h2>

<p>In my own talk about tiny repos, I said my blog hosting choices were largely influenced by my desire to grow as a frontend web developer.  Heck, I almost went to a screen-reader talk <em>(couldn’t make it, notified a friend and hoped they did instead)</em>.</p>

<p>But then I also sat through talks about doing advanced math as part of programming against operating systems and thinking about how GPUs vs. CPUs are designed at a hardware level.</p>

<p>I dearly love being a Renaissance Woman / Jill of all trades / polymath.  Gorging myself at a full buffet of knowledge is such incredible <em><strong>fun</strong></em>.</p>

<h2 id="kubernetes-is-for-bursts-and-sprawls">Kubernetes is for bursts and sprawls</h2>

<p>A hyperscaler PaaS like AWS Elastic Beanstalk / Azure App Service / GCP App Engine, or a simple VM, is probably the easiest to operate and understand if you don’t need orchestration, and there are a lot of web applications / services that don’t tend to need orchestration.</p>

<p>Services with non-bursty traffic and low service level agreements <em>(SLAs)</em> are a great example of apps that are probably fine just using a hyperscaler PaaS, and if something goes wrong, you take an outage and you deploy it onto another instance of that PaaS.  🤷‍♀️</p>

<p><em>(That said, sometimes even non-bursty apps – particularly commercial-off-the-shelf (“CotS”) sprawling multi-server/service apps from vendors – are having their inter-service connections orchestrated via container orchestration, these days, so that they don’t have to roll their own service mesh.  So sometimes you don’t choose that you need Kubernetes; the vendor chooses for you.)</em></p>

<h2 id="switch-to-npm-ci-and-set-minimum-age">Switch to npm ci and set minimum age</h2>

<p>Over the weekend, following up, two things I learned are:</p>

<ol>
  <li>Right away, switch from using <code class="language-plaintext highlighter-rouge">npm i</code> to <code class="language-plaintext highlighter-rouge">npm ci</code>.</li>
  <li>Right away, append the <code class="language-plaintext highlighter-rouge">--min-release-age</code> flag to your calls to <code class="language-plaintext highlighter-rouge">npm i</code> / <code class="language-plaintext highlighter-rouge">npm ci</code> <em>(or put the flag straight into your <code class="language-plaintext highlighter-rouge">.npmrc</code> files)</em> with a minimum age of at least 2-3 days, to work that age-old IT “great idea; you go first” adage into dependencies.
    <ul>
      <li>Set your Dependabot settings, if you use it, to also minimum-age.</li>
    </ul>
  </li>
</ol>

<h2 id="machine-identities">Machine identities</h2>

<p>I ran into a friend who did a lot of work on <a href="https://spiffe.io/" target="_blank">SPIFFE</a>, and suddenly it hit me that while I take <a href="https://katiekodes.com/entra-azure-system-assigned-managed-identity/" target="_blank">Azure System-Assigned Managed Identities’</a> existence for granted, I shouldn’t.  They came out in late 2017, but the SPIFFE proposal was in May 2016, so, like, lots of people were working on the concept of “give every machine its own identity” authentication <em>(“authN”)</em> principle that today I treat as table stakes while I <a href="https://katiekodes.com/securing-authenticated-ai/" target="_blank">gripe about authorization <em>(“authZ”)</em> issues in the LLM generative AI agent/MCP era</a>.</p>

<h2 id="scrappy-sha1-hulud-cleanup">Scrappy Sha1-Hulud cleanup</h2>

<p>Hallway aside:  I remembered one of my friends helps secure a large company, and I asked how they’re dealing with digging around for compromised supply chain packages in places where they might not’ve even thought to look.  <em>(e.g. if you have a Java developer working on an AWS EC2 VM running AWS’s Linux … surprise, it’s also got Python libraries on it that might be vulnerable if major Python libraries were hacked, even though the Java developer who maintains it had no idea they were supposed to look for Python vulnerabilities on their machine and wouldn’t know what part of the machine to look on anyway because they didn’t put them there!)</em></p>

<p>Money.  The answer is money.</p>

<p>My friend’s company has gobs and gobs of money, and they can afford to pay top-tier sysadmins who know a <em><strong>lot</strong></em> about infosec blue-teaming and keep abreast of what all the supply chain hackers are up to whatever they want.  So they just lend out said sysadmins to said VM owners and tell them to inspect every last VM, if that’s what it seems like it’d take.</p>

<p>They’re simply not in short supply of extremely knowledgeable headcount, so they threat-hunt the toilsome way as needed because they can afford to.  🤷‍♀️</p>

<p>However, I stopped by the OpenSSF booth, too, and they said that for things on a budget:</p>

<ol>
  <li>Yes, their Guac project seems like a decent place to put your SBOMs.  I believe … so that you can query whether you’re impacted by various CVEs.</li>
  <li>Become a regular reader of the OpenSSF’s <a href="https://best.openssf.org/" target="_blank">best practices guidance</a>.</li>
  <li>Keep an eye on future developments in Intel’s OpenSSF contribution, <a href="https://github.com/ossf/cve-bin-tool" target="_blank">cve-bin-tool</a>.</li>
  <li>Keep an eye on future developments in the U.S. government’s Defense Advanced Research Projects Agency’s <em>(DARPA’s)</em> <a href="https://www.darpa.mil/research/programs/enhanced-sbom-for-optimized-software-sustainment" target="_blank">Enhanced SBOM for Optimized Software Sustainment</a> (EBOSS) program.  Hopefully, it’ll one day release some open-source tools that can, on a shoestring, help you get some benefits as if you, too, had more of those “gobs of money sysadmins” on staff.</li>
</ol>

<h2 id="sha1-hulud-has-me-stressed-out">Sha1-Hulud has me stressed out</h2>

<p>As I took a break from trying to figure out how to help about supply chain worms, I ended up doomscrolling and seeing open letters authored by strangers in the UK about the terrible regressions in civil rights and liberties going on over there <em>(particularly aimed at harming transgender people extremely intensely, but FWIW, I only get to get paid for my computer knowledge while wearing non-foot-destroying shoes because of loosened standards since the 1990s about what’s “woman enough;” clearly, harsh gender rules hurt us all)</em>.</p>

<p>As I wondered just how soon I’ll next have to try to figure out how to help under the intensity of local violence emergency, like I <a href="https://katiekodes.com/ice-detain-plan/" target="_blank">felt helpless in the face of in Minnesota this winter</a>, I realized that my anger at the people behind supply chain worms is <em>personal</em>.  I need <em><strong>rest</strong></em> between emergencies.  Clearly, outside of work, there are plenty more coming.</p>

<p>I feel resentful that supply chain attackers are putting me back into “<strong>I feel so helpless, because this emergency is too huge, but I can’t relax, because surely someone like me is needed as a helper, also because this emergency is so huge</strong>” mode <em>through work</em> when I can clearly see that I should be resting up because that emotional crisis-state is surely on its way back into my personal life soon.</p>

<p>Like open-source software maintainers, <em><strong>I’m tired</strong></em>, and now is <em><strong>not a good time</strong></em>.</p>

<ul>
  <li><em>(As Linus said to a slightly different audience … ugh … don’t be an ego about discovering how to make someone else miserable!)</em></li>
</ul>

<p>I’d <em>thought</em> I was just obsessing about researching software supply chain defense every evening and all weekend, this week, because it was interesting.  But in this epiphany, it occurred to me, that that’s not quite what it is.  I’m <em>too</em> attached to it in a way that isn’t just <em>interest</em>-based hyperfixation.  This is <em>stress</em>-based hyperfixation.</p>

<p>I managed to get out for a walk in the woods within an hour of having this epiphany, so that was good, but still, I was already planning to go for walks in the woods all summer anyway.  So, like, that doesn’t lessen my resentment.  My walks this summer were supposed to be “catch-up” restorative in <em>general</em>, not trying to do real-time double-duty in the <em>specific</em> already as well.</p>

<h2 id="supply-chain-worms-seem-like-a-march-2020-moment">Supply chain worms seem like a March 2020 moment</h2>

<p>You know how the COVID-19 pandemic’s March 2020 overnight shift to fully-remote work instantly accelerated “might be nice” enterprise IT transformations like adopting “continuous identity verification” and endpoint/mobile device management that didn’t require coming onto campus to complete?</p>

<p>Sadly, I fear this whole <a href="https://cyberscoop.com/cisa-chief-frets-about-open-source-vulnerabilities-delayed-security-improvements/" target="_blank">package-registry-native supply chain worm</a> problem is another such “we’re all gonna be treading water” crisis of overwork.  <em>(Which, like, will lead to clearing a backlog, but maybe not in a particularly humane way of getting there, and isn’t the world already hard enough?)</em></p>

<ul>
  <li>I think that “observability” for endpoints and for applications/services is going to urgently need to mean not merely o11y of its <strong>runtime</strong>, but also of commit/build/deploy <em>(sdlc/supply-chain)</em>-time events.
    <ul>
      <li>As Andrew Nesbitt blogged about Sigstore:  “<a href="https://nesbitt.io/2026/05/25/github-actions-security-in-python-packages.html" target="_blank">Where the signing did help in those cases was in working out what had happened, fast and with certainty.</a>.”</li>
      <li>I don’t think it’s reasonable to try to shift, overnight, from letting your horses get out of the barn.  You could grind your business to a halt trying to only allow-list, say, 10 open-source transitive dependencies for your entire enterprise.  It’s simply not going to work.</li>
      <li>But much like sometimes Crowdstrike scans for malware but can’t always keep it from getting onto a system in the first place but at least makes remediation fast, we can set up a LIDAR on the door of the barn and <em>count</em> the horses that escaped.  I think enterprises can, with a tiring-but-achievable amount of toil, get everyone writing SBOMs pronto and whatnot, so that it’s easier, each time major news breaks about yet another worm, to decide <em>whether</em> you were impacted.</li>
      <li>And you can put more things in the way of the barn door, so the horses get out slower – e.g. “sounds cool; you go first” “minimum age” requirements of 2-7 days on software library dependency imports.</li>
    </ul>
  </li>
  <li>Oh, lordy – I said this to a colleague and they pointed out that even individual <em>homes</em> might start to need unreasonably toilsome levels of digital security to safely connect to the internet at all.  Yeesh, can we have a <em>little</em> break before it gets <em>that</em> bad?  I sure hope so.  Particularly because I’d hate to see <a href="https://www.youtube.com/watch?v=HUEvRyemKSg" target="_blank">general computation</a> get further shock-doctrine eroded.  😬</li>
  <li>I think it’s gonna take enterprises a few years, partly because <a href="https://opensourcesecurity.io/2026/2026-04-ecosystems-andrew/" target="_blank">the remediation surface is still so complex</a>.  <em>(So do that “minimum age” stuff and get your SBOM house in order now, I guess, and hope that even better tools come out for making it easier to scan all those mystery EC2 VM Boto3 Python installations later, I suppose.  Defense in depth is Swiss cheese, and I don’t know if you’re going to get all of your cheese layers stacked to be hole-free right away, but get started nonetheless.)</em></li>
</ul>

<h2 id="hello-microsoft">Hello Microsoft</h2>

<p>I <a href="https://katiekodes.com/lf-26-ms/" target="_blank">left you a wishlist</a> recapping what I dream-dumped at your booth.</p>

<h2 id="more-later">More later</h2>

<p>All right, out of time, gotta get outside.  Keep reloading through next week until I get everything added in from paper notes.</p>]]></content><author><name>Katie</name></author><category term="professional development" /><summary type="html"><![CDATA[#OSSHomework - practicing what I preach]]></summary></entry><entry xml:lang="en"><title type="html">Microsoft wishlist</title><link href="https://katiekodes.com/lf-26-ms/" rel="alternate" type="text/html" title="Microsoft wishlist" /><published>2026-05-18T14:00:00+00:00</published><updated>2026-05-18T14:00:00+00:00</updated><id>https://katiekodes.com/lf-26-ms</id><content type="html" xml:base="https://katiekodes.com/lf-26-ms/"><![CDATA[<p>Hi, Microsoft!  Here’s that wishlist I approached you about toward the end of the day at the Linux Foundation’s Open Source Summit:</p>

<h2 id="1---jit-authz">1 - JIT AuthZ</h2>

<p>Entra-native / access-control-platform-native <em>(e.g. Azure-RBAC-native / Entra-App-Role-native)</em> “just-in-time authZ elevation” / “PIM” / “eligible, but not active unless there is proof of fresh human intent/approval and only active for a limited timespan” authorization <em>(authZ)</em> for <em><strong>workload identities</strong></em>.</p>

<p>We’ve already got machine-gets-stuck-until-human-approves flows with Azure Pipelines deployment approval checks and GitHub Actions environment approvals.</p>

<p>Let’s make things where Entra service principals are <em><strong>eligible</strong></em> for certain privileged access control grants, but has to wait to move forward because it only <em><strong>active</strong></em> after the machine requests escalation if one of a designated Entra group of humans personally <em><strong>approves</strong></em> it.</p>

<ul>
  <li>I’ve wanted this even back when machines were all deterministic.
    <ul>
      <li><em>(Again, we already have an implementation in ADO and GH CI/CD; we just didn’t have it more generally/natively for all Entra-attached authZ platforms)</em>.</li>
    </ul>
  </li>
  <li>But now I <em><strong>really</strong></em> want it in the era of <em><strong>nondeterministic</strong></em> machines running around doing things.</li>
</ul>

<p>See my blog post “<a href="https://katiekodes.com/securing-authenticated-ai/" target="_blank">Securing authenticated agentic AI</a>.”</p>

<ul>
  <li><em>(Say, what was that standards organization you suggested I get involved with?  I-something-something-F, maybe?)</em></li>
</ul>

<p>Update, 6/29/2026:  see also my new post, “<a href="https://katiekodes.com/m365-agent-registry-needs-tools/" target="_blank">Microsoft 365’s Agent Registry should list tools</a>.”  More o11y than prevention, but also important, and kinda related.</p>

<h2 id="2---cdevents">2 - CDEvents</h2>

<p>Please jump with both feet into the <a href="https://cdevents.dev/" target="_blank">CDEvents protocol</a> pool.</p>

<p>Please make both GitHub and Azure DevOps natively publish events and natively subscribe to / consume events.</p>

<p>CDEvents is as impactful as OpenTelemetry!  <em>(Which Azure Monitor invested in becoming capable of consuming, and Azure Application Insights invested in becoming capable of producing.)</em></p>

<p>Particularly because CDEvents can be used <em><strong>as</strong></em> a form of infosec-critical observability, e.g. to centrally monitor whether every CI pipeline run is also accompanied by a corresponding SBOM generation run, etc.  In the post-Sha1-Hulud era, enterprises need CDEvents publication <em><strong>yesterday</strong></em> out of our hyperscaler-owned CI/CD platforms.</p>

<ul>
  <li><em>(Making GH/ADO able to subscribe to / consume CDEvents is probably less urgent than making them able to publish / produce CDEvents, as a question of security.  Even if I also think subscribe/consume nonetheless seems important as a question of developer experience.)</em></li>
</ul>

<h2 id="3---provenance">3 - Provenance</h2>

<p>GitHub, I loved your <a href="https://github.blog/changelog/2026-05-05-code-to-cloud-risk-visibility-with-microsoft-defender-for-cloud-is-now-generally-available/" target="_blank">“Code-to-cloud risk visibility with Microsoft Defender for Cloud is now generally available” blog post</a>, but I was heartbroken it only applies to containerization.</p>

<p>Azure App Service team, can you please partner with the Defender team and the GitHub team <em>(and Azure DevOps team, for that matter!)</em> to find a way to provide the same type of attestation/provenance party tricks when simply running an <code class="language-plaintext highlighter-rouge">npm run build</code> CI/CD build step followed by an <code class="language-plaintext highlighter-rouge">azure/webapps-deploy</code> CI/CD deploy step?</p>

<p>Easy-button “Buy” application developers deserve provenance just as much as hard-mode “Build” <em>(container-trained)</em> application developers!  🥰</p>

<p>I know that <code class="language-plaintext highlighter-rouge">azure/webapps-deploy</code> is just making a <code class="language-plaintext highlighter-rouge">.zip</code> file and throwing it over the fence at Azure App Service over HTTPS, which isn’t inherently as “hashed” as container-building is, and that Kudu potentially lets Azure App Service owners introduce drift even after that, but …</p>

<p>Could you find a way somehow, maybe, at least for the happy path?</p>

<p>I really like the idea of it being obvious that:</p>

<ol>
  <li>“this Azure App Service resource GUID’s contents were last built from this Git commit SHA” and, in the other direction,</li>
  <li>“this Git commit SHA was deployed into this Azure App Service resource GUID.”</li>
</ol>

<p>Thanks so much!</p>]]></content><author><name>Katie</name></author><category term="professional development" /><summary type="html"><![CDATA[From the Linux Foundation]]></summary></entry><entry xml:lang="en"><title type="html">Observability Summit 2026 conference talk</title><link href="https://katiekodes.com/o11ysummit-2026/" rel="alternate" type="text/html" title="Observability Summit 2026 conference talk" /><published>2026-05-17T12:00:00+00:00</published><updated>2026-05-17T12:00:00+00:00</updated><id>https://katiekodes.com/o11ysummit-2026</id><content type="html" xml:base="https://katiekodes.com/o11ysummit-2026/"><![CDATA[<p>I presented <a href="https://sched.co/2HJVx" target="_blank">“Secure by Design: Rethinking Test Credentials for Synthetic Monitoring”</a> at the Cloud Native Computing Foundation’s <em>(“CNCF”)</em> 2026 Observability Summit <em>(“#O11ySummit”)</em>.</p>

<!--more-->

<h2 id="video">Video</h2>

<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/tHBH4pkcUz8" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; fullscreen; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>

<h2 id="slides">Slides</h2>

<p><a href="https://katiekodes.com/files/O11ySummit20260521.pdf" target="_blank">Click Here to download a PDF of the slides</a></p>]]></content><author><name>Katie</name></author><category term="web development" /><category term="security" /><category term="iam" /><summary type="html"><![CDATA[Announcement (later will hold slides, links, etc.)]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://katiekodes.com/images/screenshots/screenshot-o11ysummit-sched-2026.png" /><media:content medium="image" url="https://katiekodes.com/images/screenshots/screenshot-o11ysummit-sched-2026.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Open Source Summit 2026 conference talk</title><link href="https://katiekodes.com/opensourcesummit-2026/" rel="alternate" type="text/html" title="Open Source Summit 2026 conference talk" /><published>2026-05-17T11:00:00+00:00</published><updated>2026-05-17T11:00:00+00:00</updated><id>https://katiekodes.com/opensourcesummit-2026</id><content type="html" xml:base="https://katiekodes.com/opensourcesummit-2026/"><![CDATA[<p>I presented <a href="https://sched.co/2LSqs" target="_blank">“Tiny Repos, Big Impact: Level Up Through Open-Source Teaching”</a> at the Linux Foundation’s 2026 Open Source Summit <em>(“#OSSummit”)</em>.</p>

<!--more-->

<h2 id="video">Video</h2>

<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/uz0rkr67868" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; fullscreen; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>

<h2 id="slides">Slides</h2>

<p><a href="https://katiekodes.com/files/OSSummit20260519.pdf" target="_blank">Click Here to download a PDF of the slides</a></p>

<h2 id="other-talk">Other talk</h2>

<p>Come see me again on Thursday afternoon at the <a href="https://katiekodes.com/o11ysummit-2026/" target="_blank">Observability Summit</a>.</p>

<h2 id="my-homework">My homework</h2>

<p>Here is my <a href="https://katiekodes.com/lf-summit-recaps-2026/" target="_blank">conference recap</a> <em>(<code class="language-plaintext highlighter-rouge">#OSSHomework</code> assignment number 1)</em>; still a work in progress.</p>

<h2 id="related-links">Related links</h2>

<p>7/20/26 update:  I laughed uncontrollably this morning when I saw Andrew Nesbitt’s satirical blog post “<a href="https://nesbitt.io/2026/07/10/package-management-as-org-chart.html" target="_blank">Package Management as Org Chart</a>.”  If you watched my talk’s video, you saw me ponder whether it was really ethical anymore that my tiny teaching repos avoid dependency manager lockfiles and import packages as <code class="language-plaintext highlighter-rouge">latest</code> <em>(which I started as a way of reducing distracting lines of code from the point each repo was actually trying to make)</em>, in this era of open-source software supply chain worms.  Yes, I tend to commit straight to <code class="language-plaintext highlighter-rouge">main</code> on my teaching repos – I feel very called out!  😉😆</p>

<blockquote>
  <ul>
    <li>“<strong>No lockfile, <code class="language-plaintext highlighter-rouge">latest</code> everywhere:</strong> each install resolves fresh against the registry, and the dependency set is whatever’s newest at that moment. The founder still commits to <code class="language-plaintext highlighter-rouge">main</code>, had a bad experience with <code class="language-plaintext highlighter-rouge">npm-shrinkwrap.json</code> years ago, and won’t touch a lockfile.”</li>
  </ul>
</blockquote>]]></content><author><name>Katie</name></author><category term="professional development" /><summary type="html"><![CDATA[Announcement (later will hold slides, links, etc.)]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://katiekodes.com/images/screenshots/screenshot-ossummit-sched-2026.png" /><media:content medium="image" url="https://katiekodes.com/images/screenshots/screenshot-ossummit-sched-2026.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">How to switch Visual Studio license assignment from individuals to groups</title><link href="https://katiekodes.com/group-vs-licensure/" rel="alternate" type="text/html" title="How to switch Visual Studio license assignment from individuals to groups" /><published>2026-05-13T15:00:00+00:00</published><updated>2026-05-13T15:00:00+00:00</updated><id>https://katiekodes.com/group-vs-licensure</id><content type="html" xml:base="https://katiekodes.com/group-vs-licensure/"><![CDATA[<p>So – you’ve been dutifully opening the <a href="https://manage.visualstudio.com">Visual Studio Subscriptions Admin Portal</a>, adding individual users, removing them when they leave, and generally keeping the whole thing running?  Yay – very happy it works.  But there’s a slightly more enterprise-friendly way to <a href="https://learn.microsoft.com/en-us/visualstudio/subscriptions/assign-license-bulk#use-microsoft-entra-groups-to-assign-subscriptions" target="_blank">assign Visual Studio licenses using Entra  security groups</a>, if your identity provider is Microsoft Entra ID <em>(formerly known as Azure Active Directory)</em>.</p>

<p>After one afternoon of initial setup, your day-to-day job switches from “add or remove someone in the Visual Studio admin portal” to “add or remove an Entra group member.”</p>

<h2 id="whats-in-it-for-you">What’s in it for you</h2>

<h3 id="managing-licenses">Managing licenses</h3>

<p>This might not seem like a sea change, but the nifty thing is that it’s likely your enterprise IT department already has some pretty mature bread-and-butter processes for adding and removing Entra group members in response to business-level requests <em>(e.g. through the helpdesk ticketing system, or automatically removing group members whom HR systems report are no longer employees of the enterprise at all)</em>.</p>

<p>So you might be able to get out of the manual grant-and-revoke business altogether.</p>

<h3 id="reporting-licenses">Reporting licenses</h3>

<p>Also, if the Finance department ever wants more confidence that Microsoft is granting entitlements <em>(such as Azure DevOps licensure or GitHub Enterprise Cloud licensure)</em> appropriately according to Visual Studio license level, the Finance department won’t have to wait on you personally to export a list of Visual Studio license levels from the Visual Studio admin portal.</p>

<p>Instead, any old staff member with access to see which employee is a member of which Entra security group <em>(which is often everyone at a company)</em> could pull that report of “who’s got which Visual Studio license level,” as long as they know the names of the relevant Entra security groups.</p>

<hr />

<h2 id="step-1---group-creation">Step 1 - group creation</h2>

<p>First, figure out the number of Entra security groups that makes sense for your enterprise to create.  The most common approach is one group per Visual Studio subscription level – for example, two Entra groups named:</p>

<ol>
  <li><strong>Licensed Visual Studio Enterprise Subscribers</strong></li>
  <li><strong>Licensed Visual Studio Professional Subscribers</strong></li>
</ol>

<p>For each Entra security group you need created, you’ll need to provide your Entra administrator <em>(or whoever handles group creation in your org; there’s probably a helpdesk ticket type for it)</em> with the following details:</p>

<table>
  <thead>
    <tr>
      <th>Field</th>
      <th>Example</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Name</strong></td>
      <td><code class="language-plaintext highlighter-rouge">Licensed Visual Studio Enterprise Subscribers</code></td>
    </tr>
    <tr>
      <td><strong>Description</strong></td>
      <td><code class="language-plaintext highlighter-rouge">All members of this group have been assigned a Visual Studio Enterprise subscription via the VS Subscriptions Admin Portal.</code></td>
    </tr>
    <tr>
      <td><strong>Owners</strong></td>
      <td>You and some backups <em>(note:  an “owner” of an Entra security group can in turn be another Entra security group, if that makes it easier to add your whole department in one fell swoop)</em></td>
    </tr>
    <tr>
      <td><strong>Starting members</strong></td>
      <td>The list of people who currently have that license level <em>(note:  as of the time of this writing, each “member” of this Entra security group must be a direct human, and cannot be another Entra security group – Entra wouldn’t complain about nested groups, but Visual Studio would ignore indirect group membership)</em></td>
    </tr>
  </tbody>
</table>

<p>That’s it.  Submit that request and wait for confirmation that the groups exist <em>(and, hopefully, are populated with the correct starting members, so you don’t have to do it – but if they leave the membership list empty, read on and add everyone using the usual processes you’ll use as additional people request licensure over time)</em>.</p>

<hr />

<h2 id="step-2---reassign-visual-studio-licenses-from-individuals-to-groups">Step 2 - Reassign Visual Studio licenses from individuals to groups</h2>

<p>Once your new Entra security groups exist, <a href="https://learn.microsoft.com/en-us/visualstudio/subscriptions/assign-license-bulk#use-microsoft-entra-groups-to-assign-subscriptions" target="_blank">follow Microsoft’s instructions assign Visual Studio licenses to those groups</a>.  As a recap, it’s more or less these steps:</p>

<ol>
  <li>Go to <a href="https://manage.visualstudio.com">https://manage.visualstudio.com</a> and sign in.</li>
  <li>Navigate to the <strong>Manage Subscribers</strong> tab.</li>
  <li>Click <strong>Add</strong>, then choose <strong>Microsoft Entra group</strong> from the dropdown.</li>
  <li>Type the name of your group in the search field and select it when it appears. You’ll get a preview of the members before committing.</li>
  <li>Choose the appropriate <strong>subscription level</strong>, set download rights and communication preferences as desired.</li>
  <li>Click <strong>Add</strong>, then <strong>Confirm</strong>.</li>
</ol>

<p>Repeat for each group.</p>

<p>That’s the entire one-time setup.</p>

<h3 id="existing-individual-assignments-are-self-cleaning">Existing individual assignments are self-cleaning</h3>

<p>Good news about existing individual assignments:  <a href="https://learn.microsoft.com/en-us/visualstudio/subscriptions/assign-license-bulk#use-microsoft-entra-groups-to-assign-subscriptions" target="_blank">according to Microsoft docs at the time of this writing</a>, If someone already has an individual license assignment in the Visual Studio, but they’re also in an Entra security group that has that same license level assigned, the Visual Studio portal is smart about it.  They get absorbed into the group assignment and the Visual Studio portal un-lists their individual assignment.  Yay for not needing to manually clean up every old individual assignment!</p>

<hr />

<h2 id="step-3---verify-it-worked">Step 3 - verify it worked</h2>

<p>Scroll to the bottom of your subscriber list and you’ll see your groups listed.  Click <strong>View subscribers</strong> on a group to confirm the right people are showing up.  Email a few of those individuals and ask them to spot-check that a few of those individuals can still access their Visual Studio benefits; they should see no interruption.</p>

<hr />

<h2 id="step-4---continue-onboarding-and-offboarding">Step 4 - continue onboarding and offboarding</h2>

<p>This is where your day-to-day process changes.  You probably won’t end up in the Visual Studio administrative portal anymore, day-to-day.</p>

<p>Instead, going forward:</p>

<ul>
  <li><strong>Someone needs a Visual Studio license?</strong> Add them to the appropriate Entra group.</li>
  <li><strong>Someone leaves or no longer needs the license?</strong> Remove them from the Entra group.</li>
  <li><strong>Someone leaves the organization entirely?</strong> When their Entra account is disabled or removed, their license is revoked automatically — you don’t have to do anything.</li>
</ul>

<hr />

<h2 id="a-few-things-to-know">A Few Things to Know</h2>

<ul>
  <li><strong>Group-based assignment requires a trusted agreement type</strong> (Enterprise Commercial, Education, US Government, Campus, Select 6, or Select Plus). MPSA agreements aren’t supported.</li>
  <li><strong>An Entra group can only be assigned one VS subscription level at a time.</strong> If you have a mix of Enterprise and Professional users, use separate Entra groups.</li>
  <li><strong>You can’t edit individual subscriber details for group members</strong> <em>(like their communications preferences or whether they have license key access)</em> through the Visual Studio portal.  If someone needs a one-off customization, have a new Entra Security Group created that they’re the only member of, and use the Visual Studio portal to set the new Entra Security Group’s permissions accordingly.</li>
  <li><strong>Separate notification email addresses aren’t supported</strong> for group-managed subscriptions. Notifications go to the user’s primary Entra email (their UPN).</li>
</ul>

<hr />

<h2 id="summary">Summary</h2>

<p>Here’s the old process:</p>

<table>
  <thead>
    <tr>
      <th>Cadence</th>
      <th>What Happens</th>
      <th>Who Does It</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Ongoing</strong></td>
      <td>Add/remove people from the <strong>Visual Studio admin portal</strong> as needed</td>
      <td>You or fellow VS portal admins</td>
    </tr>
  </tbody>
</table>

<p>And here’s the transition <em>(new process in the last line)</em>:</p>

<table>
  <thead>
    <tr>
      <th>Transition Phase</th>
      <th>What Happens</th>
      <th>Who Does It</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Planning</td>
      <td>Identify groups needed, compile member lists</td>
      <td>You (one time)</td>
    </tr>
    <tr>
      <td>Group creation</td>
      <td>Request Entra groups with name, description, owners, members</td>
      <td>Entra admin, as requested by you (one time)</td>
    </tr>
    <tr>
      <td>Portal setup</td>
      <td>Add each Entra group to the Admin Portal with subscription level</td>
      <td>You (one time)</td>
    </tr>
    <tr>
      <td>Verify</td>
      <td>Confirm members show up and licenses are active</td>
      <td>You (one time)</td>
    </tr>
    <tr>
      <td><strong>Ongoing</strong></td>
      <td>Add/remove people from the <strong>Entra group</strong> as needed</td>
      <td>You or fellow group owners, or maybe even central IT for you</td>
    </tr>
  </tbody>
</table>

<p>The whole transition should only be a few minutes/hours of hands-on work.  Most of the delay will involve waiting on the Entra security group creation request to be fulfilled by your central IT team.</p>

<p>After that, managing Visual Studio licenses stops being a portal task and becomes a simple Entra security group membership management task – one that, if you’re really lucky, can be automated by colleagues who automate Entra security group membership every day.</p>

<hr />

<h2 id="disclosure">Disclosure</h2>

<p>This post was <em><strong>heavily</strong></em> LLM-generated, with just a bit of editing, sorry, friends!  It seemed useful enough to just “git ‘er done” on a busy day and delegate to the writing-machine.</p>]]></content><author><name>Katie</name></author><category term="architecture" /><category term="tutorials" /><category term="iam" /><summary type="html"><![CDATA[It seems pretty easy]]></summary></entry></feed>