Tech Blog   (138 posts in ~17 years)

Random   RSS   Atom

  Searches stay local. No external search engine is involved.

2026 16 posts

↑ Top of page

Daily Automatic Updates, Safely

LLMs are finding vulnerabilities faster than ever. Let CI update your dependencies, images and OS daily, with tests, rollbacks and cool-off periods.

Caging the PowerDNS API

The PowerDNS API key grants full access, so I wrote PDNS-API-Cage, a proxy that lets Traefik touch only the ACME records it needs in chosen zones.

GKG Net Bad Domain Registrar

I used to recommend GKG. One of their nameservers fails on IPv6, the nameserver form is broken and support never replies, so I now warn people off.

Hardening Container Images

I rebuilt PowerDNS Recursor as a static scratch image with Landlock and a seccomp allowlist, daily rebuilds, an SBOM, OpenVEX and cosign signatures.

Sanitising Email

Sanimail, my open source mail filter, inlines remote images, sanitises HTML by policy, strips tracking parameters and handles PGP and S/MIME.

Notifications on Calendar Changes

calendiff is my self hosted tool that checks an ICS feed from cron and reports changes. Its cal2email tool sends tidy emails, with filters for noisy edits.

Auth Proxy Injection for LLMs

My Claude sandbox injects API credentials through a mitmproxy sidecar so the model never sees them, with websocket, GraphQL and token refresh support.

Development AI vs Runtime AI

Tesla's app added an AI Home Status summary with an 'AI can make mistakes' warning. Better to have AI write deterministic code once than call a model.

Stadia Maps Privacy Fail

A 'fiercely privacy-first' company sent its legal update with about 1,000 customer addresses in the To header, then an apology that said only 'some'.

Cert Authorities Check for DNSSEC From Today

From 15 March 2026, CAs must validate DNSSEC on CAA lookups and ACME checks. I've run DNSSEC for 14 years; see if your registrar supports it.

Website Testing on Steroids

The tests I run on this website: Go unit and integration tests, vnu validation, Playwright in three browsers, axe-core, pixel-exact screenshots and more.

ParseMail

My open source Django site: paste raw email source and see its IPs, URLs, MIME tree and rendered parts, with local translation. Easy to run in Docker.

New Website, New Technology

I rebuilt grepular.com in Go with posts in markdown. Notes on SVG sprites, Early Hints, speculation rules, browser tests and a single embedded binary.

Apple's "Protect Mail Activity" Doesn't Work

In my tests, iPhone Mail didn't prefetch remote content as Apple claims, and leaked via DNS prefetch. Apple closed my report. Use these settings.

2025 5 posts

↑ Top of page

Immortal SSH Sessions

A tiny sshx wrapper runs mosh with screen, so my SSH sessions survive network changes, sleeping for days and even a laptop reboot.

Fun with Gzip Bombs and Email Clients

I served a 10MB gzip bomb as an image in HTML email. Most clients and proxies coped, iOS Mail crashed and Evolution wrote 100GB of cache to my disk.

Evolution Mail Users Easily Trackable Part 2

I added a link preconnect test to the Email Privacy Tester. Evolution's developers called my last post a smear and locked the bug thread instead.

Evolution Mail Users Easily Trackable

A dns-prefetch tag in an HTML email makes Evolution Mail do a DNS lookup on open, even with remote content blocked. The developers blame WebKitGTK.

Blocking Russian IPs

A few lines of config with libnginx-mod-http-geoip on Debian 12 that show visitors from Russian IPs a plain text message instead of your site.

2024 1 post

↑ Top of page

Sending Email Using Curl

My Gitlab runner emails me when it pushes a new Docker image. No webhook service needed, just curl talking to an authenticated SMTP server on port 465.

2023 1 post

↑ Top of page

Skiff.com Email's Various Privacy Failures

Skiff fetched blocked remote content in the background, leaked IPs on iOS until a later fix, and skipped MTA-STS. Its CEO called my report disinformation.

2021 1 post

↑ Top of page

