<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>bradleyjkemp</title><link>https://bradleyjkemp.dev/</link><description>Recent content on bradleyjkemp</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 22 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://bradleyjkemp.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Phish Report</title><link>https://bradleyjkemp.dev/project/phish.report/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/project/phish.report/</guid><description>&lt;p&gt;&lt;strong&gt;Phish Report&lt;/strong&gt; is a tool I built for security teams to detect phishing websites
(based on a rule language called &lt;a href="https://phish.report/IOK"&gt;IOK&lt;/a&gt;) and then coordinate
their takedown via abuse reports to hosting providers.&lt;/p&gt;</description></item><item><title>Boiling the egg</title><link>https://bradleyjkemp.dev/post/boiling-the-egg/</link><pubDate>Sun, 22 Feb 2026 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/boiling-the-egg/</guid><description>&lt;p&gt;If you compromise an employee at a mature, well-secured enterprise, what do you get?
Lots of team-specific communication and documents, sure, but any broader company information or systems access is usually locked down behind approvals processes.
Getting to anything good requires some lateral movement and privilege escalation.&lt;/p&gt;
&lt;p&gt;Startups, however, are like a raw egg.
Break the shell, and everything falls out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A huge chunk of their Slack instance: company conversations and every embarrassing detail from the &lt;strong&gt;#incidents&lt;/strong&gt; channel.&lt;/li&gt;
&lt;li&gt;Broad access to production systems and data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No extra work required.&lt;/p&gt;</description></item><item><title>How to interview (founding) security engineers</title><link>https://bradleyjkemp.dev/post/interviewing-security-engineers/</link><pubDate>Sat, 07 Feb 2026 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/interviewing-security-engineers/</guid><description>&lt;p&gt;How do you hire your startup&amp;rsquo;s first security engineer?&lt;/p&gt;
&lt;p&gt;Over the last few months, I&amp;rsquo;ve been through half a dozen interview processes for founding security engineer roles.
Here&amp;rsquo;s what I think actually works, and what&amp;rsquo;s a waste of everyone&amp;rsquo;s time.&lt;/p&gt;
&lt;p&gt;In short:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use your standard engineering interviews.&lt;/li&gt;
&lt;li&gt;Tweak the system design interview more towards security.&lt;/li&gt;
&lt;li&gt;Use the behavioural interview to understand how they&amp;rsquo;ll work with (and not against) your engineers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don&amp;rsquo;t use &amp;ldquo;what&amp;rsquo;s insecure about this HTTP handler&amp;rdquo; puzzles.&lt;/p&gt;</description></item><item><title>Fuses: a simple pattern for preventing runaway automation</title><link>https://bradleyjkemp.dev/post/software-fuses/</link><pubDate>Tue, 06 Jan 2026 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/software-fuses/</guid><description>&lt;p&gt;I&amp;rsquo;ve built and maintained countless &amp;ldquo;janitor&amp;rdquo; systems in my career:
cronjobs which go and clean up old resources like user accounts which should no longer be active.
On multiple occasions, one of those janitors has gone off the rails and &lt;strong&gt;locked the entire company out of their accounts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now, whenever I build systems like this, I include a &amp;ldquo;fuse&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The fuse defines a maximum value I expect the system to handle at any one time.
The number of accounts to delete, or number of permissions to revoke.
If the janitor ever tries to exceed this value, the fuse &amp;ldquo;blows&amp;rdquo; and requires a human to intervene.&lt;/p&gt;</description></item><item><title>New year, new blog theme</title><link>https://bradleyjkemp.dev/post/new-year-new-blog-theme/</link><pubDate>Thu, 01 Jan 2026 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/new-year-new-blog-theme/</guid><description>&lt;p&gt;Yes, I&amp;rsquo;ve made the classic mistake and re-started a writing habit by fiddling with
the technology.
Rather than, you know, actually writing something.&lt;/p&gt;
&lt;p&gt;But I cringed every time I clicked a link to someone&amp;rsquo;s blogpost and saw they were using the same &lt;a href="http://gohugo.io/"&gt;Hugo&lt;/a&gt; template as me
(which, with &lt;a href="https://github.com/adityatelange/hugo-PaperMod"&gt;~13k stars&lt;/a&gt;, is a lot of people!)&lt;/p&gt;
&lt;p&gt;When I bought this domain, I had zero frontend experience so had no choice but to just pick something full-featured
off the shelf and hope it had everything I&amp;rsquo;d need.
But over the past couple years building &lt;a href="https://phish.report"&gt;a startup&lt;/a&gt;, I&amp;rsquo;ve learnt enough web skills to be
dangerous.&lt;/p&gt;</description></item><item><title>Are you building features for phishers?</title><link>https://bradleyjkemp.dev/post/are-you-building-features-for-phishers/</link><pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/are-you-building-features-for-phishers/</guid><description>&lt;p&gt;People expect companies/services to tell them when untoward things could be happening to their accounts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Their account has logged in on a new device&lt;/li&gt;
&lt;li&gt;Their password has been changed&lt;/li&gt;
&lt;li&gt;An export of their data was started&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These examples are things you &lt;em&gt;should&lt;/em&gt; probably be notified about.
But, if you go overboard with these warnings, you might find phishers triggering them &lt;strong&gt;&lt;em&gt;intentionally&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="a-bad-security-warning"&gt;A bad security warning&lt;/h2&gt;
&lt;p&gt;Imagine receiving this warning email:&lt;/p&gt;</description></item><item><title>A Suspicious CVC</title><link>https://bradleyjkemp.dev/post/suspicious-cvc/</link><pubDate>Sat, 21 Aug 2021 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/suspicious-cvc/</guid><description>&lt;p&gt;I once got a debit card with the CVC number 000.&lt;/p&gt;
&lt;p&gt;Now, in theory, I know there&amp;rsquo;s nothing wrong with this.
The number was chosen randomly and it being &amp;ldquo;special&amp;rdquo; is purely in my head.&lt;/p&gt;
&lt;p&gt;In fact, if 000 were excluded from the picking process, there&amp;rsquo;d be fewer possible CVCs and so overall they&amp;rsquo;d be less secure.&lt;/p&gt;
&lt;p&gt;But, 000 still feels really wrong as a CVC. Was it a bug? Did an entire batch of cards get generated with the same CVC?&lt;/p&gt;</description></item><item><title>LaunchDaemon Hijacking: privilege escalation and persistence via insecure folder permissions</title><link>https://bradleyjkemp.dev/post/launchdaemon-hijacking/</link><pubDate>Mon, 10 May 2021 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/launchdaemon-hijacking/</guid><description>&lt;p&gt;LaunchDaemon (or LaunchAgent) Hijacking is a MacOS privilege escalation and persistence technique.
It involves abusing insecure file/folder permissions to replace legitimately installed, misconfigured LaunchDaemons with malicious code.&lt;/p&gt;
&lt;p&gt;I first spotted this issue affecting the &lt;a href="https://osquery.io"&gt;OSQuery&lt;/a&gt; installer but went looking and found multiple other products with the same problem.
This isn&amp;rsquo;t a novel technique (it&amp;rsquo;s briefly mentioned in &lt;a href="https://attack.mitre.org/versions/v9/techniques/T1543/004/"&gt;T1543.004&lt;/a&gt;) but I was surprised to find it so rarely talked about.&lt;/p&gt;
&lt;h2 id="demo"&gt;Example &amp;ndash; Hijacking the OSQuery LaunchDaemon&lt;/h2&gt;
&lt;div class="not-prose my-6 flex gap-4 rounded-lg border border-gray-200 bg-gray-50 px-5 py-4 text-gray-700 shadow-sm dark:border-gray-800 dark:bg-gray-900/60 dark:text-gray-200"&gt;
 &lt;div class="text-2xl leading-none mt-1"&gt;😇&lt;/div&gt;
 &lt;div class="prose prose-lg max-w-none text-gray-700 dark:prose-invert prose-p:my-0"&gt;
 I&amp;rsquo;ve already disclosed this issue to the OSQuery team and they kindly let me use it as an example in this post. A fix will hopefully be coming in a future release 🤞🏻
 &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="what-is-osquery"&gt;What is OSQuery?&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://osquery.io"&gt;OSQuery&lt;/a&gt; is a monitoring tool that lets you remotely query the configuration and status of hosts using SQL.
