Articles

Go, Rust, Linux, cryptography and UK privacy law. One properly researched article a day.

Page 2 of 5. 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.

  1. Write Files Without a Cleanup Race with O_TMPFILE

    Linux's O_TMPFILE creates an unnamed inode, so failed writes vanish on close. Learn the Go syscall sequence for safe publication and durable files.

  2. Your Reverse Proxy Can Create More Connections Than Clients

    A reverse proxy can multiply sockets through HTTP/2 fan-out, retries and pools. Learn how to measure the real limits and cap them safely.

  3. When Can You Keep a User's Data After They Object?

    A practical UK GDPR guide to objections: when you must stop processing, when you can retain data, and why suppression is not erasure.

  4. Why a Blocking Call in an async Rust Task Stalls Other Requests

    One std::thread::sleep or sync file read in a Tokio task can freeze unrelated requests. See why it happens, how to reproduce it, and how to fix it.

  5. Your Analytics Pipeline Still Holds the IP You Dropped

    You strip the IP from the event payload, then find it in access logs, error lines, traces and queue headers. Here is how to hunt down each copy and remove it.

  6. Hashing User IDs Doesn't Make Your Analytics Anonymous

    Hashing a user ID does not anonymise it. Why pseudonymised analytics data stays personal data under UK GDPR, and what pseudonymisation does buy you.

  7. Why wg.Add Inside the Goroutine Lets Wait Return Early

    Calling sync.WaitGroup.Add from inside the goroutine it counts is a race that sometimes lets Wait return too soon. Here is why, and three safe fixes.

  8. Why Your Self-Hosted Matrix Server Leaks Who Talks to Whom

    Matrix encryption covers message text, not who is in a room, when they post or who read it. Here is what federation reveals and how to cut it.

  9. Why Your systemd Service Never Sees Your Shell's Variables

    A systemd service is started by PID 1, not your shell, so exported variables never reach it. Here is how to see its real environment and set it properly.

  10. Would an Interception Warrant Reach Your Self-Hosted Chat Server?

    A UK interception warrant can reach a hobby Matrix or XMPP server. Here is what it could demand, what it cannot, and what your server actually holds.

  11. Does a Smart Meter Reading Count as Access Under PECR?

    Regulation 6 of PECR covers access to information on a user's terminal equipment. Does a smart meter fit, and where do supplier reads land?

  12. Can a Journalist's Sources Survive an IPA Data Request?

    How the Investigatory Powers Act protects journalistic sources from communications data requests, where section 77 stops, and what metadata still gives away.

  13. Why Your Go Channel Close Panics Only Under Load

    A send on a closed channel panics only when a sender and a closer collide. Here is why load exposes it, and three fixes that remove the race.

  14. Why xargs Mangles Filenames with Spaces, and the -0 Fix

    xargs splits input on whitespace and treats quotes as special, so odd filenames break. See what goes wrong and how find -print0 with xargs -0 fixes it.

  15. Why tail -f Goes Silent After Log Rotation, and What -F Fixes

    tail -f follows a file descriptor, not a name, so rotation leaves it watching a dead file. Here is how -F, retry and copytruncate change that.

  16. When a Legitimate Interest Assessment Falls Apart

    A practical look at the purpose, necessity and balancing tests, and the warning signs that turn a legitimate interest assessment into paperwork.

  17. Why Reusing a Signing Key for Encryption Breaks Both

    One keypair for signing and decrypting looks tidy, but a decryption oracle can become a signing oracle. Here is how, and how to derive separate keys in Go.

  18. Restoring a Backup Brings Back the Users You Deleted

    Restoring a backup resurrects users you deleted. Here is how a deletion ledger, replayed after every restore, keeps erased people erased.

  19. A Backup You Have Never Restored Is a Hope, Not a Backup

    A restore drill for self-hosted services: what to restore, what to verify, and the failures it finds that green backup logs never show.

  20. Shutdown Doesn't Hang on Hijacked Connections, Your Code Does

    http.Server.Shutdown ignores hijacked connections rather than waiting on them. Here is where a shutdown hang really comes from, and a bounded pattern.

  21. Why Your Go TCP Server Needs a Connection Cap First

    Goroutines are cheap, but sockets, buffers and file descriptors are not. Add a connection cap to a Go TCP server with a small stdlib listener wrapper.

  22. Why a Go Slice Append Sometimes Changes Your Other Slice

    Two Go slices can share one backing array, so append may overwrite the other. See when it happens, how to spot it, and three ways to stop it.

  23. Why Your Shell History Is a Secrets Leak, and How to Stop It

    Tokens and passwords pasted into commands end up in plain text history files. Here is how to find them, stop new ones landing, and what the fixes miss.

  24. Why a Forensic Timeline Lies When File Timestamps Get Copied

    Copying files with cp -p, rsync or tar keeps the old modified time but stamps new change and birth times. Here is how that skews a timeline and how to spot it.

  25. Why Encrypting Your Backups Is Not the Same as Encrypting Them Well

    A backup can be encrypted and still be tampered with, leak its structure or be impossible to restore. Five failure modes and what a well-built backup does.

  26. Why Your Go Web Server Needs a Body Limit Before a Router

    Go's net/http reads request bodies without any size cap by default. Here is how to set one with MaxBytesHandler, and where forms, multipart and gzip bite.

  27. Vec Reallocation Can't Dangle a Reference in Safe Rust

    push can move a Vec's whole buffer, yet safe Rust never lets you read the old one. See how the borrow checker blocks it, and what unsafe code must do instead.

  28. Why Let's Encrypt Renewal Fails After a Port 80 Redirect Change

    Certbot renewals can work for months, then fail after a redirect change on port 80. How HTTP-01 follows redirects, and how to test it.

  29. What the DPA 2018 Does with Criminal-Offence Data

    A practical guide to Article 10, Schedule 1 and the DPA 2018 rules for criminal-offence data, including allegations, checks, safeguards and retention.

  30. Why a Federated Server Can't Delete Your Post from Everyone Else's

    Deleting a post on Mastodon or any ActivityPub server sends a polite request, not a command. Here is what that request contains, and where copies survive.

  31. Threat Modelling a Webhook Receiver Before You Write the Handler

    A webhook endpoint is a public URL that trusts strangers. Work through spoofing, replay, floods and retries first, then see the small Go handler that falls out.

  32. What an Interception Warrant Can Make a Telecoms Operator Do

    What an Investigatory Powers Act 2016 interception warrant can demand of a UK telecoms operator, what it can't, and where encryption fits in.

  33. What a Bulk Personal Dataset Warrant Lets the Agencies Keep

    Part 7 of the Investigatory Powers Act lets MI5, MI6 and GCHQ hold datasets on mostly innocent people. Here is what the warrant covers and what limits it.

  34. Yes, Your Security Logs Can Be Part of a SAR

    Security logs can contain your personal data. Learn when a UK SAR may include them, what can be redacted, and how to ask precisely.

  35. Does Your Server-Side Session Cookie Need a PECR Consent Banner?

    Keeping session state on the server doesn't remove the cookie. Here is when PECR's strictly necessary exemption covers a session ID, and when it stops.

  36. Why Your Daemon Keeps a Zombie Child Until You Call wait()

    Defunct processes pile up when a parent never calls wait(). See what the kernel keeps, how to reproduce it in Go, and how to fix it, including in containers.

  37. Your Browser Can Leak More Than Your IP Address

    Your browser exposes clues about your device, network and habits. Learn what leaks, who can see it, and how to reduce the signal.

  38. Why Your TOTP Codes Stop Working When the Server Clock Drifts

    TOTP is only a hash of the time. See how a skewed server clock rejects correct codes, how to diagnose it, and how to log drift and widen the window safely.

  39. Can Your Employer Read Your Work WhatsApp Under UK GDPR?

    When an employer can lawfully read work WhatsApp messages in the UK: UK GDPR, the Investigatory Powers Act, Article 8 case law, and why the device matters.

  40. epoll Said Readable, Then read() Blocked: Four Ways That Happens

    epoll reports a hint, not a promise. Four ways a ready socket still blocks on read(), accept() or write(), and the one habit that fixes all of them.

  41. Why a Go TCP Echo Server Stalls at 10,000 Clients, Not 10

    A goroutine per connection scales fine in Go. What stalls at 10,000 clients is the accept loop, the listen backlog and file descriptors. Here is how to tell.

  42. Serving 10,000 Static Pages from Go with Only net/http

    Yes, net/http alone can serve 10,000 static pages. Here is the 30-line server, what the standard library does for free, and the traps to avoid.

  43. Envelope Encryption in Go Without a Cloud KMS

    Wrap per-record data keys with a master key using only Go's standard library, then rotate that master key without re-encrypting a single byte of data.

  44. Why Your CLI's Exit Code Is Always 0 After a Pipe

    A shell pipeline reports only its last command's status. See how pipefail and PIPESTATUS expose hidden failures, and where pipefail bites back.

  45. Why an ESP8266 Forgets Its WiFi Channel Every Deep Sleep

    An ESP8266 wakes from deep sleep as a fresh boot with no WiFi state. Cache the channel and BSSID in RTC memory to skip the scan and save battery.

  46. Why Encrypting a File with AES-CBC Still Needs a MAC in Rust

    AES-CBC hides your file's contents but not whether someone altered it. See a one-byte tamper in Rust, then fix it with encrypt-then-MAC using HMAC-SHA256.

  47. Why Deleting a Running Binary Doesn't Crash It

    rm on a running program works fine, but overwriting it fails with 'Text file busy'. Inodes, link counts and the kernel's references explain both.

  48. Your Password Reset Link Is a Backdoor: Threat Model It

    A reset link is a password-equivalent bearer token sent over email. Here is how to threat model it: guessing, leaks, scanners, host headers and MFA bypass.

  49. Find the Deleted File That Is Filling Your Disk

    Your disk is full, but du cannot find the missing gigabytes. Track open deleted files with lsof, /proc, and a safe service restart.

  50. Can the UK Make You Hand Over Your Encryption Key?

    RIPA Part III lets police demand keys or plaintext, with prison for refusing. Here is how section 49 notices work, and what the courts have said.