Shellsharks Blogroll - BlogFlock2026-04-11T14:57:43.240ZBlogFlockdestructured, fLaMEd, Trail of Bits Blog, Aaron Parecki, Evan Boehs, James' Coffee Blog, Westenberg, gynvael.coldwind//vx.log (pl), joelchrono, Kev Quirk, cool-as-heck, Posts feed, Sophie Koonin, Adepts of 0xCC, <span>Songs</span> on the Security of Networks, cmdr-nova@internet:~$, Johnny.Decimal, Werd I/O, Robb Knight, Molly White, Hey, it's Jason!, Terence Eden’s BlogCheapest way to keep a UK mobile number using an eSIM - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=691402026-04-11T11:34:38.000Z<p>I have an old mobile phone number that I'd like to keep. I <em>think</em> it is registered with a bunch of services for 2FA by SMS, but I can't be sure. So I want to keep it for a couple of years just in case I need it to log on to something.</p>
<p>I don't want to faff around with physical SIMs, so I went looking for the <em>cheapest</em> way to keep my number for the longest time. There are a whole bunch of providers out there who will do low-cost <em>monthly</em> contracts (like Spusu), which I don't want. Similarly, there are some pure PAYG providers who require you to top-up with £10 every few months (like 1pmobile).</p>
<p>In the end, I went with <a href="https://aklam.io/yJrzBWhD">Lyca Mobile</a> (affiliate link). Total cost was £10 which should last indefinitely.</p>
<p>The process isn't particularly straightforward. Here's how it works:</p>
<p>First, add a PAYG SIM to your basket and select "eSIM"</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/03/Add-to-basket.webp" alt="Screen with a £6 SIM in the basket." width="1400" height="900" class="aligncenter size-full wp-image-69143"/>
<p>Next, click the Bin icon (🗑) in the top right. You'll get this pop-up:</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/03/Discard.webp" alt="Screen saying are you sure and offering other choices." width="1400" height="1000" class="aligncenter size-full wp-image-69142"/>
<p>Select "Discard plan & add credit" - you'll return to this screen:</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/03/Add-top-up.webp" alt="A screen letting you add a top up." width="1400" height="974" class="aligncenter size-full wp-image-69141"/>
<p>The minimum top-up is a tenner, so select that. From there, you can add details of your old number, its porting code, and when you want the port to take place. Then pay.</p>
<p>Done! You'll receive your eSIM instantly. Scan it with your phone and you'll be up and running. The phone number porting will take as long as it takes.</p>
<p>OK, but will Lyca let you keep a number indefinitely? Here's what they say:</p>
<blockquote><h2 id="how-long-can-i-keep-my-number-for-if-i-dont-use-any-of-lyca-mobiles-services"><a href="https://shkspr.mobi/blog/2026/04/cheapest-way-to-keep-a-uk-mobile-number-using-an-esim/#how-long-can-i-keep-my-number-for-if-i-dont-use-any-of-lyca-mobiles-services">How long can I keep my number for if I don’t use any of Lyca Mobile’s services?</a></h2>
<p>Normally we will keep your number for 120 days if you do not use our service. However, you may also keep your Lycamobile number for up to 1 year without using our service. Just dial <code>*139*9999#</code> from your Lycamobile and follow the instructions on the screen. Please be aware that there will be a fixed annual fee of £15 which will be deducted from your balance.</p>
<p><a href="https://www.lycamobile.co.uk/en/general/how-long-can-i-keep-my-number-for-if-i-dont-use-any-of-lycamobiles-services/">Source</a></p></blockquote>
<p>Note, their chatbot says the fixed fee is a fiver. Like all half-baked AI systems, it is wrong.</p>
<p>So, what does "using" consist of? This is hard to find out! I <em>think</em> is any chargeable event. Based on their <a href="https://www.lycamobile.co.uk/en/rates/national/#prepaid">current PAYG pricing</a> the cheapest options are:</p>
<ul>
<li>Send an SMS for 23p</li>
<li>Use 1MB of data for 15p.</li>
</ul>
<p>If I'm right, you could use 1MB of data every 120 days. That would deplete your credit in about 22 years. More than long enough for me!</p>
<p>There you have it, I'm pretty sure that's the cheapest way to keep a UK mobile number on an eSIM. You can keep it switched off for 119 days, flick it on, send a quick message, then shut it down again.</p>
<p>Click the referral link to <a href="https://aklam.io/yJrzBWhD">join Lyca Mobile</a></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=69140&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>What Interested Me Today 7 - Joel's Log Fileshttps://joelchrono.xyz/blog/what-interested-me-today-72026-04-10T15:40:00.000Z<p>I am currently working on my review for <em>Resident Evil</em>, but I need to take some pictures and finish it up a little more! So far I tend to separate everything into the basics, art, gameplay, story, music and stuff; but I ended up turning this post into more of a retrospective about survival horror as a whole and bringing up the Romero movies and talking about the FMVs and other things and, basically it’s a work in progress and the kind of thing I could make into a video essay if I put more effort into it, so it’s not ready.</p>
<p>For now, this is a quick post about <strong>what interested me today!</strong> I have been thinking about renaming this not-very-official—since it doesn’t even have a tag yet—series, to include what’s actually in it—similar to how my weeknotes are not just titled “Weeknotes”, more like Andreas’ <a href="https://82mhz.net/posts/#Linkdumps">Linkdumps</a>, I guess this is the same thing.</p>
<h2 id="some-blogs-i-added-to-my-rss-feed">Some blogs I added to my RSS feed</h2>
<ul>
<li>
<p>I have followed and enjoyed <a href="https://brandons-journal.com">Brandon’s Journal</a> for a while, but during a short hiatus where he took it down, I ended up removing it from my FreshRSS feed. I realized when he returned months ago, but I forgot to add him back, that mistake has been corrected. Here’s a <a href="https://brandons-journal.com/post/just-write">short post</a> to get a taste for his writing!</p>
</li>
<li>
<p><a href="https://chameth.com/">Chris Smith’s</a> website was not on my radar at all, but I often like to check who links back to me and noticed that he mentioned me on his <a href="https://chameth.com/monthly-meanderings-2026-03/">monthly meanderings</a>, where he appreciated the way I link back to posts I reply to, etc. In any case, I really liked the design and the fact he has a section for all his <a href="https://chameth.com/boardgames/">board games</a>.</p>
</li>
<li>
<p>Last but not least! <a href="https://marmar22.tilde.team/">marmar22</a> was a fun find. I can’t recall where I found their site, I believe I was just looking for some ereader blogposts somewhere because I stumbled upon <a href="https://marmar22.tilde.team/blog/a-review-of-a-cheap-e-reader-because-i-bought-one.html">this review</a> of some no brand ereader. The posts about <a href="https://marmar22.tilde.team/blog/organising-my-photos.html">organising photos</a> felt kind of familiar as well.</p>
</li>
</ul>
<p>So yeah! I won’t say I’ll read everything but it’s always fun to have more variety. As I write this there are 6689 unread articles on my FreshRSS instance…</p>
<h2 id="a-dumb-web-fediverse-client">A dumb web fediverse client</h2>
<p>There are a lot of clients for the fediverse, from apps to terminals to web clients. Personally I mostly stick to the default web interface and to <a href="https://tusky.app">Tusky</a> on my phone.</p>
<p>But <a href="https://social.pollux.casa/@adele">Adele</a> recently created a minimal web client that doesn’t rely on javascript and can run on ancient browsers and devices! She wrote a <a href="https://adele.pages.casa/md/blog/the-fediverse-deserves-a-dumb-graphical-client.md">blogpost announcing it</a>.</p>
<h2 id="into-the-aethers-latest-bonus-episode">Into The Aether’s latest bonus episode!</h2>
<p>I you like the <strong>Persona</strong> games, you may be up to listening to a 5+ hours long deep dive into <a href="https://intothecast.transistor.fm/episodes/persona-4-golden-bonus-episode"><em>Personal 4 Golden</em></a>, treat yourself and get into my favorite podcast of all time!</p>
<p>Personally, I’m skipping it until I play that series, more than happy to listen to their weekly episode, the <a href="https://intothecast.transistor.fm/episodes/daruni-os-they-rock-feat-zelda-ocarina-of-time-fire-emblem-advance-wars-and-cairn">latest</a> of which also talks about the rumours around a remake of <em>The Legend of Zelda: Ocarina of Time</em> for the Nintendo Switch 2. This may make me buy that console at last, no doubt.</p>
<h2 id="linux-user-groups-and-updating-my-xteink-x4">Linux user groups and updating my XTEINK X4</h2>
<p>I noticed that <a href="https://github.com/crosspoint-reader/crosspoint-reader">Crosspoint</a>, the firmware I use on my <a href="https://joelchrono.xyz/blog/early-days-with-xteink-x4/">XTEINK X4</a> recently had an update to 1.2 which introduced a couple features like a built-in EPUB optimizer, a way to turn text in current page to a QR code, and other goodies.</p>
<p>Last time I mentioned how I had to use my dad’s laptop to flash the firmware due to missing permissions. This time I took the time to figure things out and realized that I simply had to add my user to the <code class="language-plaintext highlighter-rouge">uucp</code> linux group. After restarting my user session things went smoothly from there! A shame I need to use Chromium to run the <a href="https://xteink.dev.al">web installer</a> though.</p>
<h2 id="another-ttrpg-bundle">Another TTRPG bundle…</h2>
<p>There’s a <a href="https://www.humblebundle.com/books/pathfinder-second-edition-bundle-at-center-world-paizo-inc-books">Pathfinder Humble Bundle</a> going on right now and my TTRPG friends are making me consider it yet again. I haven’t even had a second session of <em>Land of Eem</em> yet, but things happen.</p>
<p>In any case, this bit is just to let you know, and tempt you to get it as well.</p>
<p>
<a href="mailto:me@joelchrono.xyz?subject=What Interested Me Today 7">Reply to this post via email</a> |
<a href="https://fosstodon.org/@joel/116381205791884381">Reply on Fediverse</a>
</p>I've Completed 100 Days To Offload (Again) - Kev Quirkhttps://kevquirk.com/ive-completed-100-days-to-offload-again2026-04-10T15:33:00.000Z
<p>I just published my <a href="https://kevquirk.com/motorbike-servicing-rant">motorbike servicing rant</a> and went over to my <a href="https://pureblog.org/dashboard-stats">Pure Blog Dashboard</a> to take a look at some stats, when I noticed this:</p>
<p><img src="https://kevquirk.com/content/images/ive-completed-100-days-to-offload-again/100-days.webp" alt="100 days" /></p>
<p>101 posts in the last year; which means I've complete <a href="https://100daystooffload.com">100 Days to Offload</a> for a second time! 🎉</p>
<blockquote>
<p>The whole point of the <code>#100DaysToOffload</code> is to challenge you to publish 100 posts on your personal blog in a year.</p>
</blockquote>
<p>Mission accomplished! If you're interested in taking part in the challenge too, make sure you <a href="https://100daystooffload.com/#-hall-of-fame-">get yourself added to the hall of fame</a> once you've completed it.</p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=I%27ve%20Completed%20100%20Days%20To%20Offload%20%28Again%29">reply to this post by email</a>, or <a href="https://kevquirk.com/ive-completed-100-days-to-offload-again#comments">leave a comment</a>.</p>
</div>
Motorbike Servicing Rant - Kev Quirkhttps://kevquirk.com/motorbike-servicing-rant2026-04-10T15:11:00.000Z
<p>So my BMW S1000XR is now a year old and it's going in for its first <em>"full service"</em>. It had it's "break in" service after a few weeks of ownership, but that's just an oil change.</p>
<p class="notice tip">New bikes come with a very thin oil inside the engine that's used to help with the break-in process. After 500 or so miles, this needs to be swapped out for proper oil.</p>
<p>I contacted the dealership for a price and some potential dates, this is the breakdown they came back with:</p>
<ul>
<li>Labour - £150</li>
<li>Oil disposal - £20</li>
<li>Oil - £80.60</li>
<li>Sump plug washer - £0.96</li>
<li>Oil filter - £17.29</li>
<li>Brake fluid - £11.92</li>
<li>Tax @ 20% - £56.15</li>
<li><strong>Total: £336.92 (~$455)</strong></li>
</ul>
<p>So nearly £350 for what's effectively an hour's work and around £50 in parts. I'm mechanically minded and could <em>easily</em> do this at home, but like most modern vehicles, my BMW doesn't come with a service book that is stamped. These days the service history is all stored centrally with BMW, so means that the service <em>has</em> to be carried out by them.</p>
<p>Brilliant.</p>
<p>There is a misconception that home servicing will void the warranty of a new bike. <strong>It won't</strong> as long as the person doing the service uses OEM parts and has done it to manufacturers specification - which I always do. But I bought this bike from BMW, so if I hand it back after 3 years with a generic eBay service book that's been stamped by me, even though it's been done to a high standard, it <em>will</em> affect the trade-in value.</p>
<p>Ipso facto, they have me by the balls.</p>
<p>I get it, margins are small and this is how dealerships make money, but I wish they would make it accessible for mechanically minded people, like me, to service at home.</p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=Motorbike%20Servicing%20Rant">reply to this post by email</a>, or <a href="https://kevquirk.com/motorbike-servicing-rant#comments">leave a comment</a>.</p>
</div>
[RSS Club] Why do you use RSS rather than Atom? - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=702572026-04-10T11:34:36.000Z<p><mark>This post is exclusive to feed subscribers. Enjoy!</mark></p>
<p>This whole experiment is called <a href="https://daverupert.com/rss-club/">RSS Club</a> - but perhaps it should be called "XML-based distributed feed club"?</p>
<p>I've been playing about with <a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/">local-only and privacy-conscious view tracking</a>. I can see how many people click on my stories from HN or Google or anywhere else. I also decided to add the number of times a story is viewed by someone reading via feeds - like you!</p>
<p>Here's a typical day of page views:</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/Atom-v-RSS.webp" alt="Screenshot showing 596 Atom views vs 492 RSS views." width="440" height="200" class="aligncenter size-full wp-image-70258"/>
<p>First of all, I'm staggered that so many of you read this via feeds! Hurrah! And I'm amazed that I get more readers via feeds than Google. Every member of this secret RSS club is awesome 😘</p>
<p>When I originally set up this blog, it only supported RSS. At some point, WordPress added the more modern Atom feed format. Both get full support from me. But I'm wondering why so many people are still on RSS rather than Atom? Are there clients which don't support Atom? Is it just a legacy thing?</p>
<p>Should I redirect the RSS feed to the Atom feed or would that break things for you?</p>
<p>If you have any strong views on RSS 🆚 Atom, please <a href="https://edent.tel/">drop me a comment via your favourite method</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70257&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>Why I quit "The Strive" - Westenberg69d85619a6dac40001e933222026-04-10T01:50:12.000Z<div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal " data-layout="minimal">
<div class="kg-cta-content">
<div class="kg-cta-content-inner">
<div class="kg-cta-text">
<img src="https://images.unsplash.com/photo-1729949129263-b7a563d1f5fd?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE3fHxtYXRjaHN0aWNrc3xlbnwwfHx8fDE3NzU3ODU2Nzh8MA&ixlib=rb-4.1.0&q=80&w=2000" alt="Why I quit "The Strive""><p><span style="white-space: pre-wrap;">This newsletter is free to read, and it’ll stay that way. But if you want more - extra posts each month, no sponsored CTAs, access to the community, and a direct line to ask me things - paid subscriptions are $2.50/month. A lot of people have told me it’s worth it. </span></p>
</div>
<a href="https://www.joanwestenberg.com/#/portal/signup/69328a08ef56a90001ae60df/monthly" class="kg-cta-button " style="background-color: #000000; color: #ffffff;">
Upgrade
</a>
</div>
</div>
</div><p>I spent about a decade waking up at 6am and checking my follower count before I brushed my teeth. Refreshing analytics while the coffee brewed, reading Y Combinator essays, networking on Twitter and trying to reverse-engineer what made people break out. I'd look at every piece of creative work I produced and ask "will this scale?" Every night, I'd calculate the gap between where I was and where Mark Zuckerberg was at my age, or Marc Andreessen, or Om Malik, or Ryan Holiday etc etc etc - which is an unhinged thing to do.</p><p>But I did it all the time.</p><p>I was obsessed with whatever it was that would come Next. After all of this, after I had made it, after I'd stopped "plateauing" and reached my potential.</p><p>This is what I've come to call The Strive.</p><p>And you know it too, even if you've never called it that. It's the obsession with making it, going viral, founding a billion-dollar company, becoming the next TBPN, raising millions of dollars, getting profiled in Wired, landing on the Forbes 30 Under 30 list (or, for those of us who aged out, the Forbes 40 Under 40 list that doesn't exist but should). The Strive is what makes people put "serial entrepreneur" in their Twitter bio. It's what makes a 24-year-old describe their note-taking app as "disrupting knowledge work." It's what kept me awake at 2am calculating how many followers I needed per week to hit my Q3 growth target.</p><p>Back in the 70's a researcher named Philip Brickman studied lottery winners and found that people who won big were no happier than anyone else within a few months. He called it the "hedonic treadmill." You get the thing, the feeling fades, you chase the next thing.</p><p>The Strive is the hedonic treadmill all over again, but it comes with a mandatory pair of white sneakers and a Claude Max subscription.</p><h2 id="how-the-machine-works">How the machine works</h2><p>From the outside, The Strive it looks like that thing we call passion; but from the inside it feels like a crushing, soul destroying anxiety disorder.</p><p>You set a goal, and with a bit of luck and a whole lot of blood, you hit it, and you feel good for somewhere between 4 hours and 2 days (and I'm being generous with the 2 days), and then it fades and you set a bigger goal because the old one, the one you were sure would change everything, turned out to be a thing that happened and nothing more.</p><p>I hit 10,000 followers once and felt good for about an afternoon, and I got published in an outlet I'd been pitching for months and the dopamine lasted maybe 36 hours before I was back at my laptop, pitching the next thing.</p><p>Your brain's ~wanting system and your brain's ~liking system are separate circuits, and the wanting system is bigger and louder and more connected to everything else.</p><p>As it turns out, dopamine fires for the chase, not for the catch.</p><h2 id="infrastructure">Infrastructure</h2><p>The Strive doesn't live in your head alone - no, it has infrastructure. It has an entire litany of podcasts, and conferences, Twitter threads, and LinkedIn posts, co-working spaces, and pitch competitions, and all of it keeps you sprinting.</p><p>Everyone around you is Striving, too. And when you stop, you feel like you're falling behind. But falling behind who? People who are also on the treadmill, also wondering why their last win didn't stick?</p><p>Once you're in it, opting out feels like abject failure. If you're not growing, you must be dying, if you're content, you must be complacent. Peace and satisfaction are a disease that infests the uninitiated.</p><p>Well, I went to the events and read the books (the ones with single-word titles like "Grit" and "Hustle") and optimised my mornings and tracked my habits with an app that gave me a score, and I tweeted through it, and I cold-emailed strangers to ask if I could "pick their brain," which is a phrase that should be fucking illegal.</p><p>It got me nowhere.</p><h2 id="what-it-costs">What it costs</h2><p>You're told to calculate the upside: money, status, influence. You're told to weigh that against the "sacrifice," which is always framed as temporary. Grind for a few years, miss some dinners, put some relationships on hold. There's a finish line out there and once you cross it you get to enjoy things.</p><p>But this is bullshit! There's no finish line! That's the trick, and it's a damned good one!</p><p>I watched a friend raise a Series A and immediately start losing sleep over Series B. I know someone who hit a million in annual revenue and couldn't enjoy it because all he could think about was getting to 10. Every finish line is a checkpoint. You cross it and the next one appears, further away, higher up. This is intentional design.</p><p>What The Strive actually cost me was a large number of physical years. Years I spent optimising instead of living, years I spent going to networking events instead of seeing friends, building an audience when I could have been reading a book for fun. I worked on things that were always about to become The Thing that Mattered, and they never quite did. And even if they had, it wouldn't have been enough. It would never, ever have been enough.</p><h2 id="enough">Enough</h2><p>What if the right scale for interesting work is whatever scale that lets you keep doing it? What if a good idea doesn't need to become a billion-dollar company? What if it can be a good idea that you work on because it's interesting and it pays your rent?</p><p>Kahneman and Deaton published a study in 2010 showing that after about $75,000 a year (probably closer to $100,000 now), more money doesn't make your day-to-day life feel any better. Your abstract "life satisfaction" might tick up, but the actual texture of your days doesn't change.</p><p>You can't ask "how much is enough?" inside The Strive's framework because "enough" is a word it doesn't recognise.</p><p>I run a solo creative studio called <a href="https://www.thisisstudioself.com/?ref=joanwestenberg.com" rel="noreferrer">Studio Self.</a> I write things I love writing. I work with clients I actually like. I pick projects that challenge my brain in ways I find interesting and I turn down the ones that don't. I am not optimising for maximum revenue. I am not building a unicorn. I am unlikely to go down in history.</p><p>By The Strive's metrics, I'm a failure. I should be raising money. I should be building a team. I should be positioning for an exit. Instead I'm writing a blog and reading comic books and playing Doom II and working on ideas that will almost certainly never make anyone a billion dollars, and I'm fine with that. Better than fine. I wake up and I'm not dreading the day. I work on things I care about. I stop working when I'm done. My brain feels alive and I have time to read for fun and I think that's worth more than a Series A.</p><h2 id="the-mash-test">The MASH test</h2><p>The Strive doesn't believe in hobbies. In its twisted framework, everything is either productive or wasteful. Reading a comic book: wasteful. Reading a business book: productive. Playing a video game: wasteful. Building one: productive. It can't process the idea that you might do something because you enjoy it. Every hour has to be an investment. Every experience has to compound.</p><p>That is a psychotic way to live. I mean that close to literally. It's a disconnection from the basic human experience of enjoying things because they're enjoyable. A 6-year-old knows you read a book because it's fun. The Strive beats that out of you and replaces it with a spreadsheet.</p><p>I have a test for whether The Strive still owns you, and I call it the MASH test. MASH ran for 11 seasons, from 1972 to 1983. The finale pulled 105.9 million viewers, still the most-watched broadcast in American television history. It's a show about people stuck in the Korean War trying to stay human by being funny and caring about their work even though everything around them is insane.</p><p>The test: can you sit down and watch an episode of MASH on a Wednesday afternoon without feeling guilty about it?</p><p>If you can't, if you feel The Strive pulling at you, telling you that you're wasting time, that you should be producing something, that every hour not spent growing your brand is an hour wasted, then The Strive still owns you. You've handed your peace of mind to a system that will never give you permission to stop.</p><p>I can read a comic book now without running the mental math on whether I should be making content instead. I can go for a walk without listening to a business podcast. I can talk to someone without wondering if they're a useful connection. These sound like small things but mate I promise you, they're the whole game.</p><h2 id="why-it-sticks">Why it sticks</h2><p>You'd think, given everything I've described, that people would stop. But tey don't, and I didn't for a long time, even though I knew the math was bad.</p><p>Part of the reason why is survivorship bias. The Strive only shows you the people who won: the fundraise posts, the exit announcements, the profile in TechCrunch. You don't see the thousands who ground it out for five years and ended up back at a day job, older and more tired and with a credit card balance that makes them nauseous. The expected value of The Strive is way lower than it looks from the outside, but the outside is the only view you get.</p><p>Part of it is identity. Once I'd been Striving long enough, it stopped being something I did, and started being something I was. My friends were Strivers and my self-concept was "ambitious person building something." When I started pulling back, it felt like I was killing a version of myself. That's not a comfortable feeling.</p><p>But the biggest part, the part nobody wants to cop to is this: The Strive is a really good way to avoid sitting with your actual life. If you're always chasing the next milestone, you don't have to ask whether you like the way you spend your days. You don't have to look at the possibility that catching the thing wouldn't make you happy either. I think, for me, a lot of The Strive was... running, running from the question of whether any of it was what I wanted, or what I'd been told to want.</p><h2 id="boring-on-purpose">Boring on purpose</h2><p>Contentment is boring. "I woke up, I wrote something I liked, I read a book, I had dinner, I went to bed" doesn't make for a great narrative. Nobody's making a podcast series about the person who decided things were just fine and they were just fine with that.</p><p>The Strive has narrative tension. Will they raise the round? Will the product launch? Will they make it? My life doesn't have narrative tension right now and I think that might be the whole point.</p><p>A life that makes a good story tends to be a life that was awful to live. The chapters people want to read about in biographies tend to be the ones the person would have skipped if they could. The Strive sounds great in the abstract. Work hard, dream big, change the world, but on the ground it's a prescription for chronic dissatisfaction, because it trains you to put your well-being somewhere in the future, always in the future, and the future never arrives.</p><p>I'd rather be bored and present than excited and perpetually somewhere else. I'd rather have a Wednesday than a narrative arc. I realise that's not a sexy position to hold. I'm directionally ok with that.</p><p>I work hard, I care about quality. I want the things I make to be good and I want to find clients who push me and I want projects that make my brain hurt in a good way.</p><p>But the specific cultural program that equates your worth with your scale, your follower count, your funding round, is a bad deal for most people. It takes the normal desire to do good work and bolts a set of impossible metrics onto it. It takes "I'd like to make a living doing something I care about" and inflates it into "you need to build an empire." Those are different things. The Strive collapses them into one.</p><h2 id="where-this-goes">Where this goes</h2><p>"Is this enough?" is a better question than "How do I get more?" and I wish someone had told me that 10 years ago, but I probably wouldn't have listened.</p><p>I was too busy Striving.</p><p>The Strive isn't going anywhere, not any time soon. There's too much money in it, too many people selling the dream. The conferences will keep going, and the podcasts will keep recording, and LinkedIn will keep telling you that your comfort zone is where dreams go to die, which, as motivational slogans go, really is something isn't it?</p><p>But I think, <em>I hope</em>, the math is starting to catch up with more people. We spend years marinating in anxiety for a feeling that lasts 48 hours, on repeat, forever - and that is a bad fucking trade.</p><p>I'm going to go watch MASH now. I've got nowhere to be and nothing to optimise and I don't feel guilty about it at all.</p>
<div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal " data-layout="minimal">
<div class="kg-cta-sponsor-label-wrapper">
<div class="kg-cta-sponsor-label">
<span style="white-space: pre-wrap;">SPONSORED</span>
</div>
</div>
<div class="kg-cta-content">
<div class="kg-cta-content-inner">
<div class="kg-cta-text">
<p><span style="white-space: pre-wrap;">Westenberg is designed, built and funded by my solo-powered agency, Studio Self. Reach out and work with me:</span></p>
</div>
<a href="https://www.thisisstudioself.com/?ref=joanwestenberg.com" class="kg-cta-button " style="background-color: #000000; color: #ffffff;">
Work with me
</a>
</div>
</div>
</div>
Mildliner Fine Review - Robb Knight • Posts • Atom Feedhttps://rknight.me/blog/mildliner-fine-review/2026-04-09T11:50:01.000Z<p>I'm not saying I'm obsessed with Mildliners but this review of the new fine versions will be my fourth post about them so make of that what you will.</p>
<figure><img src="https://cdn.rknight.me/site/2026/mildliner-fine-samples.jpg" alt="A notepad showing a sample of 10 different mildliner highlighters. All the pens are resting on the pad at the bottom." /></figure>
<p>These new fine versions have two tips: a fine 0.7 and an extra fine 0.5. They're longer than the standard Mildliners presumably to accommodate the fine tips and the top of the cap is embossed with an F. There are ten of these in total reusing existing colours across two sets: the calmer, darker "Set A" and the brighter "Set B". I've updated the <a href="https://mildliners.rknight.me/">Mildliner site</a> to have the new sets but for the sake of completeness the available colours are:</p>
<ul>
<li>Gray</li>
<li>Brown</li>
<li>Dark Blue</li>
<li>Red</li>
<li>Dark Gray</li>
<li>Gold</li>
<li>Apricot</li>
<li>Fuchsia</li>
<li>Violet</li>
<li>Summer Green</li>
</ul>
<p>I think gray is probably a little too light to be useful at the extra fine size but overall this is a decent selection of colours. Two grays though? Come on. If <a href="https://www.afth.co.uk/zebra-pens---mildliner-thin---set-a-70857-p.asp">Art from the Heart</a> are to be believed these have limited availability although I can't verify that because Zebra don't seem to know these exist based on their website.</p>
<p>The extra fine tip doesn't give the kind of resistance I like from a fineliner usually but I doubt I'll be using these to write with; much more likely they get used for cover pages and general decoration. It's notable that there is now multiple definitions of "fine" across the range - the standard fine, the new fine, and the brush tipped ones mark the non-brush end as "super fine".</p>
<figure><img src="https://cdn.rknight.me/site/2026/mildliner-fine-samples-tips.jpg" alt="A notepad showing the differences in size new fine mildliners next to their standard counterparts. The new ones are longer" /></figure>
<p>One other oddity when comparing them is that all the cap colours match with the exception of dark grey where the cap is much darker on the fine one than it's standard counterpart.</p>
<p>I paid £10 for each set of these which is about right for Mildliners and I'm impressed with them. As of right now I've only seen them on <a href="https://www.afth.co.uk/zebra---mildliners-1367-c.asp">Art from the Heart</a> but I'd imagine other retailers will get some soon.</p>Book Review: Small Comfort by Ia Genberg ★★☆☆☆ - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=700172026-04-09T11:34:59.000Z<p><img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/hbg-title-small-comfort.webp" alt="Book cover." width="200" class="alignleft size-full wp-image-70019"/> I was left somewhat unconvinced by this book. I liked the concept - a series of interrelated stories all told in different styles.</p>
<p>Much like the film "<ruby lang="de">Lola Rennt<rt lang="en">Run Lola Run</rt></ruby>" there's a briefcase full of cash, a cast of morally ambiguous characters, and a meandering philosophical discussion about the nature of economic salvation.</p>
<p>It slams together the naïve and the cynical into a bunch of uneasy conversations.</p>
<p>I loved the slow-burn of the first story - the way it gradually revealed more and more about the characters. But throughout I was left wondering "where is this going?" The answer, disappointingly, was nowhere.</p>
<p>That's the heart of my problem with the book - it was compelling and frustrating in equal measure. The author herself states it best:</p>
<blockquote><p>The reader needs something to hold on to. A glimmer of hope</p></blockquote>
<p>It was stylish, there's no doubt about that. The texture of each story was gorgeous. The plotting was inventive and the morality interesting. I also enjoyed the bluntness of the social politics of economics. I just felt the whole was much less than the sum of its parts.</p>
<p>I read this as part of a new book club I'm attending. Thankfully, everyone else seemed to agree that it was a bit of a let down.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70017&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>Master C and C++ with our new Testing Handbook chapter - Trail of Bits Bloghttps://blog.trailofbits.com/2026/04/09/master-c-and-c-with-our-new-testing-handbook-chapter/2026-04-09T11:00:00.000Z<p>We added a new chapter to our Testing Handbook: <a href="https://appsec.guide/docs/languages/c-cpp/">a comprehensive security checklist for C and C++ code</a>. We’ve identified a broad range of common bug classes, known footguns, and API gotchas across C and C++ codebases and organized them into sections covering Linux, Windows, and seccomp. Whereas other handbook chapters focus on static and dynamic analysis, this chapter offers a strong basis for manual code review.</p>
<p>LLM enthusiasts rejoice: we’re also developing a Claude skill based on this new chapter. It will turn the checklist into bug-finding prompts that an LLM can run against a codebase, and it’ll be platform and threat-model aware. Be sure to give it a try when we release it.</p>
<p>And after reading the chapter, you can test your C/C++ review skills against two challenges at the end of this post. Be in the <a href="https://www.google.com/url?q=http://trailofbits.com/c-whats-wrong-challenge&sa=D&source=docs&ust=1774476381966292&usg=AOvVaw3f2cK9azgCKSuTCcMD4Kjn">first 10 to submit correct answers</a> to win Trail of Bits swag!</p>
<h2 id="whats-in-the-chapter">What’s in the chapter</h2>
<p>The chapter covers five areas: general bug classes, Linux usermode and kernel, Windows usermode and kernel, and seccomp/BPF sandboxes. It starts with language-level issues in the bug classes section—memory safety, integer errors, type confusion, compiler-introduced bugs—and gets progressively more environment-specific.</p>
<p>The Linux usermode section focuses on libc gotchas. This section is also applicable to most POSIX systems. It ranges from well-known problems with string methods, to somewhat less known caveats around privilege dropping and environment variable handling. The Linux kernel is a complicated beast, and no checklist could cover even a part of its intricacies. However, our new Testing Handbook chapter can give you a starting point to bootstrap manual reviews of drivers and modules.</p>
<p>The Windows sections cover DLL planting, unquoted path vulnerabilities in <code>CreateProcess</code>, and path traversal issues. This last bug class includes concerns like <a href="https://devco.re/blog/2025/01/09/worstfit-unveiling-hidden-transformers-in-windows-ansi/">WorstFit Unicode bugs</a>, where characters outside the basic ANSI set can be reinterpreted in ways that bypass path checks entirely. The kernel section addresses driver-specific concerns such as device access controls, denial of service through improper spinlock usage, security issues arising from passing handles from usermode to kernelmode, and various sharp edges in Windows kernel APIs.</p>
<p>Linux <a href="https://man7.org/linux/man-pages/man2/seccomp.2.html">seccomp</a> and <a href="https://man7.org/linux/man-pages/man2/bpf.2.html">BPF</a> features are often used for sandboxing. While more modern tools like <a href="https://docs.kernel.org/userspace-api/landlock.html">Landlock</a> and <a href="https://man7.org/linux/man-pages/man7/namespaces.7.html">namespaces</a> exist for this task, we still see a combination of these older features during audits. And we always uncover a lot of issues. The new Testing Handbook chapter covers sandbox bypasses we’ve seen, like <code>io_uring</code> syscalls that execute without the BPF filter ever seeing them, the <a href="https://man7.org/linux/man-pages/man2/clone.2.html"><code>CLONE_UNTRACED</code></a> flag that lets a tracee effectively disable seccomp filters, and memory-level race conditions in ptrace-based sandboxes.</p>
<h2 id="test-your-review-skills">Test your review skills</h2>
<p>We’ve provided two challenges below that contain real bug classes from the checklist. Try to spot the issues, then <a href="http://trailofbits.com/c-whats-wrong-challenge">submit your answers</a>. If you’re in the first 10 to submit correct answers, you’ll receive Trail of Bits swag. The challenge will close April 17, so get your answers in before then.</p>
<p>Stuck? Don’t worry. We’ll be publishing the answers in a follow-up blog post, so don’t forget to #like and #subscribe, by which we mean <a href="https://blog.trailofbits.com/index.xml">add our RSS feed to your reader</a>.</p>
<h3 id="the-many-quirks-of-linux-libc">The many quirks of Linux libc</h3>
<p>In this simple ping program, there are two libc gotchas that make the program trivially exploitable. Can you find and explain the issues? If you can’t, check out the handbook chapter. Both bugs are covered in the Linux usermode section.</p>
<figure class="highlight">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf"><string.h></span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf"><arpa/inet.h></span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define ALLOWED_IP "127.3.3.1"
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">ip_addr</span><span class="p">[</span><span class="mi">128</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">in_addr</span> <span class="n">to_ping_host</span><span class="p">,</span> <span class="n">trusted_host</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// get address
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">fgets</span><span class="p">(</span><span class="n">ip_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ip_addr</span><span class="p">),</span> <span class="n">stdin</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">ip_addr</span><span class="p">[</span><span class="nf">strcspn</span><span class="p">(</span><span class="n">ip_addr</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// verify address
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">inet_aton</span><span class="p">(</span><span class="n">ip_addr</span><span class="p">,</span> <span class="o">&</span><span class="n">to_ping_host</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">ip_addr_resolved</span> <span class="o">=</span> <span class="nf">inet_ntoa</span><span class="p">(</span><span class="n">to_ping_host</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// prevent SSRF
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">((</span><span class="nf">ntohl</span><span class="p">(</span><span class="n">to_ping_host</span><span class="p">.</span><span class="n">s_addr</span><span class="p">)</span> <span class="o">>></span> <span class="mi">24</span><span class="p">)</span> <span class="o">==</span> <span class="mi">127</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// only allowed
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">inet_aton</span><span class="p">(</span><span class="n">ALLOWED_IP</span><span class="p">,</span> <span class="o">&</span><span class="n">trusted_host</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">trusted_resolved</span> <span class="o">=</span> <span class="nf">inet_ntoa</span><span class="p">(</span><span class="n">trusted_host</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">strcmp</span><span class="p">(</span><span class="n">ip_addr_resolved</span><span class="p">,</span> <span class="n">trusted_resolved</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// ping
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">char</span> <span class="n">cmd</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"> <span class="nf">snprintf</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">cmd</span><span class="p">),</span> <span class="s">"ping '%s'"</span><span class="p">,</span> <span class="n">ip_addr</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="nf">system</span><span class="p">(</span><span class="n">cmd</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</figure>
<h3 id="windows-driver-registry-gotchas">Windows driver registry gotchas</h3>
<p>This Windows Driver Framework (WDF) driver request handler queries product version values from the registry. There are several bugs here, including an easy-to-exploit denial of service, but one of them leads to kernel code execution by messing with the registry values. Can you figure out the bug and how to exploit it?</p>
<figure class="highlight">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">NTSTATUS</span>
</span></span><span class="line"><span class="cl"><span class="nf">InitServiceCallback</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">_In_</span> <span class="n">WDFREQUEST</span> <span class="n">Request</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">NTSTATUS</span> <span class="n">status</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">PWCHAR</span> <span class="n">regPath</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">size_t</span> <span class="n">bufferLength</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// fetch the product registry path from the request
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">status</span> <span class="o">=</span> <span class="nf">WdfRequestRetrieveInputBuffer</span><span class="p">(</span><span class="n">Request</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="o">&</span><span class="n">regPath</span><span class="p">,</span> <span class="o">&</span><span class="n">bufferLength</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">NT_SUCCESS</span><span class="p">(</span><span class="n">status</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">TraceEvents</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_LEVEL_ERROR</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_QUEUE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"%!FUNC! Failed to retrieve input buffer. Status: %d"</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">status</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">status</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="cm">/* check that the buffer size is a null-terminated
</span></span></span><span class="line"><span class="cl"><span class="cm"> Unicode (UTF-16) string of a sensible size */</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">bufferLength</span> <span class="o"><</span> <span class="mi">4</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl"> <span class="n">bufferLength</span> <span class="o">></span> <span class="mi">512</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="n">bufferLength</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl"> <span class="n">regPath</span><span class="p">[(</span><span class="n">bufferLength</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="sa">L</span><span class="sc">'\0'</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">TraceEvents</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_LEVEL_ERROR</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_QUEUE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"%!FUNC! Buffer length %d was incorrect."</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">bufferLength</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">STATUS_INVALID_PARAMETER</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="n">ProductVersionInfo</span> <span class="n">version</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"> <span class="n">HandlerCallback</span> <span class="n">handlerCallback</span> <span class="o">=</span> <span class="n">NewCallback</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">readValue</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// read the major version from the registry
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">RTL_QUERY_REGISTRY_TABLE</span> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"> <span class="nf">RtlZeroMemory</span><span class="p">(</span><span class="n">regQueryTable</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">RTL_QUERY_REGISTRY_TABLE</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">Name</span> <span class="o">=</span> <span class="sa">L</span><span class="s">"MajorVersion"</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">EntryContext</span> <span class="o">=</span> <span class="o">&</span><span class="n">readValue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">Flags</span> <span class="o">=</span> <span class="n">RTL_QUERY_REGISTRY_DIRECT</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">QueryRoutine</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="nf">RtlQueryRegistryValues</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">RTL_REGISTRY_ABSOLUTE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">regPath</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nb">NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nb">NULL</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">NT_SUCCESS</span><span class="p">(</span><span class="n">status</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">TraceEvents</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_LEVEL_ERROR</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_QUEUE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"%!FUNC! Failed to query registry. Status: %d"</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">status</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">status</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nf">TraceEvents</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_LEVEL_INFORMATION</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_QUEUE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"%!FUNC! Major version is %d"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">readValue</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">version</span><span class="p">.</span><span class="n">Major</span> <span class="o">=</span> <span class="n">readValue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">version</span><span class="p">.</span><span class="n">Major</span> <span class="o"><</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// versions prior to 3.0 need an additional check
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">RtlZeroMemory</span><span class="p">(</span><span class="n">regQueryTable</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">RTL_QUERY_REGISTRY_TABLE</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">Name</span> <span class="o">=</span> <span class="sa">L</span><span class="s">"MinorVersion"</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">EntryContext</span> <span class="o">=</span> <span class="o">&</span><span class="n">readValue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">Flags</span> <span class="o">=</span> <span class="n">RTL_QUERY_REGISTRY_DIRECT</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">QueryRoutine</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="nf">RtlQueryRegistryValues</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">RTL_REGISTRY_ABSOLUTE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">regPath</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">regQueryTable</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nb">NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nb">NULL</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">NT_SUCCESS</span><span class="p">(</span><span class="n">status</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">TraceEvents</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_LEVEL_ERROR</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_QUEUE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"%!FUNC! Failed to query registry. Status: %d"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">status</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">status</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nf">TraceEvents</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_LEVEL_INFORMATION</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">TRACE_QUEUE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"%!FUNC! Minor version is %d"</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">readValue</span>
</span></span><span class="line"><span class="cl"> <span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">version</span><span class="p">.</span><span class="n">Minor</span> <span class="o">=</span> <span class="n">readValue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">DoesVersionSupportNewCallback</span><span class="p">(</span><span class="n">version</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">handlerCallback</span> <span class="o">=</span> <span class="n">OldCallback</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nf">SetGlobalHandlerCallback</span><span class="p">(</span><span class="n">handlerCallback</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</figure>
<h2 id="were-not-done-yet">We’re not done yet</h2>
<p>Our goal is to continuously update the handbook, including this chapter, so that it remains a key resource for security practitioners and developers who are involved in the source code security review process. If your favorite gotcha is not there, please <a href="https://github.com/trailofbits/testing-handbook">send us a PR</a>.</p>
<p>Checklist-based review, even combined with skilled-up LLMs, is only a single step in securing a system. Do it, but remember that it’s just a starting point for manual review, not a substitute for deep expertise. If you need help securing your C/C++ systems, <a href="https://www.trailofbits.com/contact/">contact us</a>.</p>The bottleneck shifts to distribution - Werd I/O69d683a634c6b00001decbbd2026-04-08T16:34:46.000Z<p>[<a href="https://newsletter.squishy.computer/p/the-bottleneck-shifts-to-distribution?ref=werd.io">Gordon Brander</a>]</p><p>This definitely gave me pause. In a world where writing code is something vastly more people can do, when even GitHub is struggling to keep up with the ballooning number of codebases out there, it’s going to be increasingly impossible to get recognition for your work.</p><blockquote>“This is what it takes for your free and open source project to be recognized in 2026: you must secure the endorsement of legendary actress Milla Jovovich. You know, like a celebrity vodka.”</blockquote><p>I kicked against this — who says Milla Jovovich wasn’t a first class contributor? <a href="https://www.history.com/articles/hedy-lamarr-inventor-frequency-hopping-wifi?ref=werd.io">The fundamentals of WiFi were created by Hedy Lamarr</a> — but it’s true that the commits are mostly assigned to Sigman, the CEO of Bitcoin Libre. She is credited as architect, he as engineer, together with a contributor called Lu.</p><p>Regardless, it’s obvious that attaching her name to the project has drawn it more attention, and that this is a product that could result in a real financial outcome for both her and Sigman. I’m left feeling really glad that I released my first big open source software 22 years ago, when LLMs were an impossibility and big names didn’t attach themselves to open source. I was able to build a community with the funding equivalent of a can of Coke and a packet of crisps; if I’d been competing against Hollywood celebrities, I would have had no chance at all.</p><p>But I don’t quite agree with the thesis. Whether you’re famous or not, the way to get a following for your code is to solve a real problem better than anyone else. It’s true that distribution platforms can be kingmakers, but starting small by building real relationships with people you’re trying to help in ways that don’t scale is still a good way to get off the ground. That means building something genuinely differentiated rather than something that’s a few degrees off from what everyone else is doing. For small players with no networks and no names, that’s always been the best way to start, and I think it likely still is.</p><p>[<a href="https://newsletter.squishy.computer/p/the-bottleneck-shifts-to-distribution?ref=werd.io">Link</a>]</p>Early days with the XTEINK X4 ereader - Joel's Log Fileshttps://joelchrono.xyz/blog/xteink-x42026-04-08T13:30:00.000Z<p>A couple of weeks ago I acquired a tiny ereading device, the XTEINK X4. It all started with a YouTube video <a href="https://youtu.be/uGpAAKEHjlo">reviewing the device</a> that I first shared in <a href="https://joelchrono.xyz/blog/2026-w10/">one of my weeknotes</a>. A day later I saw that <a href="https://bne.social/@james/116204477104692183">James had been using one already</a>, and soon enough after a few more reviews I <a href="https://joelchrono.xyz/blog/e-ink-is-very-cool/">ordered one myself</a>.</p>
<p>Along James, some other people I follow on the fedi got it, such as Neil, <a href="https://neilzone.co.uk/2026/03/initial-thoughts-on-the-tiny-xteink-x4-ereader/">who shared his thoughts on it too</a>.</p>
<p>And because of me (yes, I’m taking all the credit ;) <a href="https://polymaths.social/@jp/statuses/01KKKWEZ53P9E078P4839PS9YW">Jeremy got one</a>, <a href="https://www-gem.codeberg.page/sys_x4/">wwwgem got one</a>, <a href="https://gts.da-miez.de/@irgndsondepp/statuses/01KNC8B6V0R1Q2MV3Y9SA7FZGM">Robert got one</a>, <a href="https://im-in.space/@njrk/116221119639099884">njrk got one</a>… so on and so forth. A quick look through <a href="https://mastodon.social/tags/xteink">the hashtag</a> will show how the device’s gotten popular for a few months now.</p>
<p>There really are not a lot of reasons not to give it a go. With a price of 70 bucks or much less on a good sale, there is no excuse, in my opinion.</p>
<p>The XTEINK X4 has excellent battery life, a great set of physical buttons—with no touch screen—and, best of all, a community building homebrew for it and making it better day after day!</p>
<p>The most popular firmware is <a href="https://github.com/crosspoint-reader/crosspoint-reader">CrossPoint</a>, which optimizes quite a lot of things compared to the built-in OS. In fact, I didn’t even use the device until I got it installed—it took me less than ten minutes.</p>
<p>All I did was change the language, plug the device to my dad’s Windows laptop—because I couldn’t bother to figure out permissions for the serial USB access on my Linux-powered laptop, sorry not sorry—and off I went.</p>
<p>I went for a minimal and more manual approach. I only have eight books on it, and I will only be replacing them as I go through them. The device doesn’t have a lot of memory—much less than a megabyte of RAM—so it’s ideal to <a href="https://github.com/bigbag/epub-to-xtc-converter">format the EPUBs accordingly</a> to avoid high-resolution covers and unsupported features diminishing the experience.</p>
<p>Honestly, the EPUB files look great, the font included with the firmware, <a href="https://en.wikipedia.org/wiki/Bookerly">Bookerly</a>—which was made for Kindle back in 2015—is a pleasure to read through as well. Here’s how a page of text looks like:</p>
<p><img src="https://joelchrono.xyz/assets/img/blogs/2026-04-08-xteink2.jpg" alt="The XTEINK X4 showing some text displayed"/></p>
<p>You can change the font, margins, UI theme, and most other regular settings, and the controls for it all are very intuitive. There’s also plenty of mods and forks adding even more features, such as reading statistics.</p>
<p><a href="https://www-gem.codeberg.page/">www-gem</a> has done a lot of work finding links and extra tools, so definitely check out his posts on the device if you’re curious about all its possibilities.</p>
<p>I already finished one book on it, and I am making progress on another two. The reading experience is excellent and I really have no complaints about it other than the lack of a backlight.</p>
<p>I carry it almost everywhere, and reading one or two pages—often many more—at any point is painless, as it wakes up in just a couple seconds from sleep. The portability really is killer too. Like <a href="https://moddedbear.com/i-love-reading-on-the-xteink-x4/">Jeremy</a>, I also added a magnet to my <em>Nothing (3A)</em> to stick it there and have it with me.</p>
<p><img src="https://joelchrono.xyz/assets/img/blogs/2026-04-08-xteink.jpg" alt="The XTEINK X4 showing CrossPoint's main UI"/></p>
<p>I don’t know what else to say, I’ve not even charged it since I bought it! I’ll just keep reading on it and enjoying the process.</p>
<p>Even though I still love my <a href="https://joelchrono.xyz/blog/kobo-clara-2e-review/">Kobo Clara 2E</a>, this makes for an excellent companion device. The lack of stats on CrossPoint at the moment makes it so I don’t really want to read big books on it as much, but maybe I’ll get over that soon. I’m happy to read <a href="https://clarkesworldmagazine.com/">Clarkesworld magazine</a> and short novellas on it though…</p>
<p>This is day 47 of <a href="https://100daystooffload.com">#100DaysToOffload</a></p>
<p>
<a href="mailto:me@joelchrono.xyz?subject=Early days with the XTEINK X4 ereader">Reply to this post via email</a> |
<a href="https://fosstodon.org/@joel/116369361291372517">Reply on Fediverse</a>
</p>Theatre Review: Avenue Q ★★★★★ - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=701602026-04-08T11:34:25.000Z<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/AVEQ.webp" alt="Colourful puppets surround the letter Q." width="256" height="256" class="alignleft size-full wp-image-70161"/>
<p>I'll admit, I was a little sceptical about returning to Avenue Q. I saw it on its original West End run back in… OH MY GOD I AM <em>SO</em> OLD! FUCK! Where did the time go?</p>
<p>It's always hard to know how much to update a show. Does it need constant reinvention to stay in the zeitgeist or can it be pickled forever as a classic?</p>
<p>"I wish I had taken more pictures" was something that utterly resonated with me about my university experience. Photos were a rare commodity back when film still cost a couple of quid to develop. Perhaps today's uni students will sing "I wish I had posted less on Instagram"?</p>
<p>The show has been sympathetically updated. Some of the references have been modernised, a transphobic joke given the boot, and the lyrics tweaked to sometimes devastating effect. The song "Everyone's A Little Bit Racist" seems to have the most changes - and all for the better.</p>
<p>Parts of the show are adapted for a UK audience. Barely anyone here knows who Gary Coleman was so his intro is changed (although I guess part of the metajoke is that we all watched foreign celebrities on Sesame Street when we were growing up - so what's one more obscure cultural reference?). In the American show, the Bad Idea Bears proffer Long Island Ice Teas - that was a bit tame for UK audiences, so in the <a href="https://playbill.com/article/diva-talk-catching-up-with-avenue-qs-ann-harada-plus-news-of-buckley-and-york-com-162426">original UK run they guzzled absinthe daiquiris</a> - a change inexplicably reverted for this limited run.</p>
<p>As a piece of pure entertainment it is spectacular. The laughs are genuinely non-stop and the whole auditorium rose to give the performers a well-deserved ovation. It is a tender and beautiful show which shows off the power of live theatre.</p>
<p>The songs are still stuck in my head and the puppetry is still amazing. Absolutely hilarious, genuinely shocking in places, utterly filthy - an excellent night out.</p>
<h2 id="pre-and-post-show"><a href="https://shkspr.mobi/blog/2026/04/theatre-review-avenue-q/#pre-and-post-show">Pre- and Post-Show</a></h2>
<p>I've written before about <a href="https://shkspr.mobi/blog/2024/12/the-art-of-the-pre-show-and-post-show/">The art of the Pre-Show and Post-Show</a>. With West End prices higher than ever, it is incumbent on theatres to make their shows a memorable and spectacular evening out. That can be as simple as a bit of set dressing in the foyer, or as extravagant as they can get away with.</p>
<p>The offering is pretty reasonable here. You can buy the T-shirt, hoodie, and commemorative socks at exorbitant prices. The souvenir programme is £8 and, while lush with photos, is pretty sparse. The original West End programme from the early 2000s had a pin-up calendar of Lucy The Slut, a bunch more funny photos, and fake autographs of the puppets.</p>
<p>There's a photo-booth for taking selfies, but it appeared to be broken.</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/broken.webp" alt="A broken photo stand." width="1024" height="771" class="aligncenter size-full wp-image-70215"/>
<p>It might been nice to have a few puppets placed around for people to take photos with.</p>
<p>One of the simplest things a venue can do is put on a themed cocktail menu. I'm surprised more shows don't do that. Who is going to turn down a glass of "The Internet Is For Pornstar Martini"?</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/cocktails.webp" alt="Cocktails include "The Internet is for pornstar martini" a "Chardenfreude" made with green chartreuse, a "fuzzy neighbour", and a mocktail called "Canadian Girlfriend"." width="1024" height="768" class="aligncenter size-full wp-image-70216"/>
<p>The Shaftesbury Theatre itself isn't too cramped, even in the cheap seats. Although, at the back of the stalls, the overhang cuts off the top of the set which means you will miss a bit of action in some scenes.</p>
<p>While we were waiting for the show to start, the auditorium was filled with soundscape of subway cars rattling and distorted announcements. Again, fairly cheap and simple, but a nice way to build the mood.</p>
<p>As we exited, we were handed leaflets encouraging us to come back and bring our friends. Even better was the £10 discount on our next booking!</p>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/leaflet.webp" alt="A leaflet offering a discount on Avenue Q." width="1024" height="831" class="aligncenter size-full wp-image-70218"/>
<p>Considering this is a limited run, the production has done a fair job of getting the audience in the mood and rewarding them for their patronage.</p>
<p>Well done to all involved!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70160&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>Personal site infrastructure, diagrammed - Posts feedhttps://www.coryd.dev/posts/2026/personal-site-infrastructure-diagrammed2026-04-08T01:27:00.000Z<p>That I even need and have made a diagram of the infrastructure for this site speaks to how over-engineered it is. Yet, while it is ostensibly a personal site, it's a personal site that's replaced many services that I previously used.</p>
<p><img src="https://cdn.coryd.dev/uploads/01KNNCKZM2RFGY55CHXBJ9DGHA.png?class=w800" alt="" /></p>Music, story(ies) - James' Coffee Bloghttps://jamesg.blog/2026/04/08/music-story-ies2026-04-08T00:00:00.000Z
<p>I was inspired by, of all things, a <a href="https://www.youtube.com/watch?v=8pnk93AAsdw">video monologue by a Scottish surfer</a> [1] who said that the future for them was challenging themselves in new ways. My guitar was close by and I thought <em>maybe I should give myself a bit of a challenge too.</em> I picked up my guitar and looked up a tutorial on how to do finger picking. </p><p>The first video I found was a bit challenging. I looked for another that was easier. The one I found was a tutorial showing how to play <em>How did it end?</em> by Taylor Swift, a song with one of her best – and dare I say most solemnly passionate – bridges. For the next fifteen minutes or so, I followed the tutorial dutifully, trying, making mistakes, and, along the way, hearing something that resembled the song. The more I practiced, the closer I was to the melody of the song. [2]</p><p>Earlier today I was doing a few creative writing exercises as part of an introduction to creative writing at school. Admittedly, the prospect of creative writing was a bit scary. I never knew where to begin. With all the possibilities, where should I start?</p><p>The exercises have surprised me in how approachable they are. One exercise involved making a character and writing a few bullet points about them based on a list of questions. The next step was to turn the bullet points into a paragraph or two of text. I was surprised by how much fun I had. The exercise wasn’t as scary as I thought. And I started to figure out how to bring in some of the elements of the introspective writing style I enjoy so much into a creative writing exercise. I could bring in part of me into a fictional character. I’m looking forward to the next exercises.</p><p>Meanwhile, this week I have been tinkering with a new design for my <a href="https://jamesg.blog/gallery">gallery page</a> which lists a few paintings I like. One idea I want to explore is a layout that shows one image at a time, which would make it easier for viewers to focus on a painting. I also want to add in a little bit more metadata, such as a link to the original painting and, if applicable, a link to any blog post I have written on the painting.</p><p>I have also added a <a href="https://jamesg.blog/talks">talks page</a> to my website which lists several talks I have enjoyed. The list is far from comprehensive but I accept that as a limit. Like my gallery page, there is no way I could list all of the talks I have watched and enjoyed. But I can add a few that were especially memorable, and keep gardening it over time. Thus is the nature of having a website. If you make a talks page, let me know. I am always looking for more talks to watch.</p><p><strong>[1]:</strong> h/t <a href="https://artlung.com" rel="noreferrer">Joe</a> for sharing the video today. I was mesmerised by how the surfer weaved through the waves.</p><p><strong>[2]:<em> </em></strong>Side note: I have really enjoyed playing the <a href="https://www.youtube.com/watch?v=60UPfRRTbTk">Out of the Woods x All You Had to Do Was Stay</a> mashup. I did try to start making a web page that listed Eras Tour mashups I especially enjoyed, but with time I realised such a list would encompass every mashup and thus be more of an index. Now that I think more about it, it might be worth making that page nevertheless as a more direct means of accessing the recordings of mashups posted to YouTube. Every little web page can make a difference on this big World Wide Web.</p>
<a class="tag" href="https://artlung.com">Joe</a>
<a class="tag" href="https://jamesg.blog/gallery">gallery page</a>
<a class="tag" href="https://jamesg.blog/talks">talks page</a>
<a class="tag" href="https://www.youtube.com/watch?v=60UPfRRTbTk">Out of the Woods x All You Had to Do Was Stay</a>
<a class="tag" href="https://www.youtube.com/watch?v=8pnk93AAsdw">video monologue by a Scottish surfer</a>
Obfuscating My Contact Email - Kev Quirkhttps://kevquirk.com/obfuscating-my-contact-email2026-04-07T21:41:00.000Z
<p>I stumbled across <a href="https://spencermortensen.com/articles/email-obfuscation/">this great post by Spencer Mortensen</a> yesterday, which tested different email obfuscation techniques against real spambots to see which ones actually work. It's a fascinating read, and I'd recommend checking it out if you're into that sort of thing.</p>
<p>The short version is that spambots scrape your HTML looking for email addresses. If your address is sitting there in plain text, they'll hoover it up. But if you encode each character as a <a href="https://developer.mozilla.org/en-US/docs/Glossary/Character_reference">HTML entity</a>, the browser still renders and uses it correctly, while most bots haven't got a clue what they're looking at.</p>
<p>From Spencer's testing, this approach blocks around 95% of harvesters, which is good enough for me.</p>
<h2>Where my email appears</h2>
<p>On this site, my contact email shows up in two places:</p>
<ol>
<li>The <em>Reply by email</em> button at the bottom of every post.</li>
<li>My <a href="https://kevquirk.com/contact">contact page</a>.</li>
</ol>
<p>Both pull from the <code>site_email</code> value in Pure Blog's config, so I only needed to make a couple of changes.</p>
<h2>The reply button</h2>
<p>The reply button lives in <code>content/includes/post-meta.php</code>, which is obviously a PHP file. So the fix there was straightforward - I ditched the <code>{{ site_email }}</code> shortcode and used PHP directly to encode the address character by character into HTML entities:</p>
<pre><code class="language-php"><?php
$_email = load_config()['site_email'] ?? '';
$_encoded = implode('', array_map(fn($c) => '&#x' . dechex(ord($c)) . ';', str_split($_email)));
?>
<a class="button reply-button"
href="mailto:<?= $_encoded ?>?subject=Reply to: {{ post_title }}">Reply by email
</a></code></pre>
<p>Each character becomes something like <code>&#x6b;</code>, which is gibberish to a bot, but perfectly readable to a human using a browser. The <code>{{ post_title }}</code> shortcode still gets replaced normally by Pure Blog after the PHP runs, so the subject line still works as expected.</p>
<h2>The contact page</h2>
<p>The contact page is a normal page in Pure Blog, so it's Markdown under the hood. This means I can't drop PHP into it. Instead, I used Pure Blog's <code>on_filter_content</code> <a href="https://pureblog.org/using-hooks">hook</a>, which runs after shortcodes have already been processed. By that point, <code>{{ site.email }}</code> has been replaced with the plain email address, so all I needed to do was swap it for the encoded version:</p>
<pre><code class="language-php"><?php
declare(strict_types=1);
function on_filter_content(string $content): string
{
$config = load_config();
$email = trim((string) ($config['site_email'] ?? ''));
if ($email === '') {
return $content;
}
$encoded = implode('', array_map(fn($c) => '&#x' . dechex(ord($c)) . ';', str_split($email)));
return str_replace($email, $encoded, $content);
}</code></pre>
<p>This goes in <code>config/hooks.php</code>, and now any page content that passes through Pure Blog's <code>filter_content()</code> function will have the email automatically encoded. So if I decide to publish my <code>site_email</code> elsewhere, it should automagically work.</p>
<h2>One more layer of protection</h2>
<p>As well as the obfuscation, I also set up my email address as a proper alias rather than relying on a catch-all to <a href="https://kevquirk.com/segregating-email-with-sub-domains">segregate emails</a>. That way, if spam does somehow get through, I can nuke the alias, create a new one, and update it in Pure Blog's settings page.</p>
<p>Is this overkill? Probably. But it was a fun little rabbit hole, and now I can feel smug about it. 🙃</p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=Obfuscating%20My%20Contact%20Email">reply to this post by email</a>, or <a href="https://kevquirk.com/obfuscating-my-contact-email#comments">leave a comment</a>.</p>
</div>
When the President threatens to commit a genocide - Werd I/O69d5563734c6b00001decb9e2026-04-07T19:09:44.000Z<p>Some of you might have missed that the President threatened Iran with genocide.</p><p>So to be clear, he said: “A whole civilization will die tonight, never to be brought back again.” Not a regime; a civilization. This is a meaningful threat on the entire population of a nation.</p><p>If he follows through, it's a crime against humanity.</p><p>If he doesn't follow through, it's a threat of genocide.</p><p>This isn't a situation we can both-sides. He's threatened to end an entire nation. There's no "people are entitled to their opinion" here. If you think this is okay, you think threatening to commit genocide is something a President should be able to do.</p><p>Some people will describe criticism of this as TDS or some knee-jerk "orange man bad". It's not those things. It's incredibly serious.</p><p>It feels surreal: like something from a movie or a TV show. That effect can be paralyzing. But it's real.</p><p>Using our voices is important at times like these. Even when it's professionally inconvenient. Even if we might lose friends when we do so.</p><p>If he is allowed to continue along this path, bad things will likely happen. Even if he doesn't execute on his threat this time, he may another time. Other nations may feel they need to defend themselves from potential violence.</p><p>What would it look like to bring the world back to a peaceful order? How can we ensure that the United States does not call for genocide again and cannot follow through with such an obscene threat?</p>Why Have a Dedicated Music Device? - Kev Quirkhttps://kevquirk.com/why-have-a-dedicated-music-device2026-04-07T13:31:00.000Z
<p>In the last year or so I've read about many people moving from streaming services, like Apple Music and Spotify, to their own music library. To support these local libraries, many seem to be getting themselves a music player, such as the <a href="https://www.fiio.com/echomini">Fiio Echo Mini</a>.</p>
<p>While moving to a local library is something that I've thought about <em>many</em> times<sup id="fnref1:1"><a href="https://kevquirk.com/why-have-a-dedicated-music-device#fn:1" class="footnote-ref">1</a></sup>, I don't understand why people are buying these little music players.</p>
<p>The big selling points generally seem to be:</p>
<ul>
<li>Bluetooth connectivity so you can use with buds, or in your car.</li>
<li>Plenty of local storage.</li>
<li>Audio jack.</li>
<li>Easy to drag and drop music.</li>
</ul>
<p>With the exception of the 3rd point, pretty much every smartphone on the market will do all of this. And let's be honest, #3 doesn't really matter as most people use Bluetooth buds these days.</p>
<p class="notice">Yes, I know <em>some</em> people still use old school wired earphones. I don't need an email from you.</p>
<p>So if the device that's already in your pocket will do everything these little music players will already do, why get an extra device to lug around everywhere?</p>
<p>I want to stress, these look <em>really</em> cool, and if that's why you want one, that's totally fine. But anecdotally, that's not what I'm seeing.</p>
<p>Can someone enlighten me? I see the advantages of owning your own music library, but I don't get why people want to carry another device everywhere.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>I've decided to stick with streaming, but that's a post for another day. <a href="https://kevquirk.com/why-have-a-dedicated-music-device#fnref1:1" rev="footnote" class="footnote-backref">↩</a></p>
</li>
</ol>
</div> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=Why%20Have%20a%20Dedicated%20Music%20Device%3F">reply to this post by email</a>, or <a href="https://kevquirk.com/why-have-a-dedicated-music-device#comments">leave a comment</a>.</p>
</div>
Did WordPress VIP leak my phone number? - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=698042026-04-07T11:34:43.000Z<p>As discussed <a href="https://shkspr.mobi/blog/2026/04/someone-at-browserstack-is-leaking-users-email-address/">in my last blog post</a>, the scumsuckers at Apollo.io have been giving out my personal details.</p>
<p>Not only did they have my email address, they also had a copy of one of my phone numbers. I asked them where they got it from and they said:</p>
<blockquote><p>Your phone number came from Parsely, Inc (wpvip.com) one of our customers who participates in our customer contributor network by sharing their business contacts with the Apollo platform.</p></blockquote>
<p>I've never done any business with <a href="https://www.parse.ly/">Parsely</a>. They have no reason to have my phone number and <em>absolutely</em> no permission to share it with other organisations.</p>
<p>Back in 2021, <a href="https://wpvip.com/blog/parse-ly-is-now-a-core-part-of-wordpress-vips-platform/">Parsely became part of WordPress VIP</a>. Ah yes, our old "friends" at Automattic with their <a href="https://shkspr.mobi/blog/2024/12/is-wordpress-org-gdpr-compliant/">somewhat lax attitude to privacy</a>.</p>
<p>I took advantage of <a href="https://wpvip.com/vip-and-the-gdpr/">WordPress VIP's GDPR policy</a> and sent a terse but polite "Hey, WTAF?" to them. Their response was quick:</p>
<blockquote><p>Thanks for reaching out. We are currently investigating our systems to locate any personal data regarding your request. We appreciate your patience.</p></blockquote>
<p>After a bit of prodding, they eventually replied with:</p>
<blockquote><p>It appears that we obtained your contact information as a result of a meeting you had with a representative for the WPScan service around August 5, 2022. WPScan is owned by our parent company Automattic.</p>
<p>We have no record of Parsely, Inc. (which is no longer in existence) or WPVIP Inc. (the owner of the Parse.ly service) having any relationship with Apollo.io.</p>
<p>We also have no record of Parsely, Inc. or WPVIP Inc. having sold or otherwise provided your information to any third party.</p></blockquote>
<p>I have no memory and no record of meeting anyone from WPScan - although I concede it is possible I did as part of a previous job.</p>
<p>But even if it was in an email signature when I contacted them that still doesn't explain how it made its way to Apollo for them to give to spammers everywhere. Was it a hack? A data leak? A treacherous employee? A deliberate sale? A sneaky app update? Or maybe just Apollo lying to me.</p>
<p>I don't care any more. I'm just so tired of shitty companies treating personal data as a commodity to be traded, sold, repackaged, and abused.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=69804&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>What we learned about TEE security from auditing WhatsApp's Private Inference - Trail of Bits Bloghttps://blog.trailofbits.com/2026/04/07/what-we-learned-about-tee-security-from-auditing-whatsapps-private-inference/2026-04-07T11:00:00.000Z<p>WhatsApp’s new “Private Inference” feature represents one of the most ambitious attempts to combine end-to-end encryption with AI-powered capabilities, such as message summarization. To make this possible, Meta built a system that processes encrypted user messages inside trusted execution environments (TEEs), secure hardware enclaves designed so that not even Meta can access the plaintext. Our <a href="https://github.com/trailofbits/publications/blob/master/reviews/2025-08-meta-whatsapp-privateprocessing-securityreview.pdf">now-public audit</a>, conducted before launch, identified several vulnerabilities that compromised WhatsApp’s privacy model, all of which Meta has patched. Our findings show that TEEs aren’t a silver bullet: every unmeasured input and missing validation can become a vulnerability, and to securely deploy TEEs, developers need to measure critical data, validate and never trust any unmeasured data, and test thoroughly to detect when components misbehave.</p>
<h2 id="the-challenge-of-using-ai-with-end-to-end-encryption">The challenge of using AI with end-to-end encryption</h2>
<p>WhatsApp’s Private Processing attempts to resolve a fundamental tension: WhatsApp is end-to-end encrypted, so Meta’s servers cannot read, alter, or analyze user messages. However, if users also want to opt in to AI-powered features like message summarization, this typically requires sending plaintext data to servers for computationally expensive processing. To solve this, Meta uses TEEs based on AMD’s SEV-SNP and Nvidia’s confidential GPU platforms to process messages in a secure enclave where even Meta can’t access them or learn meaningful information about the message contents.</p>
<p>The stakes in WhatsApp are high, as vulnerabilities could expose millions of users’ private messages. Our review identified 28 issues, including eight high-severity findings that could have enabled attackers to bypass the system’s privacy guarantees. The following sections explore noteworthy findings from the audit, how they were fixed, and the lessons they impart.</p>
<h2 id="key-lessons-for-tee-deployments">Key lessons for TEE deployments</h2>
<h3 id="lesson-1-never-trust-data-outside-your-measurement">Lesson 1: Never trust data outside your measurement</h3>
<p>In TEE systems, an “attestation measurement” is a cryptographic checksum of the code running in the secure enclave; it’s what clients check to ensure they’re interacting with legitimate, unmodified software. We discovered that WhatsApp’s system loaded configuration files containing environment variables <em>after</em> this fingerprint was taken (issue TOB-WAPI-13 in the report).</p>
<p>This meant that a malicious insider at Meta could inject an environment variable, such as <code>LD_PRELOAD=/path/to/evil.so</code>, forcing the system to load malicious code when it started up. The attestation would still verify as valid, but the attacker’s malicious code would be running inside, potentially violating the system’s security or privacy guarantees by, for example, logging every message being processed to a secret server.</p>
<p>Meta fixed this by strictly validating environment variables: they can now contain only safe characters (alphanumeric plus a few symbols like dots and dashes), and the system explicitly checks for dangerous variables like <code>LD_PRELOAD</code>. Every piece of data your TEE loads must either be part of the measured boot process or be treated as potentially hostile.</p>
<h3 id="lesson-2-do-not-trust-data-outside-your-measurement-have-we-already-mentioned-this">Lesson 2: Do not trust data outside your measurement (have we already mentioned this?)</h3>
<p>ACPI tables are configuration data that inform an operating system about the available hardware and how to interact with it. We found these tables weren’t included in the attestation measurement (TOB-WAPI-17), creating a backdoor for attackers.</p>
<p>Here’s why this matters: a malicious hypervisor (the software layer that manages virtual machines) could inject fake ACPI tables defining malicious “devices” that can read and write to arbitrary memory locations. When the secure VM boots up, it processes these tables and grants the fake devices access to memory regions that should be protected. An attacker could use this to extract user messages or encryption keys directly from the VM’s memory, and the attestation report will still verify as valid and untampered.</p>
<p>Meta addressed this by implementing a custom bootloader that verifies ACPI table signatures as part of the secure boot process. Now, any tampering with these tables will change the attestation measurement, alerting clients that something is wrong.</p>
<h3 id="lesson-3-correctly-verify-security-patch-levels">Lesson 3: Correctly verify security patch levels</h3>
<p>AMD regularly releases security patches for its SEV-SNP firmware, fixing vulnerabilities that could allow attackers to compromise the secure environment. The WhatsApp system did check these patch levels, but it made an important error: it trusted the patch level that the firmware <em>claimed</em> to be running (in the attestation report), rather than verifying it against AMD’s cryptographic certificate (TOB-WAPI-8).</p>
<p>An attacker who had compromised an older, vulnerable firmware could simply lie about their patch level. Researchers have publicly demonstrated attacks that can extract encryption keys from older SEV-SNP firmware versions. An attacker could use these published techniques against WhatsApp users to exfiltrate secret data while the client incorrectly believes it’s connected to a secure, updated system.</p>
<p>Meta’s solution was to validate patch levels against the VCEK certificate’s X.509 extensions. These extensions are cryptographically signed data from AMD that can’t be forged by compromised firmware.</p>
<h3 id="lesson-4-attestations-need-freshness-guarantees">Lesson 4: Attestations need freshness guarantees</h3>
<p>Before our review, when a client connected to the Private Processing system, the server would generate an attestation report proving its identity, but this report didn’t include any timestamp or random value from the client (TOB-WAPI-7). This meant that an attacker who compromised a TEE once could save its attestation report and TLS keys, then replay them indefinitely.</p>
<p>Achieving a one-time compromise of a TEE is typically much more feasible and much less severe than a persistent compromise affecting each individual session. For example, consider an attacker who can extract TLS session keys through a side channel attack or other vulnerability. For a single attack, the impact tends to be short-lived, as the forward security of TLS makes the exploit impactful for only a single TLS session. However, without freshness, that single success becomes a permanent backdoor because the TEE’s attestation report from that compromised session can be replayed indefinitely. In particular, the attacker can now run a fake server anywhere in the world, presenting the stolen attestation to clients who will trust it completely. Every WhatsApp user who connects would send their messages to the attacker’s server, believing it’s a secure Meta TEE.</p>
<p>Meta addressed this issue by including the TLS <code>client_random</code> nonce in every attestation report. Now each attestation is tied to a specific connection and can’t be replayed.</p>
<h3 id="how-meta-fixed-the-remaining-issues">How Meta fixed the remaining issues</h3>
<p>Before their launch, Meta resolved 16 issues completely and partially addressed four others. The remaining eight unresolved issues are low- and informational-severity issues that Meta has deliberately not addressed. Meta provided a justification for each of these decisions, which can be reviewed in appendix F of our <a href="https://github.com/trailofbits/publications/blob/master/reviews/2025-08-meta-whatsapp-privateprocessing-securityreview.pdf">audit report</a>. In addition, they’ve implemented broader improvements, such as automated build pipelines with provenance verification and published authorized host identities in external logs.</p>
<h2 id="beyond-individual-vulnerabilities-systemic-challenges-in-tee-deployment">Beyond individual vulnerabilities: Systemic challenges in TEE deployment</h2>
<p>While Meta has resolved these specific issues, our audit revealed the need to solve more complex challenges in securing TEE-based systems.</p>
<p><strong>Physical security matters:</strong> The AMD SEV-SNP threat model doesn’t fully protect against advanced physical attacks. Meta needed to implement additional controls around which CPUs could be trusted (TOB-WAPI-10). If you are interested in a more detailed discussion on physical attacks targeting these platforms, check out our <a href="https://watch.getcontrast.io/register/trail-of-bits-after-wiretap-and-battering-ram-what-changes-for-tee-based-blockchain-infrastructure">webinar</a>, which discusses recently published physical attacks targeting both AMD SEV-SNP and Intel’s SGX/TDX platforms.</p>
<p><strong>Transparency requires reproducibility:</strong> For external researchers to verify the system’s security, they need to be able to reproduce and examine the CVM images. Meta has made progress in this area, but achieving full reproducibility remains challenging, as issue TOB-WAPI-18 demonstrates.</p>
<p><strong>Complex systems need comprehensive testing:</strong> Many of the issues we found could have been caught with <a href="https://en.wikipedia.org/wiki/Negative_testing">negative testing</a>, specifically testing what happens when components misbehave or when malicious inputs are provided.</p>
<h2 id="the-path-forward-for-securely-deploying-tees">The path forward for securely deploying TEEs</h2>
<p>Can TEEs enable privacy-preserving AI features? Our audit suggests the answer is <em>yes, but only with rigorous attention to implementation details</em>. The issues we found weren’t fundamental flaws in the TEE model but rather implementation and deployment gaps that a determined attacker could exploit. These are subtle flaws that other TEE deployments are likely to replicate.</p>
<p>This audit shows that while TEEs provide strong isolation primitives, the large host-guest attack surface requires careful design and implementation. Every unmeasured input, every missing validation, and every assumption about the execution environment can become a vulnerability. Your system is only as secure as your TEE implementation and deployment.</p>
<p>For teams building on TEEs, our advice is clear: engage security reviewers early, invest in comprehensive testing (especially negative testing), and remember that security in these systems comes from getting hundreds of details right, not just the big architectural decisions.</p>
<p>The promise of confidential computing is compelling. But, as this audit shows, realizing that promise requires rigorous attention to security at every layer of the stack.</p>
<p><em>For more details on the technical findings and Meta’s fixes, see our <a href="https://github.com/trailofbits/publications/blob/master/reviews/2025-08-meta-whatsapp-privateprocessing-securityreview.pdf">full audit report</a>. If you’re building systems with TEEs and want to discuss security considerations, we offer free office hours sessions where we can share insights from our extensive experience with these technologies.</em></p>Lost and found bottle, Easter vacation! - W14 - Joel's Log Fileshttps://joelchrono.xyz/blog/w142026-04-07T03:40:00.000Z<p>Happy Easter to all of you! The week has come and gone in a flash, and a lot of things happened this time around, thanks to the few days off I got. Here’s a quick rundown through some important events and things of note!</p>
<ul>
<li>
<p>✈️ My siblings came here! There were a lot of things I did that I mention here, which happened with them around. It was a fun time, but I also quickly remembered that being the older brother comes with its caveats… let’s say my wallet feels very light right now, but it was fun!</p>
</li>
<li>
<p>🥤I went to the gym on Monday! after I left, I realized I forgot my water bottle… I was already on the bus back home so, I had to wait until tomorrow. I called a coworker who was still there, but he couldn’t find it. The next morning, the first thing I did was ask at the reception—my bottle was nowhere to be found. The next day, my siblings went to the gym with me, and even though I had already given up, they still asked, and wouldn’t you know, the bottle was right there! So, yay!</p>
</li>
<li>
<p>🚗 The first day of my Easter vacation was spent on… goint to a small town to get new plates for the family car, for like 6 hours. There was a store nearby and we got some snacks, I took a couple pictures in the main plaza downtown, so that was fun. I also played a lot of <em>Resident Evil.</em></p>
</li>
<li>
<p>🍔 Once we got out of that place, we went back to civilization and ate some burgers! The usual chain here is <em>Burguer King</em>, and we enjoyed them very much.</p>
</li>
<li>
<p>🧱 I created a new background pattern for my website! You can see it on any page as long as it’s on desktop, currently unavailable on mobile due to screen size. Hope you like it! I plan to make it better later</p>
</li>
<li>
<p>🍿 Invited my family to watch a movie to the cinemas, which were pretty close (we were at a mall), and ended up watching <em>Project Hail Mary</em>. It was very fun because the place was packed full of people because of the release of the <em>Super Mario Galaxy</em> movie… we’ll watch that one later. We went with my grandma and kinda didn’t realize there was no ramp for her wheelchair. However, she sat on the first row along my parents, and nobody had reserved those seats, so there was no problem!</p>
</li>
<li>
<p>🃏 We acquired and played a new card game! <em>Coup</em>, a bluffing game where you eliminate all of your opponents until someone takes over and controls the whole political landscape!</p>
</li>
<li>
<p>🎂 We had a surprise party for a friend and spent sometime decorating their place before they got there. We also had pizza!</p>
</li>
<li>
<p>✝️ My church organized a hospital visit, we made food and gave water bottles for the people who were waiting outside, we prayed for them and the patients in need as well.</p>
</li>
</ul>
<h2 id="watching">Watching</h2>
<ul>
<li><strong>Project Hail Mary</strong> - This was a fantastic movie in my opinion. It rushed through a lot of the details of the book, but it was fun and I loved it for what it is. The visuals were stunning and I also have to give props to the soundtrack which felt rather different in many occasions, to what a “Sci-Fi” movie usually sounds like, from time to time. I had a good time!</li>
</ul>
<h2 id="reading">Reading</h2>
<ul>
<li>
<p><strong>To Be Taught, If Fortunate</strong> by Becky Chambers - A novella I suddenly started, about a group of astronauts sending a message back to Earth, or something like that. I actually don’t know much yet, haven’t made a lot of progress.</p>
</li>
<li>
<p><strong>Clarkesworld #211</strong> by Neil Clarke - I completed the second story of the book! It was much longer than the first one, but I actually really, really enjoyed it, it got to the heart strings for a bit, what a nice short story. The next entry is a novella, so I’ll need to focus on it some more.</p>
</li>
<li>
<p><strong>Fly Me To The Moon</strong> - Up to chapter 229. I continued with this slice of life rom-com! It keeps being fun and adorable! While building up and answering some mysteries little by little. Good stuff!</p>
</li>
<li>
<p><strong>Yokohama Kaidashi Kikou</strong> - Up to chapter 70. I made the decision to read 4 or so chapters of this masterpiece, and they were absolutely lovely. Alpha continues on her journey through Japan, and stumbles upon an airport, where she gets to see a plane up close for the first time, and even more surprises. Absolutely lovely.</p>
</li>
<li>
<p><strong>Kingdom</strong> - Up to chapter 867. Still making progress on the war at large, with a side-character stepping up to the role of getting some allies out of trouble, I’m looking forward to know how thigs will fare.</p>
</li>
</ul>
<h2 id="gaming">Gaming</h2>
<h3 id="completed">Completed</h3>
<ul>
<li><strong>Resident Evil</strong> - The gateway into the World of Survival Horror. This classic held up extremely well for its age. IT lacks quite a bit of quality of life features that the sequel contained, but even then, all the basics are there. And not only that but there are some things that are genuinely awesome about it. The Mansion setting is truly great, and some of the puzzles were incredible. I enjoyed it from start to finish, even if it ended up funneling from Metroidvania-style gameplay to linearity, just like the sequel, I didn’t mind at all, I enjoyed the journey a lot. I only played as Jill Valentine though!</li>
</ul>
<h3 id="ongoing">Ongoing</h3>
<ul>
<li><strong>Balatro</strong> - I simply continued to go through a few playthroughs of this game on my phone, I am yet to win still. I’m truly terrible at it, I guess.</li>
</ul>
<h2 id="around-the-web">Around the Web</h2>
<h3 id="blog-posts">Blog posts</h3>
<ul>
<li>
<p><a href="https://axxuy.com/blog/2026/do-you-have-the-time/">Do You Have the Time?</a> - A post and ramble about how buying simple things that were available in physical stores before has been ruined by Amazon, instant shipping and the like.</p>
</li>
<li>
<p><a href="https://rldane.space/i-miss-my-hometown.html">I Miss My Hometown</a> - A trip down RL Dane’s memory lane, and a wonderful conclusion.</p>
</li>
<li>
<p><a href="https://stephvee.ca/blog/crafts/early-efforts-in-sticker-making/">Early Efforts in Sticker Making</a> - A fun project that makes me want to buy one of those sticker cutting machines.</p>
</li>
<li>
<p><a href="https://brennan.day/thats-home-thats-us/">That’s Home. That’s us.</a> - I had not seen <em>Hello, World</em> until today, it made me feel something I didn’t know I could sense. What a photo, what a post.</p>
</li>
</ul>
<h3 id="youtube">YouTube</h3>
<ul>
<li><a href="https://youtu.be/AG79QHM2-2w">Can Ocarina of Time be the Future of Zelda?</a> - Brandon’s video about the latest rumour of Ocarino of Time getting a full remake for the Switch 2, I am incredibly hyped about this, this is what will get me to buy the Switch 2, finally.</li>
<li><a href="https://youtu.be/fl_gGQxGx_c">The ORIGINAL Resident Evil Games</a> - Some guy who played the original trilogy and did a pretty good comparison and shared some thoughts that I found pretty good. I just love these type of videos.</li>
<li><a href="https://youtu.be/spQBojtT_8Q">Setting up a retro gaming corner in my room</a> - I really enjoy this channel and now I kind of want a CRT TV and some old consoles that I never got to own as a kid… oh well.</li>
<li><a href="https://youtu.be/j_AlXChA9F4">The Missions Bringing Us Back To The Moon</a> - Neil</li>
</ul>
<p>This is day 46 of <a href="https://100daystooffload.com">#100DaysToOffload</a></p>
<p>
<a href="mailto:me@joelchrono.xyz?subject=Lost and found bottle, Easter vacation! - W14">Reply to this post via email</a> |
<a href="https://fosstodon.org/@joel/116361362321724248">Reply on Fediverse</a>
</p>