Self Building and Executing Dockerfiles

A shebang trick that makes a Dockerfile executable: running it builds the image with podman and runs it with your args. My example wraps yt-dlp.

2020 2 posts

↑ Top of page

Sandbox Rust Development with Rust Analyzer

I keep cargo in Docker with saferrust. Getting rust-analyzer in VS Code to work the same way took a wrapper script, a custom image and a sudo rule.

Manage Firewall from Dockerised NodeJS

Running iptables and pcap from a Node app in Docker without root: a setuid xtables binary, setcap on node, NET_ADMIN and NET_RAW, and host networking.

2019 1 post

↑ Top of page

Nginx Restic Backend

I replaced Restic's Rest Server with plain Nginx, using the DAV and Lua modules and JSON autoindex to give append-only backups with per-host credentials.

2018 1 post

↑ Top of page

Twitter to RSS with Google Cloud Function

I wrote funcTwitter, a GPL NodeJS app that runs on Google Cloud's free tier and turns Twitter accounts or searches into RSS. It stopped working in 2023.

2017 7 posts

↑ Top of page

GPG Agent Forwarding

With OpenSSH 6.7 or later on Debian Stretch, one RemoteForward line in ~/.ssh/config lets me use gpg on a server without my private keys being on it.

Keybase Browser Extension Insecure

The Keybase extension injects its chat box into the page, so Reddit, Twitter and the others can read what you type and send messages as you. Use the app.

Email Authentication Failure

Changes to a friend's mailing list broke first my DKIM signature, then my SPF, and DMARC began rejecting my mail. Plus an XSS bug in dkimvalidator.com.

Monitoring Expiry of GPG Keys

My small Perl script warns when a PGP master key or subkey is close to expiry. It prints nothing otherwise, so a daily cron job emails me only when needed.

Lavabit Security Misconfiguration

Lavabit's IMAP and SMTP servers accepted my login over an unencrypted connection. They should require STARTTLS and refuse authentication without it.

Private Location Tracking/Sharing

I use OwnTracks with my own Mosquitto MQTT server to track and share my phone's location without a third party, even running it over a Tor hidden service.

2016 3 posts

↑ Top of page

When Backup MXs Are Ignored

My primary MX hung, accepting TCP connections but sending no SMTP banner. GMail, Sendgrid and Github waited on it for a week and never tried my backup MX.

DNSCrypt Reduces Privacy

DNSCrypt hides DNS lookups from your ISP but shows them to whoever runs the resolver, and SNI and IPs still reveal your browsing. Use Tor or a VPN.

2015 3 posts

↑ Top of page

MeteorJS Sorting Troubles

MongoDB sorts case sensitively and Minimongo can't do aggregation, so case insensitive sorting with reactive pagination in Meteor needs ugly workarounds.

An NFC PGP SmartCard For Android

With PGP subkeys on a Yubikey Neo, I sign and decrypt mail in K-9 and OpenKeychain over NFC, so my Android phone never has access to my keys.

Perfectly Private Android Networking (Almost)

OpenVPN, Orbot and orWall gave my rooted phone per-app network rules, but Android's in-kernel DNS resolver lets blocked apps leak data through DNS lookups.

2014 4 posts

↑ Top of page

DNS Validation of Email Addresses in Perl

Checking an email domain has MX, A or AAAA records in Perl, with all three lookups sent at once via Net::DNS bgsend and IO::Select so nothing blocks.

2013 3 posts

↑ Top of page

Transparent Access to Tor Hidden Services

Any device on my LAN can reach .onion sites with no setup. Unbound forwards to Tor's DNSPort, iptables redirects to TransPort, Tor2webMode cuts the hops.

Transparent Access to I2P eepSites

My Debian router lets any device on my LAN open .i2p sites with no proxy settings, using Unbound for .i2p lookups, iptables and Privoxy feeding I2P.

Disk Caching with SSDs on Linux and Windows

My dual boot desktop puts SSD caches in front of a fakeRAID stripe: BCache on Linux, Intel Smart Response on Windows. Setup, pitfalls and hit rates.

