<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Security on Tom Meurs</title>
    <link>https://tommeurs.nl/en/categories/security/</link>
    <description>Recent content in Security on Tom Meurs</description>
    <generator>Hugo</generator>
    <language>en</language>
    <copyright>© Tom Meurs</copyright>
    <lastBuildDate>Wed, 23 Sep 2026 19:00:00 +0200</lastBuildDate>
    <atom:link href="https://tommeurs.nl/en/categories/security/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Your Dependency&#39;s Business Model Is Part of Your Threat Model</title>
      <link>https://tommeurs.nl/en/posts/license-change-supply-chain-risk/</link>
      <pubDate>Wed, 23 Sep 2026 19:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/license-change-supply-chain-risk/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; A vendor freezing its free edition belongs in your risk register next to the expiring certificate. Thirty-six dated cases below, three kinds of event, and five questions to score your own stack. My own register had the Vault row missing for three years.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;On 11 September, Portainer&amp;rsquo;s CEO published &lt;a href=&#34;https://www.portainer.io/blog/portainer-3-0-is-coming&#34;&gt;&amp;ldquo;Portainer 3.0 is coming, and here&amp;rsquo;s what it means for you&amp;rdquo;&lt;/a&gt;. I read it the Monday after and shrugged.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s what it says. 3.0 is a Kubernetes-first codebase for enterprise customers, and &amp;ldquo;we are not cutting a separate CE build of it&amp;rdquo;. Community Edition stays on 2.x. 2.45 LTS &amp;ldquo;is the last release in the 2.x line&amp;rdquo;. A few days later they added a clarification: 2.45 keeps getting security fixes, bug fixes and back-ports of any 3.x feature that has a Docker API equivalent, &amp;ldquo;for as long as that LTS is supported&amp;rdquo;. The &lt;a href=&#34;https://docs.portainer.io/start/lifecycle&#34;&gt;lifecycle page&lt;/a&gt; puts that at May 2027. Want 3.x for free? There&amp;rsquo;s a Business Edition key called &lt;a href=&#34;https://www.portainer.io/take-3&#34;&gt;3 Nodes Free&lt;/a&gt;, one per organisation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NIS2 for Platform Teams: Which Control Satisfies Which Article</title>
      <link>https://tommeurs.nl/en/posts/nis2-for-platform-teams/</link>
      <pubDate>Sun, 20 Sep 2026 21:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/nis2-for-platform-teams/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; The Cyberbeveiligingswet has applied since 15 August 2026. Below, the ten measures of &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Cbw art. 21: the duty of care. Appropriate and proportionate measures, of which paragraph 3 names ten.&#34;&gt;article 21&lt;/span&gt;&#xA; mapped onto controls that actually run, a Kyverno policy that proves one of them, the reporting deadlines as three Prometheus alerting rules, and the four duties no YAML covers. The first run of that policy found seven pods in my own cluster I&amp;rsquo;d have sworn were mirrored.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Data Poisoning: Reclaiming Your Privacy Through Offence</title>
      <link>https://tommeurs.nl/en/posts/data-poisoning-privacy/</link>
      <pubDate>Sun, 07 Jun 2026 21:43:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/data-poisoning-privacy/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s how privacy works today. You read the policy. You dismiss the cookie banner. You hunt through three settings menus for the opt-out toggle that someone buried on purpose. All of that to exercise a right that should&amp;rsquo;ve been the default. And while you&amp;rsquo;re still on the first paragraph of the terms of service, every click, scroll, hover and the exact timing of your keystrokes has already been harvested, packaged and sold. Somewhere along the way I stopped finding that strange, and that bothers me more than the harvesting does.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Quantum-safe GPG identity with multiple aliases</title>
      <link>https://tommeurs.nl/en/posts/quantum-safe-gpg-identity/</link>
      <pubDate>Sat, 18 Apr 2026 10:47:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/quantum-safe-gpg-identity/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; One GPG masterkey that only certifies, kept offline. Three aliases bound to it, so anyone can check they&amp;rsquo;re the same person. Ed25519 subkeys for signing and SSH, an ML-KEM plus X448 subkey for encryption so recorded ciphertext stays closed after a quantum computer shows up, and three backups that each assume the other two are gone. Needs GnuPG 2.5.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;A cryptographic signature still means exactly what it says. If the key is yours and the signature verifies, the content came from you. No vendor handed you that identity, no CA can pull it, no platform can suspend it. It exists because you generated the key, and it&amp;rsquo;s yours for as long as you hold the private half. Most of what gets called &amp;ldquo;online identity&amp;rdquo; is borrowed. A handle someone can ban, an email address the domain owner can take back the day they feel like it. A GPG signature sits outside all of that.&lt;/p&gt;</description>
    </item>
    <item>
      <title>cert-manager: Automatic TLS Certificates in Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/cert-manager-kubernetes-tls/</link>
      <pubDate>Sun, 12 Apr 2026 21:38:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/cert-manager-kubernetes-tls/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; cert-manager watches Certificate resources, fetches the certificate from Let&amp;rsquo;s Encrypt, your own CA or Vault, stores it in a Secret and renews it 30 days before it expires. I run one DNS-01 ClusterIssuer through Cloudflare and one wildcard certificate, copy that Secret into the namespaces that need it, and let two Prometheus alerts tell me when a renewal is stuck. Nothing left to remember.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;For years my certificates renewed the way most people&amp;rsquo;s do. A calendar reminder, a manual &lt;code&gt;certbot&lt;/code&gt; run, and the hope that I&amp;rsquo;d get to it before the thing expired. It worked, right up to the morning a service started throwing cert errors at me and I had no idea why. The renewal cron had been failing for weeks. Quietly.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Declarative Infrastructure as Compliance Documentation: Talos, NixOS, and Audit-Ready Systems</title>
      <link>https://tommeurs.nl/en/posts/declarative-infrastructure-compliance-certification/</link>
      <pubDate>Mon, 23 Mar 2026 19:28:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/declarative-infrastructure-compliance-certification/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Talos and NixOS boot from a file that says what the machine is. That file is what an ISO 27001, SOC 2 or NIS2 auditor asks for, so the evidence collection shrinks to a git log, a diff with no output and an inventory dump. Below is the mapping from config to control, the scripts, and the part that stays hard work.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;An ISO 27001 audit starts weeks before the auditor shows up, with someone collecting screenshots. Configuration panels, firewall rules, a dashboard that shows which patches went out. Then the Word documents that describe what the systems are supposed to do. Then the change tickets, dug out of the ticketing system, each one pointing at a &amp;ldquo;server maintenance&amp;rdquo; nobody can reconstruct six months later. Everyone treats this as the price of being in business. I did too, for years.&lt;/p&gt;</description>
    </item>
    <item>
      <title>CTF and Forensics Skills That Make You a Better DevOps Engineer</title>
      <link>https://tommeurs.nl/en/posts/ctf-skills-for-devops/</link>
      <pubDate>Fri, 27 Feb 2026 19:52:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/ctf-skills-for-devops/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I spend my evenings on Hack The Box and it&amp;rsquo;s made me better at my day job, which is platform engineering and has nothing to do with pentesting. The first ten minutes on a &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Capture The Flag: a security exercise where you break into a deliberately vulnerable system and prove it by retrieving a planted token, the flag.&#34;&gt;CTF&lt;/span&gt;&#xA; box and the first ten minutes on a broken production server are the same loop, with &amp;ldquo;flag&amp;rdquo; swapped for &amp;ldquo;incident&amp;rdquo;. Below is the toolkit that loop runs on, from one host up to a Kubernetes pod, with the CTF use and the work use side by side for every command.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Zero Trust Explained: The Hotel Key Card Metaphor</title>
      <link>https://tommeurs.nl/en/posts/zero-trust-explained/</link>
      <pubDate>Thu, 19 Feb 2026 21:34:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/zero-trust-explained/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; The old model is a castle. Get past the wall and you&amp;rsquo;re trusted everywhere inside. Zero trust is a hotel. Your key card opens your room, the gym if you booked it, and nothing else, and every door checks the card every time. Below, the three principles, a day in that hotel, and what the key card turns into once the doors are software.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;So what is this zero trust thing everyone keeps talking about?&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Privacy Matters More Than Ever</title>
      <link>https://tommeurs.nl/en/posts/why-privacy-matters-now/</link>
      <pubDate>Mon, 02 Feb 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/why-privacy-matters-now/</guid>
      <description>&lt;p&gt;Your phone logged where you slept before you woke up. You check Gmail, search something on Google, message a friend on WhatsApp, pay for coffee with a card and walk past a dozen cameras before lunch. None of that feels like surveillance. It feels like a normal morning.&lt;/p&gt;&#xA;&lt;p&gt;It felt the same five years ago, and I want to show you what changed in between. The comfortable version of privacy, &amp;ldquo;I have nothing to hide&amp;rdquo;, has quietly stopped being true, and I think most people haven&amp;rsquo;t noticed. Three things happened at once. On its own each one is manageable. Together they&amp;rsquo;re what worries me.&lt;/p&gt;</description>
    </item>
    <item>
      <title>YubiKey &#43; Pass &#43; GPG &#43; SSH: One Key to Rule Them All</title>
      <link>https://tommeurs.nl/en/posts/yubikey-pass-gpg-ssh/</link>
      <pubDate>Tue, 13 Jan 2026 17:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/yubikey-pass-gpg-ssh/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; One YubiKey carries a GPG key with a signing, an encryption and an authentication subkey. gpg-agent hands the authentication subkey to SSH, git signs with the signing subkey and pass decrypts with the encryption subkey, so one PIN in the morning and a touch per action replace every password I used to type. The SSH part alone is three steps and worth doing on its own.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Every morning I plug in my YubiKey, type one PIN, and that&amp;rsquo;s the last secret I type until I pull it out again. SSH to a server, no password. Sign a commit, no passphrase. Pull a secret out of pass, touch the key. One thing in a USB port, and the rest of the day my authentication happens without me.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pass: the Unix password manager that just works</title>
      <link>https://tommeurs.nl/en/posts/pass-password-manager/</link>
      <pubDate>Sat, 10 Jan 2026 12:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/pass-password-manager/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; pass keeps each password as a GPG-encrypted file in a directory, and the directory is the whole data model. &lt;code&gt;pass -c email/gmail&lt;/code&gt; puts a password in your clipboard from any terminal, &lt;code&gt;pass git push&lt;/code&gt; backs the store up, and the fzf script further down is how I look up every password I have. The price is GPG key management, and it&amp;rsquo;s a real price.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I used KeePass for years. Then 1Password. Then Bitwarden. All decent tools, and every one of them was too much for what I asked of it. Too much UI, too many features, and a password always lived on the other side of an app I had to alt-tab into. A small interruption, and they added up.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GPG explained: from first key to daily use</title>
      <link>https://tommeurs.nl/en/posts/gpg-beginners-guide/</link>
      <pubDate>Tue, 06 Jan 2026 19:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/gpg-beginners-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; GPG encrypts files and signs things, and it sits under pass, under signed git commits and under the checksums maintainers publish. One command gives you a working keypair in five minutes. Subkeys and a YubiKey come later, if ever, and the UX is bad enough that I complain about it at length below.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;GPG is a tool I kept meaning to learn and didn&amp;rsquo;t, for years. The docs are a wall of text, the terminology is its own dialect, and the error messages are cryptic in both senses of the word.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes RBAC: Least Privilege in Practice</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-rbac-least-privilege/</link>
      <pubDate>Tue, 19 Aug 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-rbac-least-privilege/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Kubernetes ships with a permission model that hands every pod a token and lets the default service account collect rights nobody remembers granting. Least privilege means a service account per workload, no token unless the app talks to the API, and roles that name the namespace, the resource and the verb. Below are the four RBAC resources, the five settings that cap the blast radius, the bindings I copy most often, and how I check and enforce all of it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Runtime Security with Falco: Detect Suspicious Behavior in Your Cluster</title>
      <link>https://tommeurs.nl/en/posts/falco-runtime-security/</link>
      <pubDate>Thu, 07 Aug 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/falco-runtime-security/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Trivy and Kyverno check an image before it runs. Falco watches what the container does after that, syscall by syscall, and alerts when the behaviour doesn&amp;rsquo;t match a rule. This post goes from the one thing Falco does to the config I run, with the noise problem in between.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I scanned my images with &lt;a href=&#34;https://tommeurs.nl/en/posts/trivy-container-scanning/&#34;&gt;Trivy&lt;/a&gt;. I enforced policies with &lt;a href=&#34;https://tommeurs.nl/en/posts/kyverno-policies-governance/&#34;&gt;Kyverno&lt;/a&gt;. My workloads got cryptographic identity through &lt;a href=&#34;https://tommeurs.nl/en/posts/spiffe-spire-zero-trust/&#34;&gt;SPIFFE&lt;/a&gt;. Three layers of prevention, all green, and for a while that felt like enough.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SPIFFE and SPIRE: Zero Trust Service Identity</title>
      <link>https://tommeurs.nl/en/posts/spiffe-spire-zero-trust/</link>
      <pubDate>Sat, 26 Jul 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/spiffe-spire-zero-trust/</guid>
      <description>&lt;p&gt;How does Service A know that Service B is actually Service B?&lt;/p&gt;&#xA;&lt;p&gt;I keep coming back to that question because the usual answer is uncomfortable. For years we trusted network location. Traffic from the right IP was legitimate, end of story. Zero trust took that assumption out back and shot it. Now every service has to prove who it is, every single request, no matter where it sits on the network.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kyverno Policies: Governance as Code for Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/kyverno-policies-governance/</link>
      <pubDate>Mon, 14 Jul 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/kyverno-policies-governance/</guid>
      <description>&lt;p&gt;I used to keep a wiki page titled &amp;ldquo;Cluster conventions&amp;rdquo;. Resource limits on everything. No &lt;code&gt;:latest&lt;/code&gt; tags. No deploys in the &lt;code&gt;default&lt;/code&gt; namespace. It was a good page. Nobody read it. Six months in, half the cluster broke those rules and I only found out when something fell over.&lt;/p&gt;&#xA;&lt;p&gt;A rule that lives in a doc is a suggestion. A rule the API server refuses to accept is governance. That gap is the whole reason this post exists.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vault for Beginners: Secrets Management in Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/vault-beginners-kubernetes/</link>
      <pubDate>Wed, 02 Jul 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/vault-beginners-kubernetes/</guid>
      <description>&lt;p&gt;The first time I ran &lt;code&gt;kubectl get secret myapp -o yaml&lt;/code&gt; and base64-decoded the value, I felt my stomach drop. There was my database password, sitting in etcd, readable by anyone who could reach the API with the right RBAC. Kubernetes Secrets are not secrets. They&amp;rsquo;re base64-encoded plain text with a fancy name. That&amp;rsquo;s the default, and it&amp;rsquo;s the thing nobody warns you about on day one.&lt;/p&gt;&#xA;&lt;p&gt;Every cloud provider has a fix for sale. AWS has Secrets Manager, Google has Secret Manager, Azure has Key Vault. They work. The catch shows up later: the day you need to migrate, the day you want to know exactly what happens to a secret after you write it, the day you realise your most sensitive data lives in a system you can&amp;rsquo;t inspect.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Container Image Scanning with Trivy in Your CI Pipeline</title>
      <link>https://tommeurs.nl/en/posts/trivy-container-scanning/</link>
      <pubDate>Sun, 08 Jun 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/trivy-container-scanning/</guid>
      <description>&lt;p&gt;Pull a base image, copy in your code, push it to production. That&amp;rsquo;s the loop most of us run on autopilot. The part nobody looks at is the base image itself, which quietly drags in a few hundred packages you never chose. Any one of them could carry a known &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Common Vulnerabilities and Exposures: the public identifier for one specific vulnerability, in the form CVE-2026-1234. The identifier says nothing about severity.&#34;&gt;CVE&lt;/span&gt;&#xA;, and you&amp;rsquo;d have no idea.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes Network Policies: A Visual Guide to Pod Security</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-network-policies-visual/</link>
      <pubDate>Sat, 08 Feb 2025 19:34:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-network-policies-visual/</guid>
      <description>&lt;p&gt;Picture this: an attacker pops a single pod in your cluster, maybe through a vulnerable image or a leaked token. From that one foothold, they can reach every database, every internal API, every secret-fetching sidecar you run. Nothing stops them, because by default nothing tries to.&lt;/p&gt;&#xA;&lt;p&gt;Network Policies are the thing that stops them. They turn &amp;ldquo;one compromised pod&amp;rdquo; into &amp;ldquo;one compromised pod, and that&amp;rsquo;s it.&amp;rdquo; Everyone knows they should use them. Almost nobody actually does, because the YAML looks scary and the behaviour is weird until the mental model clicks.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
