[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f2683ck9mk4hm8":3,"$fanuq43nlrv5g":56},{"slug":4,"title":5,"body":6,"summary":7,"tags":8,"author":14,"cover_url":15,"published_at":16,"seo_title":17,"seo_description":18,"reading_minutes":19,"related":20},"quoted-tilde-in-path-check","A quoted ~ in your PATH runs whatever sits in .\u002F~\u002F: a one-line check for dotfiles, servers and CI images","\u003Cp>This line is in a lot of dotfiles, Dockerfiles and CI configs:\u003C\u002Fp>\n\u003Cfigure data-post-media=\"6acd58e773d443ad8fa7483a\">\u003Cvideo src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6acd58e873d443ad8fa74840-0-bcc589fc.mp4\" autoplay muted loop playsinline preload=\"metadata\">\u003C\u002Fvideo>\u003C\u002Ffigure>\n\u003Cpre class=\"code-block\" data-lang=\"bash\">\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-built_in\">export\u003C\u002Fspan> PATH=\u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$PATH\u003C\u002Fspan>:~\u002F.local\u002Fbin&quot;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>It looks right, and in your own terminal it usually works. But the \u003Ccode>~\u003C\u002Fcode> sits inside double quotes, so the shell never turns it into your home directory. \u003Ccode>PATH\u003C\u002Fcode> ends up holding the literal string \u003Ccode>~\u002F.local\u002Fbin\u003C\u002Fcode>, which is a \u003Cem>relative\u003C\u002Fem> path: a directory called \u003Ccode>~\u003C\u002Fcode> inside whatever directory a program happens to be running in. Anyone who can create \u003Ccode>.\u002F~\u002F.local\u002Fbin\u002F\u003C\u002Fcode> there (a cloned repo, an unpacked archive, a shared upload folder, \u003Ccode>\u002Ftmp\u003C\u002Fcode>) can put a binary in front of the one you meant to run.\u003C\u002Fp>\n\u003Cp>Dominik Czarnota (disconnect3d) wrote this up on 2 October; below is a reproduction on two systems, the check, and the places worth grepping.\u003C\u002Fp>\n\u003Ch2>Why the tilde stays a tilde\u003C\u002Fh2>\n\u003Cp>Bash only performs tilde expansion on \u003Cem>unquoted\u003C\u002Fem> words. In an assignment it also expands a \u003Ccode>~\u003C\u002Fcode> right after the \u003Ccode>=\u003C\u002Fcode> or after a \u003Ccode>:\u003C\u002Fcode>, which is why the unquoted form works:\u003C\u002Fp>\n\u003Cfigure data-post-media=\"6acd3f0373d443ad8fa743c5\">\u003Cimg src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6acd3f0373d443ad8fa743ca-0-fa2f0bb7.png\" alt=\"A literal tilde in a path creates a hidden, deceptive route for the system.\" loading=\"lazy\">\u003Cfigcaption>A literal tilde in a path creates a hidden, deceptive route for the system.\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003Cpre class=\"code-block\" data-lang=\"bash\">\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-built_in\">export\u003C\u002Fspan> PATH=\u003Cspan class=\"hljs-variable\">$PATH\u003C\u002Fspan>:~\u002F.local\u002Fbin      \u003Cspan class=\"hljs-comment\"># expands: \u002Fhome\u002Fyou\u002F.local\u002Fbin\u003C\u002Fspan>\n\u003Cspan class=\"hljs-built_in\">export\u003C\u002Fspan> PATH=\u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$PATH\u003C\u002Fspan>:~\u002F.local\u002Fbin&quot;\u003C\u002Fspan>    \u003Cspan class=\"hljs-comment\"># stays literal: ~\u002F.local\u002Fbin\u003C\u002Fspan>\n\u003Cspan class=\"hljs-built_in\">export\u003C\u002Fspan> PATH=\u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$PATH\u003C\u002Fspan>:\u003Cspan class=\"hljs-variable\">$HOME\u003C\u002Fspan>\u002F.local\u002Fbin&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-comment\"># expands, and is safe to quote\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The unquoted version is fragile (a space in a path breaks the assignment), so the fix is the third line: use \u003Ccode>$HOME\u003C\u002Fcode>, which expands inside double quotes.\u003C\u002Fp>\n\u003Ch2>Why you never noticed: interactive bash covers for it\u003C\u002Fh2>\n\u003Cp>We planted an executable at \u003Ccode>.\u002F~\u002F.local\u002Fbin\u002Fwhoru\u003C\u002Fcode> in a temp directory, set \u003Ccode>PATH\u003C\u002Fcode> with the quoted tilde, and asked different programs to run \u003Ccode>whoru\u003C\u002Fcode>. On Debian bookworm (bash 5.2.15) in Docker:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" data-lang=\"bash\">\u003Ccode class=\"hljs language-bash\">D=$(\u003Cspan class=\"hljs-built_in\">mktemp\u003C\u002Fspan> -d)\n\u003Cspan class=\"hljs-built_in\">mkdir\u003C\u002Fspan> -p \u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$D\u003C\u002Fspan>\u002F~\u002F.local\u002Fbin&quot;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-built_in\">printf\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;#!\u002Fbin\u002Fsh\\necho PLANTED\\n&#x27;\u003C\u002Fspan> &gt; \u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$D\u003C\u002Fspan>\u002F~\u002F.local\u002Fbin\u002Fwhoru&quot;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-built_in\">chmod\u003C\u002Fspan> +x \u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$D\u003C\u002Fspan>\u002F~\u002F.local\u002Fbin\u002Fwhoru&quot;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-built_in\">cd\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$D\u003C\u002Fspan>&quot;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-built_in\">export\u003C\u002Fspan> PATH=\u003Cspan class=\"hljs-string\">&quot;\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin:~\u002F.local\u002Fbin&quot;\u003C\u002Fspan>\n\nbash -c whoru\nbash --posix -c whoru\nsh -c whoru\nzsh -c whoru\n\u003Cspan class=\"hljs-built_in\">env\u003C\u002Fspan> whoru\npython3 -c \u003Cspan class=\"hljs-string\">&#x27;import subprocess; subprocess.run([&quot;whoru&quot;])&#x27;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"code-block\">\u003Ccode class=\"hljs\">bash -c whoru          bash: line 1: whoru: command not found\nbash --posix -c whoru  PLANTED\nsh -c whoru (dash)     PLANTED\nzsh -c whoru           PLANTED\nenv whoru              PLANTED\npython3 subprocess     PLANTED\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Plain bash looks the command up in \u003Ccode>$HOME\u002F.local\u002Fbin\u003C\u002Fcode>, because it expands a leading \u003Ccode>~\u003C\u002Fcode> in \u003Ccode>PATH\u003C\u002Fcode> entries when it searches. So the commands you type keep working and the bug stays hidden. Everything else takes the entry literally: \u003Ccode>\u002Fbin\u002Fsh\u003C\u002Fcode> on Debian and Ubuntu (dash), which is what \u003Ccode>make\u003C\u002Fcode>, \u003Ccode>system()\u003C\u002Fcode> and many scripts use; zsh; bash in POSIX mode; and anything that calls \u003Ccode>execvp\u003C\u002Fcode> directly, such as \u003Ccode>env\u003C\u002Fcode>, Python's \u003Ccode>subprocess\u003C\u002Fcode> and most language runtimes. On macOS with the stock bash 3.2 we saw the same split: \u003Ccode>bash\u003C\u002Fcode> and \u003Ccode>\u002Fbin\u002Fsh\u003C\u002Fcode> found nothing, while \u003Ccode>zsh\u003C\u002Fcode>, \u003Ccode>env\u003C\u002Fcode> and Python ran the planted file. Python's \u003Ccode>shutil.which(\"whoru\")\u003C\u002Fcode> even returned \u003Ccode>~\u002F.local\u002Fbin\u002Fwhoru\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>The practical result: a tool you start from your shell can run a different binary than the one you get when you type the same name yourself.\u003C\u002Fp>\n\u003Ch2>The one-line check\u003C\u002Fh2>\n\u003Cp>From the original write-up:\u003C\u002Fp>\n\u003Cfigure data-post-media=\"6acd3f0373d443ad8fa743cf\">\u003Cimg src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6acd3f0373d443ad8fa743d4-0-8d927d3b.png\" alt=\"Searching for hidden relative paths in environment configurations.\" loading=\"lazy\">\u003Cfigcaption>Searching for hidden relative paths in environment configurations.\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003Cpre class=\"code-block\" data-lang=\"bash\">\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-built_in\">echo\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$PATH\u003C\u002Fspan>&quot;\u003C\u002Fspan> | \u003Cspan class=\"hljs-built_in\">tr\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;:&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C\u002Fspan> | grep \u003Cspan class=\"hljs-string\">&#x27;~&#x27;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>No output means no literal tilde. While you are there, also look for empty entries and \u003Ccode>.\u003C\u002Fcode>, which have the same effect (the current directory is searched):\u003C\u002Fp>\n\u003Cpre class=\"code-block\" data-lang=\"bash\">\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-built_in\">echo\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;\u003Cspan class=\"hljs-variable\">$PATH\u003C\u002Fspan>&quot;\u003C\u002Fspan> | \u003Cspan class=\"hljs-built_in\">tr\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;:&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C\u002Fspan> | grep -n -v \u003Cspan class=\"hljs-string\">&#x27;^\u002F&#x27;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>That prints every entry that does not start with \u003Ccode>\u002F\u003C\u002Fcode>: empty entries, \u003Ccode>.\u003C\u002Fcode>, a literal \u003Ccode>~\u003C\u002Fcode> and any other relative directory. Each line it shows is searched relative to wherever a program runs.\u003C\u002Fp>\n\u003Ch2>Where to grep\u003C\u002Fh2>\n\u003Cp>Your shell's \u003Ccode>PATH\u003C\u002Fcode> is only one copy. Check the files that build other people's and other machines' environments:\u003C\u002Fp>\n\u003Cpre class=\"code-block\" data-lang=\"bash\">\u003Ccode class=\"hljs language-bash\">grep -rn \u003Cspan class=\"hljs-string\">&#x27;PATH.*~&#x27;\u003C\u002Fspan> \\\n  ~\u002F.bashrc ~\u002F.bash_profile ~\u002F.profile ~\u002F.zshrc ~\u002F.zprofile ~\u002F.config\u002Ffish 2&gt;\u002Fdev\u002Fnull\n\n\u003Cspan class=\"hljs-comment\"># in a repo: Dockerfiles, CI configs, scripts, systemd units\u003C\u002Fspan>\ngit grep -n \u003Cspan class=\"hljs-string\">&#x27;PATH.*~&#x27;\u003C\u002Fspan> -- \\\n  \u003Cspan class=\"hljs-string\">&#x27;*Dockerfile*&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;*.yml&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;*.yaml&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;*.sh&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;*.service&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;*.env&#x27;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>This finds unquoted tildes too, which are fine in shell files; read each hit and fix the quoted ones and everything outside a shell.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Dockerfiles.\u003C\u002Fstrong> \u003Ccode>ENV PATH=\"$PATH:~\u002F.local\u002Fbin\"\u003C\u002Fcode> is common after a \u003Ccode>pip install --user\u003C\u002Fcode>. \u003Ccode>ENV\u003C\u002Fcode> does not do tilde expansion at all, quoted or not (we built one to confirm), so every container from that image carries a literal \u003Ccode>~\u002F.local\u002Fbin\u003C\u002Fcode>. Use the absolute path: \u003Ccode>ENV PATH=\"\u002Froot\u002F.local\u002Fbin:${PATH}\"\u003C\u002Fcode> or \u003Ccode>\u002Fhome\u002Fapp\u002F.local\u002Fbin\u003C\u002Fcode> for a non-root user.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>CI env blocks.\u003C\u002Fstrong> YAML \u003Ccode>env:\u003C\u002Fcode> values are plain strings handed to the runner; a \u003Ccode>~\u003C\u002Fcode> there is not expanded by anything. Write the full path, or append to the runner's path file with \u003Ccode>$HOME\u003C\u002Fcode> in a shell step.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>systemd units.\u003C\u002Fstrong> \u003Ccode>Environment=PATH=...\u003C\u002Fcode> takes the value literally. Use absolute paths.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Shared servers and jump hosts.\u003C\u002Fstrong> These have the most writable directories that other users \u003Ccode>cd\u003C\u002Fcode> into, so a planted \u003Ccode>.\u002F~\u002F\u003C\u002Fcode> folder has the best chance of being hit there. Check the system-wide files too: \u003Ccode>\u002Fetc\u002Fprofile\u003C\u002Fcode>, \u003Ccode>\u002Fetc\u002Fprofile.d\u002F*\u003C\u002Fcode>, \u003Ccode>\u002Fetc\u002Fenvironment\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Fixing it\u003C\u002Fh2>\n\u003Col>\n\u003Cli>Replace \u003Ccode>~\u003C\u002Fcode> with \u003Ccode>$HOME\u003C\u002Fcode> inside quotes: \u003Ccode>export PATH=\"$HOME\u002F.local\u002Fbin:$PATH\"\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>In files that are not shell (Dockerfile \u003Ccode>ENV\u003C\u002Fcode>, YAML, systemd), write the absolute path.\u003C\u002Fli>\n\u003Cli>Open a new shell and run the check again. Then check from the tools that actually matter: \u003Ccode>sh -c 'echo $PATH'\u003C\u002Fcode> and \u003Ccode>env | grep ^PATH=\u003C\u002Fcode> inside the container or CI job.\u003C\u002Fli>\n\u003Cli>If the bad entry has been there a while on a shared machine, look for planted directories: \u003Ccode>find \u002F -xdev -type d -name '~' 2&gt;\u002Fdev\u002Fnull\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Takes about five minutes per repo, and it is one of the few security fixes that is a find-and-replace.\u003C\u002Fp>\n\u003Cfigure data-post-media=\"6acd3f0373d443ad8fa743d9\">\u003Cimg src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6acd3f0373d443ad8fa743de-0-ab341df4.png\" alt=\"Replacing relative tildes with absolute paths secures the environment.\" loading=\"lazy\">\u003Cfigcaption>Replacing relative tildes with absolute paths secures the environment.\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003Ch2>Sources\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fdisconnect3d.pl\u002F\u002F2026\u002F10\u002F02\u002Fdont-put-tilde-in-your-path\u002F\">disconnect3d: Don't put tilde in your PATH (2 Oct 2026)\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.gnu.org\u002Fsoftware\u002Fbash\u002Fmanual\u002Fhtml_node\u002FTilde-Expansion.html\">GNU Bash manual: Tilde Expansion\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fnews.ycombinator.com\u002Fitem?id=50042425\">Hacker News discussion\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>if.codes reproduction: Debian bookworm (bash 5.2.15, dash, zsh, Python 3) in Docker, and macOS (bash 3.2.57, zsh), 12 Oct 2026\u003C\u002Fli>\n\u003C\u002Ful>","export PATH=\"$PATH:~\u002F.local\u002Fbin\" never expands the tilde. Interactive bash hides it, but sh, zsh, env and Python search a folder literally named ~ under the current directory. The check, the fix, and where to grep.",[9,10,11,12,13],"linux","shell","security","devops","ai-assisted","if.codes","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6acd3f0073d443ad8fa743bf-0-c8db0f5d.png","2026-10-12T23:53:16.705Z","A quoted ~ in PATH runs .\u002F~\u002F: the check and the fix","Quoted tildes in PATH become a relative path that sh, zsh, env and Python search. Interactive bash hides it. A one-line check and where to grep.",4,[21,33,44],{"slug":22,"title":23,"type":24,"summary":25,"tags":26,"author":14,"cover_url":30,"published_at":31,"updated_at":32},"docker-published-ports-bypass-ufw-vps-hardening","Docker publishes ports straight past UFW: hardening a fresh VPS without the firewall rule that does nothing","blog","ufw deny 8080 does not stop a Docker container published on 8080. Docker's own docs explain why. A 15-minute fresh-VPS walkthrough: key-only SSH, ufw, then the two fixes that actually close a container port, and a scan from outside to prove it.",[27,11,28,29,13],"docker","vps","firewall","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6acb12dddbaf8c2bc523d0bb-0-21ee3023.png","2026-10-11T05:42:15.363Z","2026-10-11T05:42:15.364Z",{"slug":34,"title":35,"type":24,"summary":36,"tags":37,"author":14,"cover_url":41,"published_at":42,"updated_at":43},"deno-deploy-shutdown-exit-guide","Deno Deploy shuts down in six months: moving a small app to Cloudflare Workers, self-hosted Deno in Docker, or Node","Deno is joining Cloudflare: Deploy has six months left and the runtime gets a year of fixes. Write your app as one fetch handler and you can run it on Workers, in a Deno container or on Node. Code for all three, plus what does not carry over.",[38,39,40,27,13],"deno","cloudflare-workers","migration","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac9c181dbaf8c2bc523a0fd-0-caa268de.png","2026-10-10T05:47:19.665Z","2026-10-10T05:47:19.666Z",{"slug":45,"title":46,"type":24,"summary":47,"tags":48,"author":14,"cover_url":53,"published_at":54,"updated_at":55},"durable-object-alarm-loop-guards","The Durable Object alarm that cost $10,000: guarding setAlarm() loops with backoff, idempotency and a kill switch","Durable Object alarms are at-least-once, retried, and usually rescheduled from inside the handler, which makes a billing loop easy to write. Four guards in TypeScript, a kill switch, and a Vitest test that proves the loop stops.",[49,50,51,52,13],"cloudflare","durable-objects","typescript","cost-control","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac8709b392a85804f209fb3-0-9143ed0c.png","2026-10-09T06:09:10.127Z","2026-10-09T06:09:10.128Z",[57,60,63,65,68,79,91,103,114,123,133,146,160,172,184,195,206,214,225,236,245,256,266,275,284],{"slug":4,"title":5,"type":24,"summary":7,"tags":58,"author":14,"cover_url":15,"published_at":16,"updated_at":59,"reading_minutes":19},[9,10,11,12,13],"2026-10-12T23:53:16.706Z",{"slug":22,"title":23,"type":24,"summary":25,"tags":61,"author":14,"cover_url":30,"published_at":31,"updated_at":32,"reading_minutes":62},[27,11,28,29,13],6,{"slug":34,"title":35,"type":24,"summary":36,"tags":64,"author":14,"cover_url":41,"published_at":42,"updated_at":43,"reading_minutes":62},[38,39,40,27,13],{"slug":45,"title":46,"type":24,"summary":47,"tags":66,"author":14,"cover_url":53,"published_at":54,"updated_at":55,"reading_minutes":67},[49,50,51,52,13],7,{"slug":69,"title":70,"type":24,"summary":71,"tags":72,"author":14,"cover_url":77,"published_at":78,"updated_at":78,"reading_minutes":62},"cctld-hijack-counterfeit-certs-caa-accounturi-ct-watch","Counterfeit certs via hijacked ccTLDs: CAA with accounturi and a CT watch for your domains in 15 minutes","Attackers took over the .gh, .sl and .as registries and got 12 valid certificates for Google domains. CAA would not have stopped the hijack. Here is the CAA record that limits the damage afterwards, and a CT watch script that tells you within a day.",[73,74,75,76,13],"tls","caa","certificate-transparency","dns","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac75337392a85804f207d25-0-12f538ac.png","2026-10-08T22:47:12.408Z",{"slug":80,"title":81,"type":24,"summary":82,"tags":83,"author":14,"cover_url":88,"published_at":89,"updated_at":90,"reading_minutes":62},"embeddinggemma-2-qdrant-truncation-recall","EmbeddingGemma 2 in Qdrant: one 740M model for text, images and audio, and what truncating 768 to 128 dims costs your recall","Google's open multimodal embedder runs locally and truncates from 768 to 128 dims. Index one Qdrant collection at three sizes from a single encode pass, then measure recall@10 on your own queries instead of trusting a benchmark.",[84,85,86,87,13],"embeddings","qdrant","rag","open-models","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac5cceedf0d655df505306e-0-d17d0fef.png","2026-10-07T07:21:20.071Z","2026-10-07T07:21:20.072Z",{"slug":92,"title":93,"type":24,"summary":94,"tags":95,"author":14,"cover_url":99,"published_at":100,"updated_at":101,"reading_minutes":102},"cloudflare-access-strict-service-token-auth-migration","Strict service token auth in Cloudflare Access: moving your scripts and CI over before it bites","Cloudflare Access now has a strict mode for service tokens: 401\u002F403 instead of a 302 to the login page, only Service Auth policies count, and no CF_Authorization cookie. New orgs get it forced on from 5 October. A 15-minute check and switch for existing orgs.",[49,96,97,98,13],"zero-trust","ci-cd","authentication","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac4a8860956594c947bd197-0-f768b25b.png","2026-10-06T08:30:13.154Z","2026-10-06T08:30:13.155Z",5,{"slug":104,"title":105,"type":24,"summary":106,"tags":107,"author":14,"cover_url":111,"published_at":112,"updated_at":113,"reading_minutes":62},"cloudflare-traces-trace-rules-debug-one-customer","Why was that request blocked? Tracing one customer at 100% with Cloudflare Traces and Trace Rules","Cloudflare Traces (open beta) shows a request's path through WAF rules, transforms, cache, Workers and origin as one trace. A recipe: low baseline sampling, a 100% Trace Rule for one host or debug header, traceparent to your origin, OTLP export to your own collector, and what December pricing means.",[49,108,109,110,13],"observability","opentelemetry","tracing","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac338052cb6b40613ac2b7c-0-2294d114.png","2026-10-05T06:22:19.055Z","2026-10-05T06:22:19.056Z",{"slug":115,"title":116,"type":24,"summary":117,"tags":118,"author":14,"cover_url":121,"published_at":122,"updated_at":122,"reading_minutes":102},"copyescape-cve-2026-17106-patch-docker-cp","CopyEscape (CVE-2026-17106): patch docker cp, and stop copying out of running containers","A race in docker cp lets a malicious container write files anywhere the copying process can write on the host. That matters for CI runners and AI-agent sandboxes that copy results out. Check your versions, patch, and change copy-out jobs to stop the container first.",[27,11,119,120,13],"cve","ci","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac218ebfd770659725abe68-0-eee7c8f7.png","2026-10-04T23:51:14.689Z",{"slug":124,"title":125,"type":24,"summary":126,"tags":127,"author":14,"cover_url":130,"published_at":131,"updated_at":132,"reading_minutes":19},"protected-quick-tunnels-vs-tailscale-funnel","Share localhost with three named people: Cloudflare's Protected Quick Tunnels vs Tailscale Funnel","cloudflared 2026.9.3 adds --allowed-mail: your quick tunnel now sits behind an email one-time PIN, checked against an allow-list on your own machine, free and without a Cloudflare account. The commands, what it protects, and when Tailscale Serve or Funnel is the better fit.",[49,128,129,11,13],"tailscale","tunnels","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ac218d8fd770659725abe3a-0-40f8cb2e.png","2026-10-04T23:19:14.764Z","2026-10-04T23:19:14.765Z",{"slug":134,"title":135,"type":24,"summary":136,"tags":137,"author":14,"cover_url":143,"published_at":144,"updated_at":145,"reading_minutes":62},"si-domains-super-intelligence-data",".si after 'Super Intelligence': did one UN speech move a ccTLD?","Trump renamed AI 'super intelligence' at the UN on 22 September 2026 and Slovenia's .si went from about 190,000 names to almost 276,000 in a month. Registry numbers, prices, and 87 WHOIS checks: the obvious AI names were gone years ago; the compounds went in days.",[138,139,140,141,142,13],"domains","si","tld","data","ai","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abaaee53e21d5cbd14d442d-0-d6243bc5.png","2026-10-04T22:36:14.598Z","2026-10-04T22:36:14.599Z",{"slug":147,"title":148,"type":24,"summary":149,"tags":150,"author":14,"cover_url":156,"published_at":157,"updated_at":158,"reading_minutes":159},"palantir-agent-stack-python","Steal Palantir's agent stack: typed tools, one LLM gateway, swappable models","An X thread boils Palantir's AIP docs down to four agent patterns. We check each one against the docs, then build them in one stdlib-only Python file: typed business-object tools, a gateway that masks PII, caches and retries, a model set in config, and schedule\u002Fevent\u002FAPI triggers.",[151,152,153,154,155,13],"ai-agents","llm","python","architecture","palantir","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abd88f9c951ea7137fa3872-0-48eb7eee.png","2026-10-01T23:05:10.531Z","2026-10-01T23:05:10.532Z",10,{"slug":161,"title":162,"type":24,"summary":163,"tags":164,"author":14,"cover_url":168,"published_at":169,"updated_at":170,"reading_minutes":171},"claude-code-effort-levels","Effort levels in Claude Code: when max effort pays off and when it just burns tokens","Anthropic's effort deep dive (Terminal-Bench 3.0 plus three builds) shows higher effort mostly buys verification and edge-case testing, not smarter code. A rule of thumb per task type, the commands to set effort, and a script to measure cost vs pass rate on your own repo.",[165,166,152,167,13],"claude-code","ai-coding","developer-tools","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abd88edc951ea7137fa3804-0-2716005a.png","2026-10-01T22:32:14.139Z","2026-10-02T04:44:58.001Z",9,{"slug":173,"title":174,"type":24,"summary":175,"tags":176,"author":14,"cover_url":180,"published_at":181,"updated_at":182,"reading_minutes":183},"agentic-inbox-cloudflare-setup","Self-host an AI email agent on Cloudflare Workers: agentic-inbox set up and costed","Cloudflare's open-source agentic-inbox runs a full email client on Workers, with one SQLite Durable Object per mailbox and a Kimi K2.5 agent that drafts replies. Covers the post-deploy steps people miss (Access, sending, routing, mailbox first) and the cost.",[49,177,151,178,179,13],"workers","email","self-hosting","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abd88dac951ea7137fa378b-0-5b0ec96d.png","2026-10-01T08:17:18.646Z","2026-10-05T05:56:11.919Z",8,{"slug":185,"title":186,"type":24,"summary":187,"tags":188,"author":14,"cover_url":192,"published_at":193,"updated_at":194,"reading_minutes":183},"audit-ai-agent-public-traces","Nearly a million leaked links: auditing what your AI agents leave on the public web","OpenAI's agent swarm left almost a million public shortener URLs holding credentials. Here's a tested shell + gitleaks audit to find the shortlinks, pastes and webhooks your own agents created, scan them for secrets and close the channels.",[11,189,190,191,152,13],"agents","secrets","gitleaks","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abaad873e21d5cbd14d4397-0-0f4f51f7.png","2026-10-01T07:43:19.642Z","2026-10-01T08:44:43.041Z",{"slug":196,"title":197,"type":24,"summary":198,"tags":199,"author":14,"cover_url":203,"published_at":204,"updated_at":205,"reading_minutes":183},"mikrotrick-check-patch-mikrotik","MikroTrick: check and patch your MikroTik in 15 minutes","Two chained RouterOS bugs give anyone who can reach SSH full admin, no password needed, and attacks started before the patch. Find exposed SSH, check the version, grep for the published IoCs, patch and move management behind WireGuard.",[11,200,201,202,179,13],"mikrotik","routeros","ssh","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abcd9c0838b650cb96b3d10-0-6cd107e0.png","2026-10-01T07:02:15.03Z","2026-10-01T08:44:41.391Z",{"slug":207,"title":208,"type":24,"summary":209,"tags":210,"author":14,"cover_url":211,"published_at":212,"updated_at":213,"reading_minutes":183},"agent-sandbox-dns-egress-lockdown","Your agent sandbox leaks through DNS: lock down egress in 15 minutes","An OpenAI model escaped its sandbox by tunnelling questions through DNS. Here is a tested Docker Compose setup for coding agents: a DNS allowlist, a logging egress proxy and a kill switch that actually fires.",[11,27,189,76,179,13],"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abaaca13e21d5cbd14d4306-0-cb93fe1b.png","2026-10-01T03:00:15.943Z","2026-10-01T08:44:43.165Z",{"slug":215,"title":216,"type":24,"summary":217,"tags":218,"author":14,"cover_url":222,"published_at":223,"updated_at":224,"reading_minutes":67},"who-blocks-ai-crawlers-robots-txt","Who blocks AI crawlers? robots.txt vs the network edge, with numbers","I scanned robots.txt on the top 300 sites: 33 of 138 block GPTBot, 14 block training but allow AI search. What each AI bot directive controls, why robots.txt is only a request, and a copy-paste policy plus nginx rule for small SaaS sites.",[142,219,220,49,221,13],"robots-txt","seo","saas","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abcd9c1838b650cb96b3d1b-0-11f94198.png","2026-09-30T21:00:20.673Z","2026-10-01T20:47:34.092Z",{"slug":226,"title":227,"type":24,"summary":228,"tags":229,"author":14,"cover_url":233,"published_at":234,"updated_at":235,"reading_minutes":19},"bullet-time-with-first-last-frame-video","Bullet time with first\u002Flast-frame video: orbiting a frozen moment from three stills","A freeze-frame camera orbit built from generated stills: one action shot, two camera-move angles, two first\u002Flast-frame clips between them, stitched and ping-ponged. The pipeline, the seams, and where the model re-imagines the water.",[142,230,231,232],"comfyui","video-generation","flowdsl","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abae46c45201648bfd477a7-0-6f4d036e.png","2026-09-28T22:42:41Z","2026-09-28T22:42:41.6Z",{"slug":237,"title":238,"type":24,"summary":239,"tags":240,"author":14,"cover_url":242,"published_at":243,"updated_at":244,"reading_minutes":67},"an-ai-media-pipeline-that-shows-its-work","An AI media pipeline that shows its work: ComfyUI presets, FlowDSL routing and the misses","How the images on my sites are generated: four ComfyUI presets behind one Go module, job rows as state, FlowDSL flows for routing, per-post media in the admin — and the bugs and model misses I hit shipping it. This post's own images were made the same way.",[142,232,230,241],"image-generation","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6aba8ba317ceba3543925be4-0-2f6b8a5c.png","2026-09-28T15:57:50Z","2026-10-01T20:47:34.327Z",{"slug":246,"title":247,"type":24,"summary":248,"tags":249,"author":14,"cover_url":252,"published_at":253,"updated_at":254,"reading_minutes":255},"openai-embeddings-python-mongodb","Transforming Text into Vectors: OpenAI Embeddings in Python","Learn how to generate text embeddings with the OpenAI API in Python to power semantic search, recommendations, and more. Includes practical examples with MongoDB integration and cost analysis.",[250,142,153,251],"openai","mongodb","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c2d-0-2e60b732.png","2024-11-23T00:00:00Z","2026-09-28T22:31:01.385Z",3,{"slug":257,"title":258,"type":24,"summary":259,"tags":260,"author":14,"cover_url":262,"published_at":263,"updated_at":264,"reading_minutes":265},"check-pricing-availability-ing-domains","Last Chance to Grab Short .ING Domains: The Extended List Part II","Welcome back to the second part of our exciting exploration into the .ING domain zone! This time, I've expanded our horizons to bring you an even larger selection of .ING domain names. List of over 24,000 domain names inside.",[138,261],"business","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c38-0-c55f4c8d.png","2023-12-14T00:00:00Z","2026-09-28T22:31:01.453Z",1,{"slug":267,"title":268,"type":24,"summary":269,"tags":270,"author":14,"cover_url":271,"published_at":272,"updated_at":273,"reading_minutes":274},"impressive-ing-domains","Unveiling the Impressive .ING Domains","Discover the vast potential of the new .ING domain zone in my latest blog post! I've used AI and a Python script to unearth a treasure trove of available domain names. From budget-friendly picks to exclusive premium domains, there's something for every ambition. Plus, a special list of unique, lesser-known domains awaits.",[138,261],"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c43-0-03be24b7.png","2023-12-11T00:00:00Z","2026-09-28T22:31:01.527Z",2,{"slug":276,"title":277,"type":24,"summary":278,"tags":279,"author":14,"cover_url":281,"published_at":282,"updated_at":283,"reading_minutes":255},"secured-web-server-in-5-minutes","Fortify Web Server Security in 5 Minutes with Tailscale","Tailscale revolutionizes secure networking with its user-friendly approach, effortlessly connecting devices across diverse networks.",[29,128,280],"webserver","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c4e-0-eae6f62d.png","2023-11-03T00:00:00Z","2026-09-28T22:31:01.597Z",{"slug":285,"title":286,"type":24,"summary":287,"tags":288,"author":14,"cover_url":291,"published_at":292,"updated_at":293,"reading_minutes":62},"lets-encrypt-free-ssl","How to Secure Your Website with Free SSL Certificates for a Lifetime","Let’s Encrypt certificates have revolutionized internet security by providing free, automated, and widely trusted SSL\u002FTLS certificates. The non-profit Certificate Authority (CA) has significantly contributed to a more secure web environment by simplifying the process of securing websites with HTTPS.",[289,290,280],"ssl","https","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c59-0-bf2a9a0a.png","2023-11-01T00:00:00Z","2026-09-28T22:39:13.555Z"]