2012 7 posts

↑ Top of page

FastMail.FM Security Vulnerabilities

XSS flaws I found in FastMail webmail: JavaScript in SVG attachments, a content type filter bypass and unescaped filenames, and the fixes I suggested.

Protecting Your GNU/Linux System from Dropbox

I run Dropbox as its own Linux user shared over Samba, then add AppArmor, disk quotas, iptables rules forcing its traffic over Tor, and EncFS for files.

New Version of The Email Privacy Tester

The Email Privacy Tester gets its own domain and GPL source, plus tests for video poster leaks in Android's mail app, K-9 and Hotmail, and read receipts.

Android Privacy Guard and Subkeys

APG wouldn't import GnuPG subkeys exported without the master key, so I forked it and removed the checks. How subkeys work and why I use them.

Smart Cards and SSH Authentication

I keep my SSH key on an OpenPGP smart card, using a GnuPG authentication subkey and gpg-agent on Linux, plus a pageant replacement for Putty on Windows.

Punching through The Great Firewall of T-Mobile

T-Mobile UK was injecting spoofed TCP RST packets to kill TLS SMTP and OpenVPN. Dropping RST packets with iptables at both ends got my VPN working again.

Extended Life Phone Batteries

Smart phones need charging every night. An extended life battery for about $15 can double that, with a bulging back cover. I use one in my HTC Desire Z.

2011 26 posts

↑ Top of page

TextSecure and the inPulse SmartWatch

I uninstalled TextSecure because it didn't work with my inPulse watch. Days later Twitter open sourced it, so I forked it and added basic watch support.

Understanding DNSSEC

How I set up DNSSEC on grepular.com with Bind: RRSIG, DNSKEY and DS records, KSKs and ZSKs, NSEC zone walking, key rollovers, and uses like SSHFP and DANE.

Defending Against Spear Phishing with Exim

EximPhishReplyBuster remembers the password a user logged in with and rejects outgoing mail containing it, so replies to phishing emails never leave.

Toughening up RequestPolicy

RequestPolicy lets clicked links and form submits through, leaving room for CSRF and clickjacking. I patched my copy to ask about every cross-site request.

Preventing Web Tracking via the Browser Cache

ETags, Last-Modified values, cached CSS and canvas-decoded images can all track you without cookies. I disabled Firefox's disk and memory cache to stop it.

View-Source URIs and RequestPolicy Bypass

A view-source: iframe got past RequestPolicy and loaded a page from another domain. It was fixed within hours of my report. Check your own URL parsing.

FireGPG on Firefox 5

FireGPG is discontinued and broke again with Firefox 5. A developer called bit has fixed it, and here is how to clone that fork into your Firefox profile.

Android Application Firewall: DroidWall

DroidWall on a rooted Android phone lets you pick which apps may use the network, separately for wifi and 3G, using iptables per-uid owner rules.

LastPass Vulnerability Exposes Account Details

A carriage return in an email parameter gave me XSS on lastpass.com, exposing a user's email address, password reminder, saved sites and login history.

When Third Party Email Providers Leak

Spam reached the address I gave only to BulkSMS. Unlike most companies, they investigated, changed email provider and set up honeypot addresses.

Automatically Encrypting all Incoming Email

gpgit, my Perl script that Exim runs as a transport filter, PGP encrypts every incoming email with my public key before it reaches my IMAP server.

2010 27 posts

↑ Top of page

New Year Bug in At Command

On Debian Lenny and Ubuntu, running 'at tomorrow' on 31 December 2010 scheduled the job for January 2012, a full year late. Check the date it reports.

Publishing PGP Keys in the DNS

A PKA TXT record at local_part._pka.domain holds your key's fingerprint and URL, and gpg with auto-key-locate will fetch it. No keyservers needed.

Using HTTPS Everywhere from Perl

I wrote a Perl module that applies the EFF's HTTPS Everywhere rulesets to URLs. It rewrites links on this site and powers a Squid redirector for my LAN.