On MacOS, this is accomplished by running a LaunchDaemon on each laptop that syncs with a backend server.&lt;/p&gt;</description></item><item><title>6 ways to detect phishing sites using high-entropy strings</title><link>https://bradleyjkemp.dev/post/6-ways-to-detect-phishing-sites-using-high-entropy-strings/</link><pubDate>Wed, 14 Apr 2021 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/6-ways-to-detect-phishing-sites-using-high-entropy-strings/</guid><description>&lt;p&gt;You&amp;rsquo;d expect phishing sites to be hard to detect and track, but actually, many of them contain HTML fragments that uniquely identify them.
One example doing the rounds at the moment is a bunch of Royal Mail phishing sites which all contain the string &lt;code&gt;css_4WjozGK8ccMNs2W9MfwvMVZNPzpmiyysOUq4_0NulQo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These sorts of long, random strings are extremely good indicators for tracking phishing sites.
Any webpage that contains &lt;code&gt;css_4WjozGK8ccMNs2W9MfwvMVZNPzpmiyysOUq4_0NulQo&lt;/code&gt; is almost certainly an instance of that Royal Mail phishing kit.&lt;/p&gt;</description></item><item><title>Simple A/B testing with Caddy and Plausible Analytics</title><link>https://bradleyjkemp.dev/post/simple-a/b-testing-with-caddy-and-plausible-analytics/</link><pubDate>Mon, 08 Mar 2021 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/simple-a/b-testing-with-caddy-and-plausible-analytics/</guid><description>&lt;p&gt;A/B testing is a lifesaver for a solo SaaS developer.
While it&amp;rsquo;s hard to predict whether a 14-day or 1-month trial is going to get a better signup rate, it&amp;rsquo;s really simple to test:
show half of people the 14-day button and the other half the 1-month button and just measure the click-through rate.&lt;/p&gt;
&lt;p&gt;There are loads of tools out there to help you do this, but rule #1 of running a micro-SaaS like QueryCal is to keep your technology stack simple&amp;mdash;it&amp;rsquo;s better to focus your time on features, not integrating a bunch of different technologies.&lt;/p&gt;</description></item><item><title>Assurance alerts: when measuring false-positive rate can be misleading</title><link>https://bradleyjkemp.dev/post/assurance-alerts-when-measuring-false-positive-rate-can-be-misleading/</link><pubDate>Mon, 08 Feb 2021 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/assurance-alerts-when-measuring-false-positive-rate-can-be-misleading/</guid><description>&lt;p&gt;Nobody likes alerts that feel like a waste of time to review.
But, how do you tell whether an alert is actually a waste of time?&lt;/p&gt;
&lt;p&gt;The go-to metric to use is false-positive rate&amp;mdash;if an alert has high a false-positive rate then it&amp;rsquo;s &amp;ldquo;noisy&amp;rdquo; and might be getting rid of.
But, trying to distill the performance of an alert down to a single number is hard and false-positive rate might be a particularly bad choice.&lt;/p&gt;</description></item><item><title>Spending your security goodwill budget wisely</title><link>https://bradleyjkemp.dev/post/spending-your-security-goodwill-budget-wisely/</link><pubDate>Mon, 04 Jan 2021 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/spending-your-security-goodwill-budget-wisely/</guid><description>&lt;p&gt;Making users more secure generally means annoying them.
Whether it&amp;rsquo;s making them carry a hardware security key or just enforcing a short screensaver timeout, changing how people go about their work is annoying&amp;mdash;and an annoyed user is not a secure user.&lt;/p&gt;
&lt;p&gt;The effectiveness of a lot of security controls relies on the user cooperating.
If they get frustrated with all the barriers and friction between them and doing their actual job, they might just find ways around the controls&amp;mdash;their shortened screensaver timeout is soon &amp;ldquo;fixed&amp;rdquo; with a keep-awake app and now they&amp;rsquo;re less secure than they were before.&lt;/p&gt;</description></item><item><title>How intrusion detection honeypots work so well</title><link>https://bradleyjkemp.dev/post/how-intrusion-detection-honeypots-work-so-well/</link><pubDate>Tue, 08 Dec 2020 00:00:00 +0000</pubDate><guid>https://bradleyjkemp.dev/post/how-intrusion-detection-honeypots-work-so-well/</guid><description>&lt;p&gt;Intrusion detection honeypots are just plain cool.
They&amp;rsquo;re incredibly simple to run and give you extremely accurate alerts about intruders in your systems.&lt;/p&gt;
&lt;p&gt;A honeypot can be as simple as a fake server inside your network that alerts if anyone connects to it.
There&amp;rsquo;s no reason to intentionally connect to this bogus server, so any attempts are probably an attacker already inside your network.&lt;/p&gt;
&lt;p&gt;Unfortunately, that&amp;rsquo;s about as far as most people get with them.
It&amp;rsquo;s a shame that so often honeypots get written off as just a novelty&amp;mdash;no more than a neat trick to catch pentesters.
Most people miss the point behind honeypots.&lt;/p&gt;</description></item><item><title>Snapshot Testing Is Hard -- Pitfalls To Avoid</title><link>https://bradleyjkemp.dev/post/snapshot-testing-is-hard--pitfalls-to-avoid/</link><pubDate>Tue, 19 Dec 2017 12:21:26 +0000</pubDate><guid>https://bradleyjkemp.dev/post/snapshot-testing-is-hard--pitfalls-to-avoid/</guid><description>&lt;p&gt;Snapshot testing is an extremely fast way to add regression testing to an existing project.
You simply take some example inputs and then snapshot the resulting outputs.
From then on, you can have a high degree of confidence that any changes you make have not affected backwards compatibility (as this would have been detected as a change in a snapshot).&lt;/p&gt;
&lt;p&gt;However there are many pitfalls you can run into as I found when writing &lt;a href="https://github.com/bradleyjkemp/cupaloy"&gt;cupaloy&lt;/a&gt;, a snapshot testing library for Go.&lt;/p&gt;</description></item></channel></rss>