Blog
Go, Rust, Linux, cryptography and UK privacy law. One properly researched article a day.
Working notes from a software engineer who spends the day in Go, Rust and Linux and the evening reading legislation. Each post takes one specific question and answers it properly: why a worker pool deadlocks, what fsync really promises, how to enrol a TPM into LUKS without locking yourself out, what a technical capability notice can actually compel. Step-by-step how-tos sit alongside the deep dives, everything is checked against source code or primary legislation, and nothing is padded to hit a word count.
Subscribe with the Atom feed to get each post as it lands.
-
How Go's log/slog package gives you structured, leveled logging with context propagation, without adding zap or zerolog to go.mod.
-
Why a Go service can be OOM-killed inside a memory-limited container despite having a garbage collector, and how GOMEMLIMIT fixes the pacing.
-
Why bit-for-bit disk imaging with dd, a write blocker and a SHA-256 checksum beats a filesystem copy when acquiring a drive for forensic analysis.
-
Learn why io.Copy can partially mutate a destination before failing, how its byte count helps, and when to stage writes for an atomic result.
-
How the six digits in your authenticator app are actually produced: HMAC-SHA1, dynamic truncation and time steps, built in plain Go.
-
RFC 8628 explained: how tools like gh, docker and kubectl authenticate on headless machines by polling a token endpoint instead of a browser redirect.
-
How golang.org/x/sync/errgroup collects errors, cancels sibling goroutines on first failure, and bounds concurrency without a semaphore channel.
-
How errors.Join builds a tree of errors that still works with errors.Is and errors.As, and where the abstraction leaks.
-
A step-by-step guide to configuring SPF, DKIM and DMARC for a self-hosted mail server, and why the DNS records alone will not stop spam folders.
-
How Shamir's Secret Sharing splits a key into shares using polynomial interpolation over GF(256), with a working Go implementation.
-
Ofcom's 'highly effective' age assurance rests on four criteria, not a fixed toolset, and 2026 enforcement shows what that means for real services.
-
TLS 1.3 still leaks the hostname you're connecting to in plaintext. Here's how Encrypted Client Hello fixes that, and where it still falls short.
-
How to build and install a seccomp-bpf syscall filter from a plain Go binary with golang.org/x/net/bpf, and why goroutines need the TSYNC flag.
-
A status check on the UK-US Data Bridge: PCLOB's quorum collapse, the Latombe appeal at the CJEU, and the UK's own EU adequacy renewal.
-
How Go 1.25's testing/synctest package lets you test timers, retries and debounce logic deterministically, without real time.Sleep calls.
-
A walk through golang.org/x/time/rate's actual source to see how Go's token bucket limiter tracks tokens without a background goroutine.
-
Learn how Linux pidfds provide a stable handle for polling, signalling and waiting without accidentally targeting a reused PID.
-
Why Go's generics compiler rejects structs containing slices as comparable, the reasoning behind it, and how to work around it.
-
Why UK GDPR's right to erasure doesn't mean scrubbing every backup tape immediately, and what the ICO actually expects organisations to do instead.
-
The Computer Misuse Act has no good-faith defence, so a pentest's legality rests entirely on paperwork. Here's what that paperwork actually needs to say.
-
Why sync.Map only wins for two specific access patterns, how Go 1.24's trie-based rewrite changed the numbers, and when a plain mutex wins instead.
-
Deep sleep current specs look great on paper, but wake-up current spikes and a board's regulator usually decide the real battery life.
-
How to use Postgres advisory locks from Go for cron dedup and leader election, and the connection-pooling pitfall that breaks them silently.
-
Why TLS 1.3's post-quantum key exchange combines ML-KEM with ECDHE instead of replacing it, and what that costs in handshake size.
-
Starlink and most 4G home routers hide you behind CGNAT, so port forwarding does nothing. Here's how a reverse WireGuard tunnel fixes it.
-
How a reused ECDSA nonce leaks a private key, why Sony and Android wallets fell to it, and how Ed25519 designs the whole bug class out.
-
Why stock Flipper Zero firmware cannot scan or connect over BLE, the three patches that unlock the full stack, and how to drive it from your own app.
-
Closing a Go HTTP response body prevents leaks, but HTTP/1 connection reuse depends on reaching EOF. Learn when to drain, cap or abandon a body.
-
How range-over-func actually compiles in Go 1.23, why non-local control flow needs hidden state, and where iter.Seq stops being free.
-
encoding/json ignores JSON fields it doesn't recognise by default. DisallowUnknownFields turns that into an error, but only if you use it correctly.
-
Why compiling an async fn into a state machine makes the result self-referential, and how Rust's Pin type stops the compiler from moving it unsafely.
-
Why tokio::sync::mpsc suspends a task while std::sync::mpsc blocks an OS thread, and why mixing the two on one runtime causes stalls.
-
Learn which Go HTTP timeouts cover slow headers, request bodies and keep-alive gaps, and which mistakes leave connections exposed.
-
How a select loop that calls time.After every iteration quietly piles up timers on old Go, and why Go 1.23 changed the rules.
-
A Go worker pool that deadlocks under load, traced back to an unbuffered results channel, with the fix and why bigger buffers only postpone the problem.
-
A walkthrough of sshd_config's KexAlgorithms, Ciphers and MACs directives: what to strip out, why, and how to verify the change without locking yourself out.
-
sync.Once does not retry after f() panics: it quietly marks itself done, while OnceValue re-panics forever. Verified against the Go source.
-
Certificate Transparency Logs: What They Actually Prove About a TLS Certificate, and What They Don't
CT logs make TLS certificate issuance publicly auditable, but they do not validate domain control, check revocation or stop mis-issuance. The actual guarantee.
-
Create, enrol and maintain your own UEFI Secure Boot signing keys on Linux with sbctl, without turning the next reboot into a recovery exercise.
-
Rust has no async destructor, and it isn't an oversight. Why Drop::drop can't await, and the spawn/block_on/explicit-close patterns people use instead.
-
A single %v where you meant %w compiles cleanly and passes go vet, but it quietly severs the error chain that errors.Is depends on.
-
Configure BorgBackup with a server-enforced append-only repository, so a compromised client can add backups but never delete or rewrite them.
-
A Go service capped at 0.5 CPU in Kubernetes still spins up dozens of OS threads and gets throttled. Why GOMAXPROCS cannot see the limit, and how to fix it.
-
The DPA 2018 exemptions that let organisations lawfully redact a subject access request, and the patterns of overreach that turn a redaction into a breach.
-
A step-by-step guide to embedding a minimal Dropbear SSH server in initramfs so you can type a LUKS passphrase over the network on a headless server reboot.
-
Binding to port 80 as a non-root Go process without setuid tricks, using Linux capabilities, CAP_NET_BIND_SERVICE, setcap and systemd's AmbientCapabilities.
-
bcrypt silently ignores everything past the 72nd byte of a password. Why the limit exists, how it produces real collisions, and how to handle it properly in Go.
-
A practical guide to generating resident FIDO2 SSH keys with ssh-keygen, setting a PIN, and recovering the credential onto a new machine with ssh-keygen -K.
-
Comparing a computed HMAC with == looks correct and compiles fine, but it leaks timing information an attacker can use to forge a valid MAC byte by byte.
-
How SCM_RIGHTS lets one Unix process hand an open file descriptor to another, with a working Go example and a look at where systemd genuinely uses it.
Page 1 of 2
Older posts →