Why Does this Website Generate SSL Warnings?

Why this site used a free CAcert certificate in 2010 despite browser warnings, why I resent paying CAs, and my hope for certificate fingerprints in DNSSEC.

Kik Messenger Insecure

Sniffing Kik with Wireshark showed unencrypted XMPP carrying usernames, plain text passwords and messages. Kik has since added SSL.

Why no Firesheep for IM?

With tcpdump I saw my MSN contacts' email addresses cross the network in plain text. ICQ, MSN and Yahoo send chats unencrypted. Use GTalk and OTR instead.

Tor Circuits with Two Hops on Ubuntu

Tor is slow with three hops. I patched DEFAULT_ROUTE_LEN and rebuilt the Debian package on Ubuntu Lucid for two-hop circuits, at some cost to anonymity.

Scalable Vector Graphics and XSS

SVG images can carry JavaScript, so sites displaying user uploaded SVGs are open to XSS. Workarounds, and a new SVG test in the Email Privacy Tester.

iOS 4 iPhone Email Privacy Leak

With 'Load Remote Images' off, iOS 4 Mail still follows dns-prefetch link tags, telling the sender when an email is read and which DNS servers you use.

Setting up IPv6 is Easier Than You Think

I gave my Linode VPS IPv6 through a free Hurricane Electric tunnel in minutes, then set up AAAA records, reverse DNS, mail, Apache and ip6tables.

DuckDuckGo Searches Are Not Anonymous

DuckDuckGo didn't log IPs, but favicons loaded from Amazon S3 leaked every search term in the Referer header. It was fixed two days after I posted.

Making BitTorrent Safe to Use Over Tor

Vuze falls back to direct connections when its SOCKS proxy fails. I forced Java through Tor, turned off DHT and UPnP and blocked UDP to stop IP leaks.

Extract Domains from Email Using Exim

Dropping SpamAssassin to save memory, I wrote a GPL Perl script that pulls domains out of message bodies so Exim can check them against RHSBLs.

DNSSEC Will Kill Commercial CAs

If a certificate hash could be published in a DNSSEC signed zone, domain owners could prove a self-generated cert is theirs without paying a commercial CA.

Use Random Passwords Which You Can't Remember

I stopped keeping an encrypted password file. I mash the keyboard for a random password, let the browser save it, and use the reset link if I need it.

Automated Email Privacy Tester

An online tool I built that emails you and reports which tracking callbacks your email client makes, after I found leaks in Apple Mail and others.

Android Email Information Leak

Android's stock IMAP client loads remote stylesheets and iframes in HTML email as soon as you open it, even with images off, telling the sender.

ClickJacking and SSL Protection in Apache

Adding Strict-Transport-Security and X-Frame-Options headers to my site with Apache mod_headers, after Google announced support for them in Chrome.

Android Battery Graphing Source Code

Source for my G1 battery graphing tool: the Java Android app that uploads battery status over HTTP and the Perl CGI that draws rrdtool graphs.

SpamAssassin 2010 Bug

On 1 January 2010 the FH_DATE_PAST_20XX rule started scoring every legitimate email 3.2 because of a bad regex. Here is the one-line local.cf fix I used.

2009 30 posts

↑ Top of page

JSAPI Incompatible with XSLT

Calling google.load for Google's language API blocks on pages built with client side XSLT. My workaround was a hidden iframe, and a horrible one at that.

Debenhams Fails at Sending Email

Debenhams' mail software choked on my multi-line SMTP banner, sent malformed MAIL FROM commands and was on several blacklists. Little of it got through.

JavaScript Comma Quirk

A trailing comma after the last item in an object literal is fine in Firefox but breaks Internet Explorer. It is a Perl habit I keep falling foul of.

Apache Forward Proxying with Compression

Squid wouldn't gzip responses over my slow 3G link, so I switched to Apache mod_proxy as a forward proxy with mod_deflate. Here is my config.

Compressing JavaScript on the Fly

