<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Lab — IamLucif3r</title>
    <link>https://anmolsinghyadav.com/lab/</link>
    <atom:link href="https://anmolsinghyadav.com/lab/feed.xml" rel="self" type="application/rss+xml" />
    <description>After hours: LLM guardrails I want to understand by breaking, tools I built because I needed them, CTF boxes, and notes to future me.</description>
    <language>en</language>
    <lastBuildDate>Tue, 28 Jul 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>Sandboxing an LLM agent — what &quot;allow-list&quot; actually means at runtime</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-07-28-llm-agent-allowlist-runtime/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-07-28-llm-agent-allowlist-runtime/</guid>
      <pubDate>Tue, 28 Jul 2026 00:00:00 GMT</pubDate>
      <category>AI Security</category>
      <description>The prompt says the agent can only touch three tools. The runtime has no idea the prompt exists.</description>
      <content:encoded><![CDATA[<p>Every agent framework ships a config that reads like a security control: <code>allowed_tools: [read_file, search, send_email]</code>. It looks like an allow-list. It is not one — it&#39;s a suggestion, enforced by whether the model feels like following it that day.</p>
<h2>Where the gap actually is</h2>
<ul>
<li>The allow-list lives in the prompt or the framework&#39;s Python layer, not in the process boundary.</li>
<li>If the agent can shell out, read arbitrary paths, or hit an unrestricted network, the &quot;allow-list&quot; is cosmetic the moment a clever prompt (or a poisoned tool response) convinces the model to ignore it.</li>
<li>Logging what the agent <em>said</em> it did is not the same as logging what the <em>process</em> did.</li>
</ul>
<h2>What I&#39;m actually testing</h2>
<p>Wrapping agent execution in the same primitives I&#39;d use for any untrusted workload: a restricted filesystem view, an explicit egress allow-list enforced at the network layer (not the prompt layer), and syscall-level tracing so &quot;the agent read <code>/etc/passwd</code>&quot; shows up regardless of what the transcript claims happened.</p>
<p>Early read: the honest allow-list is enforced by the kernel, not the system prompt. Everything else is a nice comment.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Kata Containers, or giving every workload its own tiny hypervisor</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-07-25-kata-microvm-isolation/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-07-25-kata-microvm-isolation/</guid>
      <pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate>
      <category>Cloud &amp; Containers</category>
      <description>Notes on trading a shared kernel for a microVM per container — what it buys you, and what it costs at 2am.</description>
      <content:encoded><![CDATA[<p>The pitch for Kata is simple: stop trusting the shared host kernel and give every container its own lightweight VM instead. The container escape stops being &quot;find one syscall bug&quot; and becomes &quot;find one hypervisor bug,&quot; which is a much better problem to have.</p>
<h2>What actually changes</h2>
<ul>
<li>The workload still looks like a container from the outside — same OCI image, same orchestrator hooks.</li>
<li>Underneath, <code>containerd</code> hands it to a shim that boots a stripped-down VM (Firecracker, QEMU, or cloud-hypervisor) with its own kernel.</li>
<li>Syscalls a compromised process makes now hit a kernel nobody else&#39;s workload shares.</li>
</ul>
<h2>What it costs</h2>
<p>Nothing is free. Boot time goes up, memory overhead goes up, and anything that assumed &quot;container == process on the host&quot; (some observability agents, some debugging habits) needs re-checking. The isolation is real, but so is the tax.</p>
<blockquote>
<p>The honest sell isn&#39;t &quot;Kata makes you unhackable.&quot; It&#39;s &quot;Kata moves the blast radius of the bugs you haven&#39;t found yet.&quot;</p>
</blockquote>
<p>Still validating where the overhead is worth it versus where a well-configured seccomp + AppArmor profile gets you 80% of the benefit for free.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Container clocks drift more than the host admits</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-07-14-container-clocks/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-07-14-container-clocks/</guid>
      <pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate>
      <category>Infrastructure</category>
      <description>CLOCK_MONOTONIC inside a paused-then-resumed container skips in a way that a naive rate limiter reads as a burst. Could be a bypass primitive, could be nothing. Need a clean repro before I believe myself.</description>
      <content:encoded><![CDATA[<p><code>CLOCK_MONOTONIC</code> inside a paused-then-resumed container skips in a way that a naive rate limiter reads as a burst. Could be a bypass primitive, could be nothing. Need a clean repro before I believe myself.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A box that took four hours longer than it should have</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-07-02-the-boring-enumeration-lesson/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-07-02-the-boring-enumeration-lesson/</guid>
      <pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate>
      <category>Offensive Security</category>
      <description>A TryHackMe-style teardown of a foothold I should have found in twenty minutes, and didn't.</description>
      <content:encoded><![CDATA[<p>In the spirit of documenting dead ends honestly: this one was supposed to be quick. A web app, a login form, and — I assumed — the usual suspects. It was not the usual suspects.</p>
<h2>The wrong turns, in order</h2>
<ol>
<li>Tried the obvious SQLi payloads on the login form. Nothing. The form was, annoyingly, actually sanitized.</li>
<li>Spent an hour on the file upload endpoint assuming it was the intended path. It was a red herring with a suspiciously convenient name.</li>
<li>Finally ran a proper directory brute force instead of guessing based on &quot;vibes,&quot; and found a forgotten debug endpoint that dumped stack traces — including a hardcoded service credential.</li>
</ol>
<h2>The actual lesson</h2>
<p>The foothold was never clever. It was a debug route someone forgot to gate behind an environment check. Every fancy payload I tried was procrastination dressed up as technique.</p>
<pre><code>GET /internal/debug/status HTTP/1.1
Host: target
</code></pre>
<p>Filed under: run the boring enumeration first. My ego keeps forgetting this rule; my notes are here to remind it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>eBPF ring buffer as a covert side channel</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-06-30-ringbuf-side-channel/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-06-30-ringbuf-side-channel/</guid>
      <pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate>
      <category>Scripts &amp; Tools</category>
      <description>Two unprivileged processes sharing a map can modulate ring-buffer pressure to signal a few bits per second. Low bandwidth, but it exists — and it costs no capabilities to build.</description>
      <content:encoded><![CDATA[<p>Two unprivileged processes sharing a map can modulate ring-buffer pressure to signal a few bits per second. Low bandwidth, but it exists — and it costs no capabilities to build.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Prompt injection is just untrusted input, and we forgot</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-06-18-prompt-injection-untrusted-input/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-06-18-prompt-injection-untrusted-input/</guid>
      <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
      <category>AI Security</category>
      <description>We spent twenty years learning not to trust user input, then built agents that trust every input by default.</description>
      <content:encoded><![CDATA[<p>Strip away the &quot;AI&quot; framing and prompt injection is a bug class we already named in 2005: untrusted input reaching a privileged interpreter. We just gave the interpreter a much bigger vocabulary and called the vulnerability something new.</p>
<h2>The uncomfortable parallel</h2>
<ul>
<li>SQL injection: untrusted input treated as executable query.</li>
<li>Prompt injection: untrusted input (a webpage, an email, a tool response) treated as executable instruction.</li>
<li>The fix pattern rhymes too — the model should not be able to tell the difference between &quot;text I&#39;m summarizing&quot; and &quot;instructions I must obey,&quot; the same way a query should never confuse data for code.</li>
</ul>
<h2>Where guardrails actually help, and where they&#39;re theater</h2>
<p>Keyword filters and &quot;please ignore instructions in the following text&quot; system prompts are the equivalent of blacklisting <code>&#39; OR 1=1 --</code>. They catch the laziest attempts and nothing else.</p>
<p>What holds up better:</p>
<ul>
<li>Treating retrieved content as data, never re-parsed as instructions, at the framework level.</li>
<li>Least-privilege tool access, so even a successful injection has nothing useful to reach.</li>
<li>Assuming injection <em>will</em> succeed sometimes, and designing the blast radius accordingly.</li>
</ul>
<p>Not a solved problem. Mostly documenting that the solved-decades-ago problem it rhymes with should be informing the answer more than it currently does.</p>
]]></content:encoded>
    </item>
    <item>
      <title>runc symlink race — already patched, still instructive</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-06-09-runc-symlink-race/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-06-09-runc-symlink-race/</guid>
      <pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate>
      <category>Cloud &amp; Containers</category>
      <description>Chased what I thought was a fresh TOCTOU in a mount path. Turned out to be a known, fixed class. Kept the notes anyway — the shape of the bug is worth remembering, even after the patch makes it boring.</description>
      <content:encoded><![CDATA[<p>Chased what I thought was a fresh TOCTOU in a mount path. Turned out to be a known, fixed class. Kept the notes anyway — the shape of the bug is worth remembering, even after the patch makes it boring.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A CPU-temperature ticker for the terminal, because Activity Monitor is one click too many</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-06-02-cpu-temp-ticker/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-06-02-cpu-temp-ticker/</guid>
      <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
      <category>Scripts &amp; Tools</category>
      <description>The most over-engineered solution to &quot;is my laptop about to become a pancake griddle&quot; I have ever shipped.</description>
      <content:encoded><![CDATA[<p>Some scripts exist to solve a real problem. This one exists because alt-tabbing to Activity Monitor felt like too much friction at 2am while a fuzzer was running.</p>
<h2>The whole thing</h2>
<pre><code class="language-bash">#!/usr/bin/env bash
while true; do
  temp=$(sudo powermetrics --samplers smc -n1 2&gt;/dev/null | grep -i &quot;CPU die temperature&quot;)
  printf &quot;\r%s&quot; &quot;$temp&quot;
  sleep 2
done
</code></pre>
<p>That&#39;s it. That&#39;s the tool. It prints the CPU die temperature in place, in the corner of a terminal I already have open, so I can glance at it without breaking focus on whatever is actually cooking the machine.</p>
<h2>Why it&#39;s in the toolshed and not &quot;deleted immediately&quot;</h2>
<p>Because I&#39;ve reached for it more times than any of my actually-clever scripts. The best tools aren&#39;t the impressive ones — they&#39;re the ones you still run six months later.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A JPEG that owns your Mac</title>
      <link>https://anmolsinghyadav.com/lab/notes/2026-05-25-jpeg-owns-your-mac/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2026-05-25-jpeg-owns-your-mac/</guid>
      <pubDate>Mon, 25 May 2026 00:00:00 GMT</pubDate>
      <category>Offensive Security</category>
      <description>Walked ExifTool's macOS command-injection blind spot end to end — how a metadata parser quietly became a code-execution path (CVE-2026-3102).</description>
      <content:encoded><![CDATA[<p>Walked ExifTool&#39;s macOS command-injection blind spot end to end — how a metadata parser quietly became a code-execution path (CVE-2026-3102).</p>
]]></content:encoded>
    </item>
    <item>
      <title>Your favicon is leaking your infrastructure</title>
      <link>https://anmolsinghyadav.com/lab/notes/2025-07-20-favicon-infrastructure/</link>
      <guid isPermaLink="true">https://anmolsinghyadav.com/lab/notes/2025-07-20-favicon-infrastructure/</guid>
      <pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate>
      <category>Infrastructure</category>
      <description>A four-byte hash is enough to map an organization's forgotten, still-exposed infrastructure. Small input, uncomfortably large output.</description>
      <content:encoded><![CDATA[<p>A four-byte hash is enough to map an organization&#39;s forgotten, still-exposed infrastructure. Small input, uncomfortably large output.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