A mod_perl output filter that minifies JavaScript on the fly with Google Closure Compiler, cached because the Java compiler is slow. 8.3KB became 4.5KB.

Compressing CSS on the Fly

I wrote a mod_perl output filter that minifies CSS as Apache serves it, using CSS::Minifier::XS, so there's no separate compressed copy to maintain.

Android Email Sucks

On my G1 it was quicker to SSH in and run mutt than wait for the Android email client. It is slow, lacks IMAP IDLE and got flaky after the 1.6 update.

Gumtree Rental Fraud

Four of six replies to Gumtree flat adverts came from 419 scammers in Lagos wanting Western Union receipts. Some simple ways Gumtree could stop it.

Apple Mail Privacy Hole

With remote images turned off, Apple Mail and the iPhone still loaded HTML5 video and audio tags, so senders could tell when I read their email.

Your Email Address Isn't Safe

Poundhost, Demon and Livejournal all leaked user email addresses in the same week of 2009. That is why I give every company its own address.

BBC Wrong About Mobile Broadband Speeds

The BBC ranked Three above T-Mobile for mobile broadband speed, though they share the same 3G network, and ignored latency, which matters more.

Poundhost vs RapidSwitch

Poundhost leaked its customer list by putting everyone in Cc on a marketing email. Within hours, competitor RapidSwitch emailed me a six months free offer.

Poundhost Data Storage

My experience of Poundhost's iSCSI storage with GFS and Red Hat Cluster Suite: cheap, about 8MB/s over 100Mb NICs, and no SLA without replication.

Trusting Replies to Trusted Email Messages

Exim records the Message-Id of mail I send in MySQL. Replies with a matching In-Reply-To header skip spam filtering, so whole threads become trusted.

Redirecting Pages through CGIProxy with Squid

I abused Squid's url_regex ACLs and deny_info to send requests for chosen sites through the CTunnel CGIProxy service, hiding my IP from those sites.

Detecting Bad ClamAV Signatures by Scanning Ham

After SaneSecurity listed 'com' as a bad domain, I set up a cron job that scans my read Inbox with ClamAV every 20 minutes to catch false positives early.

Automatically Expiring Email Addresses

An Exim ACL that accepts mail for addresses like 2009-Aug-03@tmp.grepular.com until that date, then rejects it. No new alias needed each time.

Accessing Memcached from Exim

Two Exim macros using the ${readsocket} expansion to set and get values in memcached from ACLs, with expiry, plus a bug in Debian Lenny's package.

Whitelist Recipients in Exim

Exim records every address my users send mail to in MySQL, using a stored function and two macros, then skips spam filtering for mail from those senders.

3G Network Latency Comparison

SSH over O2 and Orange 3G was frustratingly laggy for me, but on T-Mobile it felt like wired broadband. High latency is not a limitation of 3G itself.

Exim Client Authentication Recipe

Exim config that reads smart host IPs, logins and auth types from one file, then picks PLAIN, LOGIN or CRAM-MD5 and TLS for each host automatically.

Accessing Rejected Spam Solution

Exim still rejects spam at SMTP time, but fakereject and my pipe2imap script file a copy in each user's read-only IMAP Junk folder for a week.

Cross Browser Compatible XSLT

Apache BrowserMatch rules that send raw XML to browsers with client side XSLT and use mod_xslt for the rest. Later I gave up on the client side.

Mitigating Spear Phishing

At Loughborough University I wrote Kochi, a GPL Perl framework that blocks outgoing email containing working login details. It talks the ClamAV protocol.

Livejournal opt-out of Phorm

I emailed Livejournal about Phorm Webwise reading friends only posts, and their Director of Engineering had every subdomain added to the exclusion list.

Google Phone Battery Usage Graphing

A background service I wrote for my Android G1 uploads the battery level to my server, where RRDtool draws hourly, daily and weekly graphs of it.

Phorm - Webwise

BT's Phorm Webwise system profiles browsing for targeted adverts. Website owners can opt out by email; here is my request and Phorm's confirmation.

↑ Back to top