Shellsharks Blogroll - BlogFlock 2026-05-13T00:22:33.858Z BlogFlock Adepts of 0xCC, destructured, fLaMEd, Aaron Parecki, Trail of Bits Blog, James' Coffee Blog, gynvael.coldwind//vx.log (pl), Westenberg, joelchrono, Evan Boehs, Kev Quirk, cool-as-heck, Posts feed, Sophie Koonin, cmdr-nova@internet:~$, <span>Songs</span> on the Security of Networks, Johnny.Decimal, Werd I/O, Robb Knight, Molly White, Hey, it's Jason!, Terence Eden’s Blog Upgrading My Home Internet to Full Fibre - Kev Quirk https://kevquirk.com/upgrading-my-home-internet-to-full-fibre 2026-05-12T18:19:00.000Z <p>As many regular readers know, we live in the North Wales countryside, which means it can take time to get the latest and greatest when it comes to technology.</p> <p>As a result, we were previously "limited" to FTTC (fibre to the cabinet) which had a max speed of 70Mbps. As a result, we got <em>okay</em> internet speeds:</p> <p><img src="https://kevquirk.com/content/images/upgrading-my-home-internet-to-full-fibre/speed-test-before.webp" alt="speed-test-before" /></p> <p>But then I saw the ISP vans in the village, and I asked them what they were doing - <em>"oh, we're upgrading the village to full fibre"</em> she said.</p> <p>I had to have it!</p> <p>As soon as FTTP (fibre to the premises) was available, I placed the order with my ISP (who offered me a great deal that's only £5 per month more), and this is the result:</p> <p><img src="https://kevquirk.com/content/images/upgrading-my-home-internet-to-full-fibre/speed-test-after.webp" alt="speed-test-after" /></p> <h2>Is it worth it?</h2> <p>In all honesty, I haven't noticed the difference. We didn't have any buffering issues when watching things like Netflix or Apple TV, so I'm not really sure why I upgraded in hindsight.</p> <p>I thought it would be this incredible difference where my internet would then be rapid, but the truth is, it's complete imperceptible. I remember when I upgraded from a 56k MODEM, to ~2Mbps broadband and it blew my mind. I was thinking this would be the same, but no.</p> <p>I do think the increased upload speed is going to come in handy when it comes to things like syncing my private <a href="https://kevquirk.com/im-off-github">git repos</a> back to my Synology, but aside from that, there's not much in it.</p> <p>Had I paid full price (~£20 more per month) I don't think I'd have been too happy, but since I got a good deal, I'm not too bothered.</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=Upgrading%20My%20Home%20Internet%20to%20Full%20Fibre">reply to this post by email</a>, or <a href="https://kevquirk.com/upgrading-my-home-internet-to-full-fibre#comments">leave a comment</a>.</p> </div> Go fuzzing was missing half the toolkit. We forked the toolchain to fix it. - Trail of Bits Blog https://blog.trailofbits.com/2026/05/12/go-fuzzing-was-missing-half-the-toolkit.-we-forked-the-toolchain-to-fix-it./ 2026-05-12T11:00:00.000Z &lt;p&gt;Go&amp;rsquo;s native fuzzing is useful, but it stands far behind state-of-the-art tooling that the Rust, C, and C++ ecosystems offer with LibAFL and AFL++. Path constraints are hard to solve. Structured inputs usually need handmade parsing. It doesn’t even detect several common bug classes, such as integer overflows, goroutine leaks, data races, and execution timeouts. So to make it better, we built &lt;a href="https://github.com/trailofbits/gosentry"&gt;gosentry&lt;/a&gt;, a fuzzing-oriented fork of the Go toolchain that keeps the standard &lt;code&gt;testing.F&lt;/code&gt; workflow while using a stronger fuzzing stack underneath to tackle those issues.&lt;/p&gt; &lt;p&gt;With gosentry, &lt;code&gt;go test -fuzz&lt;/code&gt; uses LibAFL by default. It can fuzz structs natively, run grammar-based fuzzing with Nautilus, detect bug classes that it couldn’t detect before, and create a fuzzing campaign coverage report in one command.&lt;/p&gt; &lt;p&gt;If you already have Go fuzz harnesses, you don&amp;rsquo;t need to rewrite them. Point them at gosentry&amp;rsquo;s binary and you get all of the above through the same &lt;code&gt;go test -fuzz&lt;/code&gt; interface, with a few new flags:&lt;/p&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./bin/go &lt;span class="nb"&gt;test&lt;/span&gt; -fuzz&lt;span class="o"&gt;=&lt;/span&gt;FuzzHarness --focus-on-new-code&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; --catch-races&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; --catch-leaks&lt;span class="o"&gt;=&lt;/span&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 1: Basic gosentry usage&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;p&gt;gosentry keeps the harness API and changes the engine and the surrounding tooling — you just tweak the CLI.&lt;/p&gt; &lt;p&gt;You can also generate coverage reports from an existing campaign with &lt;code&gt;--generate-coverage&lt;/code&gt;. Run it from the same package with the same &lt;code&gt;-fuzz&lt;/code&gt; target, and no corpus path is needed; gosentry stores the campaign state under Go’s fuzz cache index by package and fuzz target, so restarting the campaign resumes from the existing corpus.&lt;/p&gt; &lt;h2 id="why-we-built-gosentry"&gt;Why we built gosentry&lt;/h2&gt; &lt;p&gt;We started this project after we released &lt;a href="https://blog.trailofbits.com/2025/12/31/detect-gos-silent-arithmetic-bugs-with-go-panikint/"&gt;go-panikint&lt;/a&gt; to improve Go fuzzing’s integer overflow detection. We realized that integer overflow detection wasn’t enough. Go&amp;rsquo;s fuzzing ecosystem was still missing techniques that Rust, C, and C++ researchers already use every day.&lt;/p&gt; &lt;p&gt;We often faced these gaps in our own security work using Go’s vanilla fuzzer:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Program comparisons (path constraints) were impossible to solve: one complex &lt;code&gt;if&lt;/code&gt; branch, and the Go fuzzer could stay stuck forever.&lt;/li&gt; &lt;li&gt;Grammar-based fuzzing was never an option.&lt;/li&gt; &lt;li&gt;Structure-aware fuzzing required additional manual work.&lt;/li&gt; &lt;li&gt;Several Go bug classes would not crash by default or would depend on external libraries, so the fuzzer could reach insecure target behaviors without reporting them.&lt;/li&gt; &lt;li&gt;Generating coverage reports from a fuzzing campaign was cumbersome.&lt;/li&gt; &lt;li&gt;Making the fuzzer crash on critical error logs required manual code changes.&lt;/li&gt; &lt;/ul&gt; &lt;h2 id="same-harness-stronger-engine"&gt;Same harness, stronger engine&lt;/h2&gt; &lt;p&gt;Gosentry keeps the parts Go developers already know:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Write a fuzz target with &lt;code&gt;testing.F&lt;/code&gt;, as usual.&lt;/li&gt; &lt;li&gt;Create your initial corpus with &lt;code&gt;f.Add&lt;/code&gt;.&lt;/li&gt; &lt;li&gt;Pass the input into &lt;code&gt;f.Fuzz&lt;/code&gt;.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Under the hood, gosentry captures the fuzz callback, builds a Go archive with libFuzzer-style entry points, and runs it in-process through a Rust-based LibAFL runner. The API stays familiar, but gosentry enhances the engine, scheduling, detectors, and much more.&lt;/p&gt; &lt;p&gt;We designed it this way to avoid friction for developers and security researchers adopting a new tool. Existing Go harnesses do not need to be ported to a new framework. And since the Go toolchain documentation and usage are already widely integrated into LLM pre-training datasets, an agent can easily use gosentry, as it is a fork of the Go toolchain.&lt;/p&gt; &lt;h2 id="more-bugs-become-visible"&gt;More bugs become visible&lt;/h2&gt; &lt;p&gt;Another added value of gosentry is its capacity to turn more bad behaviors into failures that the vanilla Go fuzzer wouldn’t report.&lt;/p&gt; &lt;p&gt;It includes compiler-inserted integer overflow checks by default and optional truncation checks through the &lt;a href="https://blog.trailofbits.com/2025/12/31/detect-gos-silent-arithmetic-bugs-with-go-panikint/"&gt;go-panikint&lt;/a&gt; integration. It also lets you choose function calls that should stop the fuzzer. For example, you can use the &lt;code&gt;--panic-on&lt;/code&gt; flag to stop fuzzing when &lt;code&gt;log.Fatal&lt;/code&gt; is called. This flag is useful for codebases that log critical errors and keep going instead of panicking and reporting the bug to the user.&lt;/p&gt; &lt;p&gt;It can also catch data race issues using the native Go race detector (&lt;code&gt;--catch-races&lt;/code&gt;), and goroutine leaks through its &lt;a href="https://github.com/uber-go/goleak"&gt;goleak&lt;/a&gt; integration (&lt;code&gt;--catch-leaks&lt;/code&gt;). Finally, timeouts can be caught at fuzz-time to help detect issues like infinite loops.&lt;/p&gt; &lt;h2 id="better-inputs"&gt;Better inputs&lt;/h2&gt; &lt;p&gt;Gosentry improves input quality in two different ways, which solve different problems.&lt;/p&gt; &lt;h3 id="struct-aware-fuzzing"&gt;Struct-aware fuzzing&lt;/h3&gt; &lt;p&gt;Go&amp;rsquo;s native fuzzing accepts only a small set of parameter types, which doesn’t include composite types, such as structs, slices, arrays, and pointers. Gosentry supports fuzzing of these types.&lt;/p&gt; &lt;!-- markdownlint-disable MD010 --&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;FuzzStructInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fuzz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 2: Supported gosentry harness with structured input&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;!-- markdownlint-enable MD010 --&gt; &lt;p&gt;Under the hood, gosentry still mutates bytes. The difference is that it encodes and decodes the composite value for you in a proper way, so you don’t have to invent a custom wire format just to fuzz typed Go inputs.&lt;/p&gt; &lt;h3 id="grammar-based-fuzzing"&gt;Grammar-based fuzzing&lt;/h3&gt; &lt;p&gt;In this mode, gosentry uses &lt;a href="https://github.com/nautilus-fuzz/nautilus"&gt;Nautilus&lt;/a&gt; to generate and mutate grammar-valid inputs while LibAFL still drives the coverage-guided loop.&lt;/p&gt; &lt;p&gt;Let’s imagine you want to fuzz a homemade JSON parser. Without a grammar, most of the time you would generate junk input that wouldn’t even pass the first branches. For example, the fuzzer would mutate &lt;code&gt;{&amp;quot;postOfficeBox&amp;quot;: 123}&lt;/code&gt; to &lt;code&gt;{postOfficeBox&amp;quot;&amp;quot;: &amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;amp;%}&lt;/code&gt;, while a more interesting generated input of &lt;code&gt;postOfficeBox&lt;/code&gt; would be a much larger number like &lt;code&gt;u64.MAX&lt;/code&gt;, giving &lt;code&gt;{&amp;quot;postOfficeBox&amp;quot;: 18446744073709551615}&lt;/code&gt;. In that case, you need grammar-based fuzzing. You define what the structure should be, and the fuzzer generates inputs accordingly. You could write a harness like this:&lt;/p&gt; &lt;!-- markdownlint-disable MD010 --&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;FuzzGrammarJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{&amp;#34;postOfficeBox&amp;#34;:123}`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fuzz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;jsonInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ParseJSONFromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 3: Grammar-based harness for our JSON parser&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;!-- markdownlint-enable MD010 --&gt; &lt;p&gt;The grammar format is a JSON array of rules:&lt;/p&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;\\{\&amp;#34;postOfficeBox\&amp;#34;:{Number}\\}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Number&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{Digit}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Number&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{Digit}{Number}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;6&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;7&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Digit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;9&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 4: Definition of our postOfficeBox JSON grammar&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;p&gt;Just note that grammar mode still feeds bytes or strings to the harness. So your target needs to be able to parse either strings or bytes.&lt;/p&gt; &lt;h2 id="what-it-has-found-already"&gt;What it has found already&lt;/h2&gt; &lt;p&gt;We’ve been running gosentry on a bunch of targets using grammar-based differential fuzzing campaigns and found a number of bugs. We have disclosed some of these issues to Optimism and Revm:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://github.com/ethereum-optimism/optimism/issues/19334"&gt;Unknown batch type panics and causes denial of service in kona-protocol&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/ethereum-optimism/optimism/issues/19333"&gt;Kona and op-node can disagree on brotli channels&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/ethereum-optimism/optimism/issues/19335"&gt;Kona frame parsing mismatch against op-node and OP Stack Specs&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/bluealloy/revm/issues/3458"&gt;Failed deposit in op-revm stopping with &lt;code&gt;OutOfFunds&lt;/code&gt; does not bump nonce, leading to a state root mismatch against other clients&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Those are exactly the kinds of bugs we wanted Go fuzzing to expose. They wouldn’t have been easy to find via the native Go fuzzer, but our grammar-based fuzzer via gosentry was able to easily detect them.&lt;/p&gt; &lt;p&gt;Now, see what you can find. If you already have a Go fuzz target, run it under gosentry and see what it can reach compared to the native Go fuzzer.&lt;/p&gt; &lt;p&gt;The project is available on &lt;a href="https://github.com/trailofbits/gosentry"&gt;GitHub&lt;/a&gt; and includes documentation for each feature described above.&lt;/p&gt; &lt;p&gt;If you’d like to read more about fuzzing, check out the following resources:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Our &lt;a href="https://appsec.guide/docs/fuzzing/"&gt;&lt;strong&gt;fuzzing chapter&lt;/strong&gt;&lt;/a&gt; in the Testing Handbook&lt;/li&gt; &lt;li&gt;&lt;a href="https://blog.trailofbits.com/2024/02/23/continuously-fuzzing-python-c-extensions/"&gt;&lt;strong&gt;Continuously fuzzing Python C extensions&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://blog.trailofbits.com/2020/06/05/breaking-the-solidity-compiler-with-a-fuzzer/"&gt;&lt;strong&gt;Breaking the Solidity Compiler with a Fuzzer&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;As always, &lt;a href="https://trailofbits.com/contact/"&gt;&lt;strong&gt;contact us&lt;/strong&gt;&lt;/a&gt; if you need help with your next Go project or fuzzing campaign.&lt;/p&gt; Position or Perish: The Narrative Blueprint - Westenberg 6a02795c65b5c3000191635d 2026-05-12T10:15:17.000Z <img src="https://www.joanwestenberg.com/content/images/2026/05/photo-1714729482484-b88a505bd588.jpeg" alt="Position or Perish: The Narrative Blueprint"><p>Avis was losing $3.2 million a year; and they&apos;d been unprofitable for thirteen straight.&#xA0;</p><p>In 1962, they sat at number two in American car rental, well behind Hertz, with no plausible path to catching up. Robert Townsend, the new president, hired Doyle Dane Bernbach and asked them to do something useful with the worst hand in the industry.</p><p>The campaign DDB produced ran a single line:&#xA0;</p><p><em>&quot;Avis is only No. 2 in rent a cars. So we try harder.&quot;</em></p><p>Within a year, Avis had moved from $3.2 million in losses to $1.2 million in profit. The cars hadn&apos;t changed. The locations hadn&apos;t changed. The pricing hadn&apos;t changed; but the story they told about themselves had, and they let that story do the work.</p><h2 id="what-positioning-is"><strong>What positioning is</strong></h2><p>Positioning is the answer to a question every customer asks before they decide whether to care about your product: &quot;What is this, and why should it matter to me right now?&quot;</p><p>Before you have a product, and well before you have an investor, you need to have an answer to that question - and you need it in a single // simple sentence. Nobody is going to do the cognitive work for you; they&apos;ll categorise your product based on whatever signal they catch in the first three seconds, and the category, once set, is near-impossible to dislodge.</p><p>The category - the box they put you in - determines who you compete with, what price they expect to pay, what features they expect you to have, and what story you&apos;re allowed to tell. Get the category right and you set the terms; get it wrong and you spend the rest of your life arguing with the market about who and what you are.</p><p>Al Ries and Jack Trout published <em>Positioning: The Battle for Your Mind</em> in 1981. The book makes a forty-year-old argument that the war is fought in the customer&apos;s head, where there&apos;s no spare room and no patience for new claims.</p><h2 id="the-most-expensive-mistake-founders-make"><strong>The most expensive mistake founders make</strong></h2><p>The vast majority of founding teams treat positioning as a marketing exercise: Something the marketing team does after the product is built; something you put on the homepage when you&apos;re ready to launch.</p><p>This is both wrong - and expensive.</p><p>Positioning is upstream of marketing. It&apos;s upstream of product, pricing, hiring, fundraising, and PR. It determines what you build, who you sell to, what you charge, and what investors think you are. A company with clear positioning ships faster and raises at higher multiples because every decision flows from the same understood centre.</p><p>A company without clear positioning ships features that contradict each other and hires people who can&apos;t agree on what the company does.</p><p>I&apos;ve worked with companies that had product-market fit and were still failing because no two people inside the building could finish the sentence: &quot;We are the _____ for _____.&quot; When the founders can&apos;t agree, the sales team improvises, and the marketing team writes copy that doesn&apos;t ladder up to anything coherent.</p><h2 id="the-messaging-spine"><strong>The messaging spine</strong></h2><p>Every positioning piece should open with a messaging spine. It&apos;s the series of claims and narrative touchpoints that hold up an entire company. Decks, websites, sales scripts, hiring materials etc all come later.</p><p>A spine has four parts.</p><ol><li>The first is the category. What kind of thing are you? What bucket do you belong in? A category is a shortcut, telling the customer how to think about you in a half-second of attention. If your category is wrong or fuzzy, every downstream message leaks energy trying to fix it.</li><li>The second is the audience. Who is this for, in specifics? &quot;Businesses,&quot; &quot;developers,&quot; and &quot;creators&quot; are broad nouns that fall apart under any pressure. A real audience description names a role and a moment. &quot;Heads of compliance at mid-market fintechs trying to pass their first SOC 2&quot; is an audience. &quot;Modern professionals&quot; is a hallucination.</li><li>The third is the alternative. What are they doing today instead of using you? This is the question most founders skip, and it&apos;s the one that matters most. Customers don&apos;t compare you to nothing. They compare you to the spreadsheet they&apos;ve used for eight years, to the agency they hired last quarter, to the open-source tool they already know, or to the colleague who handled it last month. Until you name the alternative, you can&apos;t claim the wedge.</li><li>The fourth is the wedge. What&apos;s the single sharp thing you do better than the alternative? One thing, expressed so cleanly that a customer can repeat it back to a colleague without stumbling.</li></ol><p>When the spine is right, every other piece of copy in the company writes itself.</p><h2 id="narrative-is-positioning-told-over-time"><strong>Narrative is positioning told over time</strong></h2><p>Positioning is the static claim, but narrative is the moving picture.</p><p>A company can hold a single positioning statement for years, and most should; but the narrative around that statement has to evolve, because the world evolves and your competition evolves with it.</p><p>Stripe&apos;s positioning has been close to constant since 2010: payment infrastructure for the internet. The narrative around it has cycled through a dozen variations; in the early years they talked to developers about seven lines of code. By 2015 they were talking to CFOs about reducing fraud and reconciliation overhead. By 2020 they were telling Fortune 500 boards that they were the operating system for global commerce. But the spine held steady across each story.</p><p>Most companies get this backwards; they keep the narrative fixed and let the positioning drift. The pitch deck still says what it said three years ago, while the product has wandered into a new category and the leadership team is pretending it hasn&apos;t.</p><p>The remedy is to write the spine down, share it with everyone who joins the company, and revisit it once a year with the discipline of a financial audit.</p><h2 id="position-against-something-specific"><strong>Position against something specific</strong></h2><p>Every position works through contrast. The claim says you&apos;re better than something, simpler than something, more honest than something, or designed for someone the alternative ignores.</p><p>When Salesforce launched in 2000, they positioned themselves against &#x201C;software&#x201D; itself. &quot;No software.&quot; Every piece of collateral pointed at the same enemy: installed enterprise software that took twelve months to deploy and cost millions in services. Customers didn&apos;t have to understand SaaS as a category. They had to understand they were tired of waiting for IT to install Siebel.</p><p>Pick your enemy with care. It should be big enough to matter, recognisable enough that customers already have an opinion about it, beatable enough that your wedge works against it, and unable to follow you into the corner you&apos;re claiming.</p><p>The wrong enemy is another startup nobody&apos;s heard of. The wrong enemy is the abstract status quo of &quot;manual processes,&quot; because nobody buys against an abstraction. The right enemy has either a name and a market cap, or a behavioural pattern your audience can picture without effort.</p><h2 id="the-category-gambit"><strong>The category gambit</strong></h2><p>Sometimes the right move is to claim an existing category.</p><p>Sometimes the right move is to invent a new one.</p><p>Inventing a category is harder and more expensive than founders think. The standard venture advice is to &quot;create a new category and dominate it,&quot; and most who try this fail because they don&apos;t have the budget, the airtime, the patience, or the distribution to teach the market a new word.</p><p>When category creation works, it&apos;s because someone with serious distribution put their full weight behind a single term until the market repeated it back. HubSpot did this with inbound marketing. Drift did it with conversational marketing. Gong did it with revenue intelligence. Datadog did it with observability. Each company spent years publishing books and running conferences under a single banner until journalists and analysts stopped questioning whether the category was real.</p><p>If you&apos;re a seed-stage company with $2 million in the bank, you can&apos;t afford to create a category; but you can afford to claim a corner of an existing one, and own it harder than anyone else does. This is the Avis play: you don&apos;t need to invent the rental car. You need to be the company that tries harder than Hertz.</p><p>The category gambit gets misread because the visible examples are the winners. The failed attempts at category creation don&apos;t get studied. For every Drift, there are twenty companies that tried to coin a term, ran out of money before the market adopted it, pivoted into someone else&apos;s category, and disappeared from view.</p><h2 id="what-investors-actually-buy"><strong>What investors actually buy</strong></h2><p>Founders raising venture money tend to treat the pitch deck as a product spec. The deck explains what the product does, how the technology works, why the team is qualified to build it, and how the market is large enough to matter.</p><p>This is also wrong.</p><p>Investors fund stories about products. The deck is a narrative artefact, and its job is to make a partner at a fund repeat your story in a Monday morning meeting without garbling it. If the story collapses when an underprepared partner retells it on three hours of sleep, the deck has failed at the only thing decks exist for.</p><p>The best decks I&apos;ve worked on open with a claim about the world. The product comes in around slide six, after the world has been described in a way that makes the product feel inevitable. Something has changed, something is broken, and the audience half-believes it already but hasn&apos;t seen it written down with any precision.</p><p>Founders skip this because they think the world-claim is obvious. It rarely is, even to the founders who built the company. The investor sees fifteen decks a week and starts each one cold. The first three slides install the worldview that makes everything that follows feel like the logical conclusion of a premise they&apos;ve already accepted.</p><h2 id="copy-as-evidence"><strong>Copy as evidence</strong></h2><p>Every word on the homepage either confirms the positioning or contradicts it. There&apos;s no such thing as neutral copy and there should be no such thing as filler. A hero headline that says &quot;Empower your team&quot; contradicts the positioning of every company that uses it, because the words do no work and the customer has read the same line on a hundred other websites that week.</p><p>Specific words confirm positioning; vague words dissolve it. &quot;We process two billion dollars a year in same-day payouts for marketplaces&quot; is a positioning sentence. &quot;We make payments easy&quot; is a marketing hallucination that any company in the category could have written.</p><p>A good test: take your homepage copy, swap your company name for a competitor&apos;s, and see if the sentences still make sense.</p><p>If they do, you&apos;ve written wallpaper.</p><p>The same test applies to investor decks, sales scripts, hiring pages, and press releases. If a competitor could lift your copy verbatim and use it without changing anything, you&apos;ve written nothing of your own.</p><h2 id="the-pricing-tell"><strong>The pricing tell</strong></h2><p>A consultancy charging $4,000 a month is in a different category from one charging $40,000 a month, regardless of what either website claims. A SaaS product priced at $19 a seat competes in a different market from one priced at $19,000 a year, even when the feature lists overlap. The price tells the customer which competitive set you&apos;re in, and the customer believes the price more than they believe the copy.</p><p>Founders who underprice are doing it because they don&apos;t trust their own positioning. They worry that customers will balk, so they hedge by setting a number nobody could object to. The result is that nobody treats them as serious peers, because cheap reads as low-stakes, and low-stakes products don&apos;t get bought by buyers with real budget authority.</p><p>The correction is to price for the position you want, and let the positioning catch up to the number. If the plan is to sell to enterprise, an SMB price contradicts the plan on contact.</p><p>The number itself is a positioning claim, and underpricing is a way of telling the market you don&apos;t believe what your own homepage says.</p><h2 id="hiring-is-downstream-of-narrative"><strong>Hiring is downstream of narrative</strong></h2><p>People want to work for companies whose story they can repeat at a dinner party without sounding ridiculous. If your narrative is sharp, you can hire above your weight class. If it&apos;s muddy, every hire becomes a war.</p><p>I&apos;ve watched companies with worse products win senior hires from companies with better products, because the narrative was clearer and the candidates could picture themselves inside it. The folks who are actually in demand evaluate the story before the feature set. They want to know whether the story they&apos;ll tell their next employer about this job will sound impressive or embarrassing. We&#x2019;re all climbing the ladder. Your story has to place you one rung up.</p><p>The same logic applies to retention. The best people leave when they can no longer explain what the company is doing. They leave before the bad ones do, because the bad ones don&apos;t have other options, and the good ones run the calculation every six months.</p><p>A clear positioning is a retention tool. It tells your best engineers why their work matters at the scale of the company, and it lets them say something coherent at parties when someone asks where they work.</p><h2 id="when-to-reposition"><strong>When to reposition</strong></h2><p>Repositioning is the most dangerous play in the manual. Done well, it can rescue a stalled company in a quarter; done badly, it can torch ten years of accumulated meaning in a week.</p><p>A company should reposition when one of four things happens.</p><ol><li>The market has moved underneath the original claim, and the position now describes a world that no longer exists.</li><li>The product has expanded into territory the original claim can&apos;t cover, and customers are confused about what they&apos;re actually buying.</li><li>A competitor has captured the language you used to own, and the contrast has stopped doing the work it used to do. Or,</li><li>the founders have learned something material about who their best customers are, and the original audience description has stopped matching the people writing the cheques.</li></ol><p>Repositioning that happens because the founders are bored with their own message will always fail; personal boredom is not a strategic signal. The customer hasn&apos;t heard the message yet. The customer is just starting to remember it. Throwing it out because the founders have repeated it a thousand times is throwing out the only thing the market has begun to recognise.</p><p>Most repositioning attempts try to rewrite everything, and most fail because the new version has no equity, no recognition, and no proof points. A surgical change at the wedge or the alternative is easier to absorb than a full rebrand of the category and audience.</p><h2 id="founders-as-narrators"><strong>Founders as narrators</strong></h2><p>Every founder is the chief narrator of the company, whether they want the role or not. Investors read founders; hires read founders; and customers read founders. The way the founders talk about the company in informal settings tells the market more than any campaign ever will.</p><p>The founders who win at this discipline share two habits.</p><ol><li>They use the same vocabulary to describe the company across every audience, so the deck, the all-hands speech, the analyst briefing, and the dinner-table answer to a stranger all sound like they came from the same head.</li><li>They resist the temptation to update the story every time a journalist asks a clever question, because they understand that the question is a test of conviction, not an invitation to redesign the company in real time.</li></ol><p>Founders who lose at this discipline tend to do the opposite. They tailor the story to whoever&apos;s in the room. The deck says one thing, the all-hands says another, the analyst briefing says a third, and the dinner-table answer says a fourth. Over time the company loses the ability to say anything at all, because nobody inside it can agree on what the company is.</p><p>The fix is the spine again. Write it down, read it out loud, and use the words themselves. The discipline is to bore yourself with your own message a decade before the market starts repeating it back, and to keep saying the same true thing while competitors burn their oxygen on rebrands every eighteen months.</p><h2 id="what-to-do-this-week"><strong>What to do this week</strong></h2><p>Skip the rebrand for now. Sit five people in a room and finish the sentence: &quot;We are the _____ for _____ who want to _____ instead of _____.&quot;</p><p>The blanks are the spine: category, audience, outcome, alternative.</p><p>If everyone in the room agrees on the completed sentence, the company has working positioning. If the sentence doesn&apos;t read cleanly to everyone, no amount of homepage redesign or paid advertising will fix the underlying problem, because the underlying problem is that the company doesn&apos;t know what it is.</p><p>Run the exercise this week. Don&apos;t leave the room until the sentence reads cleanly. Then check it against the homepage, the deck, the sales script, and the latest job posting. Anything that contradicts the sentence is a leak in the spine. Patch the leaks one by one, and don&apos;t open a new marketing channel until they&apos;re closed.</p><h2 id="the-longer-game"><strong>The longer game</strong></h2><p>Positioning is a posture you hold for years, not a campaign you run for a quarter. Companies that hold a clear posture for a decade compound advantages that companies running a fresh campaign every quarter never accumulate.</p><p>Berkshire Hathaway&apos;s annual letter has said the same things, with the same vocabulary, since the 1970s. Buy good businesses at fair prices, hold them forever, trust the underlying math, and ignore the short-term noise. The letter doesn&apos;t change because the position doesn&apos;t change. The position doesn&apos;t change because Warren Buffett worked out what he believed early and refused to negotiate with the market about it.</p><p>You don&#x2019;t have fifty years. At most, at the absolute stretch, you have 2-3 before the company either compounds into something or doesn&apos;t.</p><p>Pick the claim, hold the claim, write everything else from the claim, and let competitors burn their oxygen on rebrands every eighteen months while you keep saying the same, damned, true ~thing.</p> Announcing Wonders of Web Weaving - James' Coffee Blog https://jamesg.blog/2026/05/12/announcing-wonders-of-web-weaving 2026-05-12T00:00:00.000Z <p>If you have ever spoken to me, you may have heard me express a meandering interest in doing something with audio. I think the heart of this interest is that I love conversations and storytelling. I love hearing people talk about the things that make them light up. I love asking questions. I enjoy the feeling where you feel like you see the world in a new light after having spoken with someone.</p><p>With all that in mind, a few weeks ago I had an idea: I could interview people who love the web and chat about all things indie web. This coalesced into an outline for a podcast, which then became <a href="https://web-weaving.jamesg.blog/">Wonders of Web Weaving</a>.</p><p>Every Tuesday for the next fifteen or so weeks, I am going to be releasing an episode of the show. <a href="https://web-weaving.jamesg.blog/1/">The first episode is with Adam, the creator of omg.lol and maintainer of many wonderful web projects</a>.</p><p>I named the podcast the way I did because web weaving – making websites and the community around doing making websites – really is wonderful. After the first interview, I felt I had made the right choice in the name – the magic of the web permeates through so much of the indie web.</p><p>The show has its own website, which has an <a href="https://web-weaving.jamesg.blog/subscribe/" rel="noreferrer">RSS feed you can use to follow along with episodes</a>. Each episode will be accompanied by a hand-written transcription, available on the web page for each episode.</p><p>I am thinking of the next fifteen weeks as either season one, or the entirety of the show. Whether there will be another season, I’m not sure. For now, I’m challenging myself to commit to fifteen conversations. Having a clear goal towards which I can strive makes the project more sustainable than committing to a recurring show.</p><p>I hope that you all enjoy the show as much as I enjoy recording it. <a href="https://web-weaving.jamesg.blog/1/">The first episode is ready for you.</a></p><script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9fa7f77ada89d230',t:'MTc3ODU3MzYzMw=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&amp;&amp;(document.onreadystatechange=e,c())}}}})();</script> <a class="tag" href="https://web-weaving.jamesg.blog/">Wonders of Web Weaving</a> <a class="tag" href="https://web-weaving.jamesg.blog/1/">The first episode is ready for you.</a> <a class="tag" href="https://web-weaving.jamesg.blog/1/">The first episode is with Adam, the creator of omg.lol and maintainer of many wonderful web projects</a> <a class="tag" href="https://web-weaving.jamesg.blog/subscribe/">RSS feed you can use to follow along with episodes</a> Bridging feels seamless. Behind the scenes, it's a technical marvel - Werd I/O 6a02585fe66c4000011e2a37 2026-05-11T22:29:51.000Z <p>Link: <a href="https://blog.anew.social/bridging-on-a-budget/?ref=a-new-social-newsletter"><em>Bridging on a budget, by Ryan Barrett at A New Social</em></a></p><p>I&#x2019;ve been in awe of <a href="https://snarfed.org/?ref=werd.io">Ryan Barrett</a> since I first met him over a decade ago. He cofounded <a href="https://cloud.google.com/appengine?ref=werd.io">Google App Engine</a> and led engineering at <a href="https://www.color.com/?ref=werd.io">Color Health</a>. His <a href="https://fed.brid.gy/?ref=werd.io">Bridgy</a> tool, which allows people on different protocols and networks to follow and converse with each other, is now the basis of <a href="https://anew.social/?ref=werd.io">A New Social</a>, the open social web non-profit that he runs with <a href="https://augment.ink/?ref=werd.io">Anuj Ahooja</a>. (Disclosure: I&#x2019;m on the board.)</p><p>This post about how he reduced Bridgy costs is brilliantly detailed. It&#x2019;s a good look into what&#x2019;s involved when you need to refactor and reduce cost at scale &#x2014; and what&#x2019;s remarkable is how effective this work actually was.</p><blockquote>&#x201C;The end result of all of this is that we grew from 2k users to almost 150k, added a ton of heavy new functionality, and still managed to optimize and cut down costs from $.15 per active user per month to just $.03 or so.&#x201D;</blockquote><p>But it didn&#x2019;t come easily. When you&#x2019;re connected to the kinds of firehoses that Bridgy needs to be, and serving the kind of traffic it&#x2019;s starting to handle, every optimization really counts. Because it&#x2019;s open-source, you can <a href="https://github.com/snarfed/arroba/issues/88?ref=werd.io">dig down into individual optimizations</a> and follow along each exploration. It&#x2019;s painstaking work and a demonstration of their commitment to financial responsibility. Try vibe coding <em>that</em>.</p><p>Bridgy (and its parent A New Social) exists to help make the individual protocols less important: everyone should be able to collaborate with everyone else regardless of which platform they&#x2019;re using. It&#x2019;s the kind of thing that feels easy in the moment &#x2014; but as this post proves, it&#x2019;s far from simple under the hood.</p> To maintain their independence, publishers are fleeing Substack - Werd I/O 6a025101e66c4000011e2a31 2026-05-11T21:58:25.000Z <p>Link: <a href="https://www.theverge.com/tech/927294/substack-tax-ghost-beehiiv?ref=werd.io"><em>Writers are fleeing the Substack Tax, by Emma Roth in The Verge</em></a></p><p>If you weren&#x2019;t all that bothered about Substack platforming and compensating Nazis, <em>The Verge</em> reports that there&#x2019;s a new reason to be worried: it costs more and its much-touted network doesn&#x2019;t count for much if you&#x2019;re not one of its featured writers.</p><p>Sean Highkin of <em>The Rose Garden Report</em> is quoted in the piece:</p><blockquote>&#x201C;&#x201C;When I first joined up, [Substack] gave me a big push and featured me and funneled a lot of traffic to me, which led to a good amount of growth,&#x201D; Highkin says. &#x201C;But once I wasn&#x2019;t one of the &#x2018;new recruited talent&#x2019; they could tout, they stopped featuring me and I saw my growth stagnate.&#x201D;&#x201D;</blockquote><p><a href="https://ghost.org/?ref=werd.io">Ghost</a> (with Ryan Singel&#x2019;s <a href="https://outpost.pub/?ref=werd.io">Outpost</a>) cost less than half and drove a significant increase in subscribers. It&#x2019;s mentioned here alongside Beehiiv and Kit, but is the only truly open-source alternative. That means you <em>can</em> use Ghost&#x2019;s services (as I do), but if you&#x2019;re dissatisfied, you can move to another provider.</p><p>This is in stark contrast with Substack, which has been promoting social media style following relationships over true subscriptions, and only allows creators to export their subscribers should they choose to move. Similarly, Beehiiv starts with open protocols like RSS switched off by default, locking readers into its ecosystem.</p><p>That freedom is important. As <a href="https://www.platformer.news/?ref=werd.io">Casey Newton</a> says in the piece:</p><blockquote>&#x201C;The more important thing is that we have a home on the open web that we control, and whatever anti-creator changes Substack is forced to make in the future to live up to its valuation we won&#x2019;t be affected by.&#x201D;</blockquote><p>Every media company, publisher, and individual creator needs to maintain their platform independence if they want to make independent business decisions. It&#x2019;s good to see more people taking this step, and it&#x2019;s good to see that they have options.</p> Asking platforms to do better won't work. We need to force their hands - Werd I/O 6a01e857e66c4000011e2a01 2026-05-11T14:31:51.000Z <p>Link: <a href="https://mattdpearce.substack.com/p/you-couldnt-create-a-more-anti-news?publication_id=2382711&amp;utm_campaign=email-post-title&amp;r=a98j&amp;utm_medium=email&amp;ref=werd.io"><em>You couldn&apos;t create a more anti-news internet if you tried, by Matt Pearce</em></a></p><p>Matt Pearce, Director of Policy for Rebuild Local News, writes a behavioral economics inspired take on why our current embodiment of the internet is so bad for news and information.</p><p>In particular, he sees the introduction of &#x201C;nudges&#x201D; as being a pro-information feature that search engines, LLM interfaces, and social media platforms could introduce:</p><blockquote>&#x201C;Social media, too, could choose to feature quality news outlets as &#x201C;defaults&#x201D; or provide subtle &#x201C;nudges&#x201D; on content that prompt users to donate or subscribe to the news outlets providing high quality news videos on platforms like Instagram, which don&#x2019;t pay for themselves.&#x201D;</blockquote><p>I happen to particularly agree with his implied criticism of newsrooms going deep on Instagram, which usually leads to vanity metrics going up and to the right but not necessarily to conversions, impact, or revenue. And I think it&#x2019;s true that nudges across all these platforms would have the effect he&#x2019;s hoping for. But I think the tragedy is that there&#x2019;s no real reason why any of these platforms would actually do it.</p><p>The internet as it stands is perfectly optimized for the needs of these platforms: engagement, advertising revenue, and rapid growth. Adding pro-social nudges would add friction to their well-oiled loops and take users off-platform. That&#x2019;s exactly why Google has moved from leading people to the best websites for a query to answering those questions on-page: its own needs are best served by keeping users in one place. For them to make different choices, they would need to be far more benevolent architects than they are.</p><p>So, one path forward is that they need to be <em>forced</em> to do it. This would need regulations to govern the features an information platform can provide, and could have very adverse side effects. We&#x2019;re seeing increased regulations with respect to things like age verification, so introducing regulation is possible &#x2014; but that age verification tech has become a surveillance layer that impacts freedom of speech for vulnerable groups. And if publishers go too far in that direction, for example by dictating that platforms share more ad revenue, the networks might simply stop supporting news content at all, <a href="https://www.cbc.ca/news/politics/online-news-act-meta-facebook-1.6885634?ref=werd.io">as we&#x2019;ve seen in places like Canada</a>.</p><p>Another is to build new platforms that make better choices for the whole ecosystem: more interesting for readers, more supportive of publishers. We&#x2019;re already seeing a resurgence in new open social web platforms as well as a regrowth in older technologies like RSS. But the incumbent platforms aren&#x2019;t going to simply go away; any new pro-social platform has to directly compete with them while also building an ecosystem. Still, I think it&#x2019;s more promising, particularly in a world where incumbent platforms are losing goodwill with the public. The kind of thinking that Matt&#x2019;s done here is very useful in helping to design what those new platforms might look like.</p><p>We&#x2019;re not in a great place and there&#x2019;s a hard road ahead. I&#x2019;m sure of one thing: asking existing platforms to do better is not going to work. So we need to take matters into our own hands.</p> WordPress powers 47% of the web. Now it's more social, too - Werd I/O 6a01da49e66c4000011e29f5 2026-05-11T13:31:54.000Z <p>Link: <a href="https://activitypub.blog/2026/05/05/radical-speed-month-the-reader-meets-the-fediverse/?ref=werd.io"><em>Radical Speed Month &#x2014; The Reader Meets the Fediverse, by Mattias Pfefferle</em></a></p><p>We&#x2019;re closer to the entire web being a social environment than ever before. That&#x2019;s very exciting to me on two fronts. The first is that it&#x2019;s always been the promise of the web that anyone could publish and be heard, and baking in social functionality is a huge part of that. The second is that it undermines the stranglehold that traditional social media platforms have had on the public discourse and democracy itself. We need movements like these to grow.</p><p>So I think it&#x2019;s cool that WordPress.com just shipped some major improvements to its core reader:</p><blockquote>&#x201C;The Radical Speed Month bet: ship three protocol adapters in four weeks, and prove the Reader can become a universal aggregator. RSS / Google Reader API (so any reader app can use WordPress.com as a sync backend), ActivityPub (so Mastodon, Pixelfed, and friends show up natively), and ATProto / Bluesky (because that&#x2019;s where a real chunk of the social-web conversation has gone). One Reader, every protocol you care about.&#x201D;</blockquote><p>In practice, that means that you can read updated content from the web via RSS, the Fediverse, and ATproto from the WordPress dashboard &#x2014; and connect any compatible reader app to that dashboard to make reading more seamless. (I&#x2019;m a die-hard fan of <a href="https://reederapp.com/classic/?ref=werd.io">Reeder Classic</a>, and it sounds like that works.) WordPress is now compatible with <em>reading</em> the whole open social web.</p><p>But, of course, it&#x2019;s WordPress, which is a publishing environment at its heart. It&#x2019;s supported RSS forever, and has supported the Fediverse for a while. Now it supports Bluesky, too. Unlike most readers, which are read-only environments, you can interact with those sources right from your feed, including by publishing posts and replying to other people&#x2019;s.</p><p>That&#x2019;s something the <a href="https://indieweb.org/?ref=werd.io">indie web</a> community has been thinking about forever: people like Aaron Parecki have been <a href="https://aaronparecki.com/2018/04/20/46/indieweb-reader-my-new-home-on-the-internet?ref=werd.io">building their own interactive readers</a> using open web standards, and I remember working on a simple prototype at an IndieWebCamp in Portland.</p><p>But it&#x2019;s also an idea that has become more powerful as the open social web has grown. There are millions of people to interact with &#x2013; all of whom might be publishing from their own websites, on their terms, free from intermediation. May it continue to grow and spread.</p> Find blog posts with missing featured images - and missing alt text - without a plugin - Terence Eden’s Blog https://shkspr.mobi/blog/?p=63594 2026-05-11T11:34:39.000Z <p>WordPress has the concept of "Featured Images". They are the images which show up when you share a blog post on social media or, on some themes, as the "hero" image.</p> <p>How can you quickly and easily find any posts which <em>don't</em> have a featured image?</p> <p>For this, I use <a href="https://wp-cli.org/">WP CLI</a> - it allows you to run complex WordPress actions and queries using the command line. After you have <a href="https://wp-cli.org/#installing">installed WP CLI</a> you can get started.</p> <h2 id="missing-images"><a href="https://shkspr.mobi/blog/2026/05/find-blog-posts-with-missing-featured-images-and-missing-alt-text-without-a-plugin/#missing-images">Missing Images</a></h2> <p>On the command line, run:</p> <pre><code class="language-_">wp eval 'foreach(get_posts(array("post_type"=&gt;"post","post_status"=&gt;array("publish"),"posts_per_page"=&gt;-1,)) as $post){if(get_the_post_thumbnail($post)==""){$post_type_object=get_post_type_object($post-&gt;post_type);$link=admin_url(sprintf($post_type_object-&gt;_edit_link . "&amp;action=edit", $post-&gt;ID));echo $post-&gt;post_date . " " . $link . " " . $post-&gt;post_title . "\n";}}' </code></pre> <p>Here's the code in a slightly more readable format:</p> <pre><code class="language-php">foreach ( get_posts( array( "post_type" =&gt; "post", "post_status" =&gt; array("publish"), "posts_per_page" =&gt; -1, ) ) as $post) { if( get_the_post_thumbnail( $post)== "" ) { $post_type_object = get_post_type_object( $post-&gt;post_type ); $link = admin_url( sprintf( $post_type_object-&gt;_edit_link . "&amp;action=edit", $post-&gt;ID ) ) ; echo $post-&gt;post_date . " " . $link . " " . $post-&gt;post_title . "\n"; } } </code></pre> <p>That will print out:</p> <pre><code class="language-_">2024-05-02 12:34:11 https://example.com/wp-admin/post.php?post=123&amp;action=edit "A post about sausages" 2023-09-13 20:55:52 https://example.com/wp-admin/post.php?post=456&amp;action=edit "I like cheese" 2021-12-31 15:43:33 https://example.com/wp-admin/post.php?post=789&amp;action=edit "Touching computers" </code></pre> <p>You can then go and edit each of those posts to add a featured image.</p> <h2 id="missing-alt-text"><a href="https://shkspr.mobi/blog/2026/05/find-blog-posts-with-missing-featured-images-and-missing-alt-text-without-a-plugin/#missing-alt-text">Missing Alt Text</a></h2> <p>Adding alt text means that people who can't see images will still be able to understand what the picture represents. Here's another one-lines to find all featured images with missing alt text:</p> <pre><code class="language-_">wp eval 'foreach (get_posts(array("post_type"=&gt;"post","post_status"=&gt;array("publish"),"posts_per_page" =&gt; -1,)) as $post){if(simplexml_load_string(get_the_post_thumbnail($post))["alt"]==""){$post_type_object=get_post_type_object($post-&gt;post_type);$link=admin_url(sprintf($post_type_object-&gt;_edit_link . "&amp;action=edit",$post-&gt;ID));echo $post-&gt;post_date . " " . $link . " " . $post-&gt;post_title . "\n";}}' </code></pre> <p>And, in slightly more readable form:</p> <pre><code class="language-php">foreach ( get_posts( array( "post_type" =&gt; "post", "post_status" =&gt; array("publish"), "posts_per_page" =&gt; -1, ) ) as $post) { if( simplexml_load_string( get_the_post_thumbnail( $post ) )["alt"] == "") { $post_type_object = get_post_type_object( $post-&gt;post_type ); $link = admin_url( sprintf( $post_type_object-&gt;_edit_link . "&amp;action=edit", $post-&gt;ID ) ) ; echo $post-&gt;post_date . " " . $link . " " . $post-&gt;post_title . "\n"; } } </code></pre> <p>Again, that lists the datetime of the post, its edit link, and its title.</p> <p>No, if you'll excuse me, I have about 873 posts which need updating 🤯</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=63594&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> Hey you, start communicating! - Kev Quirk https://kevquirk.com/hey-you-start-communicating 2026-05-11T08:25:00.000Z <div class="link card"><h2>Hey you, start communicating!</h2><p class="post-author">by David Jamieson</p><p>David talks about why it's good to reach out to authors when you read their content. Even if it's just to say hi.</p><p><a class="button" target="_blank" href="https://forkingmad.blog/hey-you-start-communicating/">Read post ➡</a></p></div><p>Hard agree with David's comments here - he and I regularly exchange emails, actually. I try to reach out to authors whenever I read something that resonates with me. I'll also try to share their work via posts like this too.</p> <p>For me, blogging is the original social network; just because we're on our own spaces doesn't mean we can't be socially connected. That's why I offer comments, and a reply by email link on all posts, including my RSS feed.</p> <p>So yeah, start communicating! 🙃</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=Hey%20you%2C%20start%20communicating%21">reply to this post by email</a>, or <a href="https://kevquirk.com/hey-you-start-communicating#comments">leave a comment</a>.</p> </div> Fear is information. - Westenberg 6a0137c865b5c30001913096 2026-05-11T03:52:45.000Z <img src="https://www.joanwestenberg.com/content/images/2026/05/photo-1568494944313-e93378ba98dd.jpeg" alt="Fear is information."><p>The motivational industry has built any number of small empires on the notion that fear is a problem to be either managed, suppressed or out-manoeuvred. Fight the fear, etc. The language is typically martial - as if fear were a hostile enemy, camped at the gates of your better self.</p><p>But this is sloppy thinking that comes at a cost.</p><p>When the body floods with adrenaline // the mind locks onto a single threat, the system is doing what it evolved to do: reporting on the state of whatever it is you care about. The signal bypasses the conscious mind almost entirely; which is why you can spend years lying to yourself about what you want and still flinch at the wrong moment when the thing you value comes under threat.</p><p>My basic claim is this. When someone (anyone, everyone) is afraid, they&apos;re telling you what they actually value. Their fear is a noisy, but no less precise indicator of both the surface threat and their underlying stake. A founder who keeps delaying their launch has a private worry that has almost nothing to do with the launch itself; they&apos;re deathly afraid of the dissonance between who they&apos;ve been telling people (and themselves) they are and who the market will reveal them to be. The surface object of the fear is misdirection; the actual content is a value statement signed in the writer&apos;s own hand.</p><p>You can argue with the rationalisations that get layered on top of the stake, but you can&apos;t argue with the signal itself.</p><p>People will lie to you about what they want, and they&apos;ll lie to themselves with even greater conviction. But their fear won&apos;t lie, because it can&apos;t. It&apos;s older than language and it runs on a circuit that doesn&apos;t consult the part of the mind responsible for maintaining a neat // tidy story.</p><p>If you want to know what someone actually values, pay attention to what they protect.</p><p>A client who keeps fixating on the timeline is afraid of something other than the difference between three weeks and four. Their fear is tied to a board meeting, or a budget cycle, or personal pressure. A prospect who keeps circling back to price is using the price as a placeholder for a deeper fear about whether they&apos;ll be able to defend their decision if it all goes sideways.</p><p>If you read the fear correctly, you can stop arguing with the placeholder and start addressing the actual stake.</p><p>Your own fear works in much the same way; it&apos;s drawn from a part of you that doesn&apos;t bother with self-deception. When you flinch at sending an email, you&apos;re exporting data about that relationship. When a project keeps slipping in your calendar - whether or not you&apos;ve admitted to deprioritising it - your behaviour is an indicator. The thought of having that one conversation you&apos;ve been putting off makes your stomach turn because you&apos;re responding to a real assessment of the stakes that the &quot;refined&quot; part of your brain has refused to acknowledge.</p><p>I&apos;ve caught myself avoiding decisions for weeks at a time, generating elaborate justifications for the delay, when the actual reason was a single, one-line fear I would&apos;ve been utterly embarrassed to say out loud.</p><p>But the fear is almost always right.</p><p>Even if it&apos;s usually wrong about what to do with the information&#x2026;</p><p>Fear is excellent intelligence, but it&apos;s not much of a strategy. It tells you what&apos;s at risk with high fidelity, and what to do about that risk with all the sophistication of a small mammal in a patch of tall grass; the amygdala, after all, rarely understands either long games or leverage. If you let the part of you that knows what&apos;s at stake dictate your response to that stake, you&apos;ll spend your life flinching away from the things that matter to you and into the things that look superficially safer.</p><p>This is why so much of the advice we give // receive about fear is suspicious of the concept without quite understanding why. People do get controlled by their fear, and that control does produce bad outcomes; but it&apos;s a mistake to conclude that fear is therefore a corrupting influence and that it has to be smothered. The fear is fine - useful, even. The problem is letting an instrument designed for tactical reflexes write the plan.</p><p>Acknowledge the fear and read it carefully; and refuse to be moved by it until you&apos;ve understood what it&apos;s telling you.</p><p>Then decide whether the information changes the plan.</p><p>But stop treating fear as either a master or an enemy. It&apos;s an instrument, and like any instrument, you have to read it and you have to choose what to do with the data it offers.</p><p>The list of things you&apos;re afraid to lose is the most accurate map you have of whatever you&apos;ve built your life around. If you want to know what actually matters to you, watch what your nervous system does when something&#x2019;s threatened. The list might not match the vision document you&apos;d recite on a podcast, but it&apos;s much closer to a source of truth.</p><p>I find that clarifying rather than depressing. </p><p>The world is not as opaque as the official explanations make it look. People are constantly broadcasting what they value, in a frequency older than speech, on a channel they can&apos;t turn off. You only have to learn to listen to it, and be willing to listen to yourself. </p><p>The discipline is the same in both directions; read the signal carefully, and then decide what to do with the information, free of any pressure to obey it.</p> [RSS Club] A Sneak Preview of Upcoming Posts - Terence Eden’s Blog https://shkspr.mobi/blog/?p=71376 2026-05-10T11:34:38.000Z <p><mark><em>Psssst!</em> This <strong>top secret</strong> post is only available to RSS subscribers!</mark></p> <p>As a little thank-you for being a member of <a href="https://daverupert.com/rss-club/">RSS Club</a> I thought I'd show you some trailers for upcoming blog posts.</p> <p>I use the brilliant <a href="https://editorialcalendarwp.com/">Editorial Calendar Plugin</a> to organise all my scheduled blog posts. Here's what you can expect over the next month:</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/05/calendar.webp" alt="List of blog posts in a calendar layout. They are Put an AV test at the start of your slides. Stupidly Simple SVG Sparklines. Find blog posts with missing featured images - and missing alt text - without a plugin. This blog is written in en-GB. Game Review: Lovers In A Dangerous Spacetime. Death to px, long live ch!. Which age-gates should be skill-gates and vice-versa?. PHP - simple way to send HTTP headers before a script ends. Are Index Funds a Socialist Plot to Destroy America?. The UK Government's Low Value Purchase System is a Waste of Time. Whale Fall. Using FourSquare's API to post location checkins to social media. Virgin Media Hub 5 API. There's still no point in gigabit broadband." width="1609" height="835" class="aligncenter size-full wp-image-71378"> <p>I tend to write in bursts - rather than once per day - and then spread the posts out. As I'm going on a long break soon, I want to make sure there are plenty of posts in the queue. There are also a bunch of posts scheduled over the next few years on specific dates.</p> <p>Of course, if I unexpectedly die, I guess they be <em>post</em>humous…</p> <p>I'm also working on what will be (I hope) a reasonably big political story. I'm under embargo until my media partner publishes it - but I hope it'll go live in the early hours of Tuesday. Stay tuned 😊</p> <p>If there's something you'd like to see me write about, 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=71376&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> I'm off GitHub - Kev Quirk https://kevquirk.com/im-off-github 2026-05-09T15:50:00.000Z <p>Ok, that's it. I'm officially off GitHub. First I moved all of my private repos to my Synology, which was <em>extremely</em> easy to do. I did that around a week or so ago and it's be working great.</p> <p>Then I had to start sorting and moving all my public repos to <a href="https://codeberg.org/kevquirk">Codeberg</a>. Many were archived as I no longer maintained the projects, which left me with just 7 actual repos that I needed to move.</p> <p>Pure Blog/Comments and Simple.css were the most challenging as they all had other people who relied on them, but I managed to get them moved with a little bit of messing around.</p> <p>The others were super simply, I used Codeberg's migration tool to migrate the repos over, the ran a command locally to point my repos to a new target:</p> <pre><code class="hljs language-bash">git remote <span class="hljs-built_in">set</span>-url origin git@codeberg.org:kevquirk/[new-repo].git</code></pre> <p>That's it! Repo migrated.</p> <h2>Thoughts on Codeberg</h2> <p>It's <em>fine</em>. And I don't mean that negatively - there's a lot less going on in the UI than on GitHub, but everything is still familiar and similarly laid out. There's been almost zero learning curve moving from GitHub to Codeberg, so props to the Codeberg team for that.</p> <p>I've applied for a <a href="https://join.codeberg.org/">Coderberg membership</a> as I think it's important to support the open source projects we use, so hopefully that will be approved soon.</p> <p>Overall I'm very happy with the move. All the old GitHub repos have had their <code>README.md</code> files updated to point to Codeberg, and they too have been archived.</p> <p>So that's one less piece of big tech I need to rely on.</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%27m%20off%20GitHub">reply to this post by email</a>, or <a href="https://kevquirk.com/im-off-github#comments">leave a comment</a>.</p> </div> Canvas is open source, but its cloud services ransomware attack really hurts - Werd I/O 69ff3bc6e66c4000011e29e1 2026-05-09T13:51:02.000Z <p>Link: <a href="https://www.404media.co/the-biggest-student-data-privacy-disaster-in-history-canvas-hack-shows-the-danger-of-centralized-edtech/?ref=werd.io"><em>&apos;The Biggest Student Data Privacy Disaster in History&apos;: Canvas Hack Shows the Danger of Centralized EdTech, by Jason Koebler at 404 Media</em></a></p><p>I started in edtech. When I graduated with my Computer Science degree, I returned to the university to work at the Media and Learning Technology Service. There, I discovered that all the edtech software at the time was <em>so bad</em> &#x2014; the learners hated it, the teachers hated it, the administrators hated it, and I have to assume the people who made it also had a deep-seated contempt for it &#x2014; that it actively made learning worse. Worse, these platforms were charging institutions huge amounts of money for the privilege.</p><p>Because I was an avid blogger at that time and knew that people were learning from each other on the web all the time, I built a prototype social network for learning and tried to give it to them. They told me they didn&#x2019;t want it (in a way that was much ruder than that). So I quit my job and ended up releasing it under an open source license so it wouldn&#x2019;t be centralized and hold institutions hostage. That act of hubris set up the entirety of the rest of my career.</p><p>Which brings me to this article:</p><blockquote>&#x201C;Thursday afternoon, millions of students at thousands of universities and K-12 schools were locked out of Canvas, a piece of catch-all education technology software that has become the de facto core of many classes. ShinyHunters, a ransomware group, hacked Canvas&#x2019;s parent company and apparently stole &#x201C;billions&#x201D; of messages and accessed more than 275 million individuals&#x2019; data, <a href="https://www.wcnc.com/article/news/nation-world/canvas-hack-shinyhunters-schools-students-teachers-data-exposed/507-0f3f5973-3d68-45af-b309-666561b2bd87?ref=werd.io">according to the hacking group</a>. The group also locked students out of Canvas.&#x201D;</blockquote><p><a href="https://linkletter.org/?ref=werd.io">Ian Linkletter</a> &#x2014; a librarian who has been an active, and in my opinion, unceasingly correct edtech critic &#x2014; is quoted as calling this &#x201C;the biggest student data privacy disaster in history&#x201D;. It need not have been the case; Canvas is theoretically <a href="https://github.com/instructure/canvas-lms?ref=werd.io">open source</a>. But <a href="https://werd.io/open-source-maintainers-need-to-go-in-with-open-eyes/">you can&#x2019;t make money with open source alone</a>, and self-hosting is not something most institutions want to undertake. Canvas is a huge codebase with real quirks that is non-trivial to self-host, and the maintenance and infrastructure costs are real.</p><p>It&#x2019;s also not clear that self-hosted infrastructure would be more resilient: a university could be subject to a ransomware attack with very little recourse. At the same time, the centralized nature of Canvas&#x2019;s core offering means <em>every</em> institution that uses it, <a href="https://www.npr.org/2026/05/08/nx-s1-5815956/canvas-data-breach-school-finals?ref=werd.io">including over half of all US higher education institutions</a>, were in a hard place right in the middle of final exam season. Access is coming back, but at the time of writing, it hasn&#x2019;t been fully restored. It&#x2019;s a hard lesson about the dangers of putting everything in the cloud.</p> Note published on May 9, 2026 at 1:42 PM UTC - Molly White's activity feed 69ff39c7b8f2d866aa0c96ec 2026-05-09T13:42:31.000Z <article><div class="entry h-entry hentry"><header></header><div class="content e-content"><p>A recent <i>CoinDesk</i> survey found 73% disapprove of government officials having crypto business ties, yet 55% weren’t aware of Trump’s involvement, and only 17% knew he co-founded World Liberty Financial.</p><p>This underscores why my work at Citation Needed is so necessary.</p><p><a href="https://www.citationneeded.news/signup/">https://www.citationneeded.news/signup/</a></p><img src="https://www.mollywhite.net/assets/images/placeholder_social.png" alt="Illustration of Molly White sitting and typing on a laptop, on a purple background with 'Molly White' in white serif." style="display: none;"/></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp-block"><div class="timestamp">Posted: <a class="u-url" href="https://www.mollywhite.net/micro/entry/202605090933"><time class="dt-published" datetime="2026-05-09T13:42:31+00:00" title="May 9, 2026 at 1:42 PM UTC">May 9, 2026 at 1:42 PM UTC</time>. </a></div></div><div class="social-links"> <span> Also posted to: </span><a class="social-link u-syndication mastodon" href="https://hachyderm.io/@molly0xfff/116544906969922101" title="Mastodon" rel="syndication">Mastodon, </a><a class="social-link u-syndication bluesky" href="https://bsky.app/profile/molly.wiki/post/3mlgequ4j7k2l" title="Bluesky" rel="syndication">Bluesky</a></div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/micro/tag/citation_needed" title="See all micro posts tagged "Citation Needed"" rel="category tag">Citation Needed</a>. </div></div></footer></div></article> Book Review: The Names by Florence Knapp ★★⯪☆☆ - Terence Eden’s Blog https://shkspr.mobi/blog/?p=70668 2026-05-09T11:34:20.000Z <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/the-names-7.jpg" alt="Book cover featuring a man with three shadows." width="180" height="276" class="alignleft size-full wp-image-70669"> <p>This has an excellent narrative structure, some beautiful prose, and I just didn't enjoy it.</p> <p>The story is <a href="https://en.wikipedia.org/wiki/Sliding_Doors">Sliding Doors</a> meets <a href="https://en.wikipedia.org/wiki/Same_Time,_Next_Year_(play)">Same Time Next Year</a> mixed with a distressing amount of domestic violence.</p> <p>A mother faces a difficult choice. Should she name her child after her abusive and violent husband? In one strand she does, in another she doesn't, and in the third she makes a compromise. We rejoin the story every few years to see how our protagonists are progressing.</p> <p>It mostly works and pushes us to consider how much the path of our life is influenced by factors outside of our control.</p> <p>I have a real difficulty with books about violence. All of the characters are unsympathetic - trapped by tyrant but also trapped by their own inaction. I also struggled with how pedestrian and limited it was. In a world where you can read anything, why would you choose to spy on your horrible neighbours? Like a tawdry soap-opera it offered nothing more than misery and heartbreak. Fine if you need that sort of substitute empathy, but it left me feeling grubby and unsatisfied.</p> <p>To be fair, the characters in the book address this:</p> <blockquote><p>‘Why read them if they make you feel bad?’</p> <p>‘Because I’m hoping one of them might feel like me,’</p></blockquote> <p>It isn't a <em>bad</em> book - although it does veer into cliché a little too often - and the structure is interesting enough. But I found its subject matter too distressing to be enjoyable,</p> <h2 id="book-club-discussion"><a href="https://shkspr.mobi/blog/2026/05/book-review-the-names-by-florence-knapp/#book-club-discussion">Book Club Discussion</a></h2> <p>This isn't the sort of book I'd normally pick up - but it was chosen by the book club I attend. The majority of readers rated it higher than I did. Here are some of the things we discussed.</p> <p>The central message sees to be that, no matter how hard you try, the tragedy which infects your life can never be escaped. I found that depressing and disempowering. The domestic dreariness was stifling and just left me irritated with the passivity of the characters.</p> <p>The evil father is an arsehole - but a <em>one-dimensional</em> arsehole. I get that there's a risk to humanising an antagonist, but other than a brief mention of his back-story there's nothing about him. I didn't want a <em>justification</em> for his actions, but he felt like a cartoon villain.</p> <p>Even when one character gains a moment of happiness, it is offset by another's misery. No matter which path is chosen, someone always ends up broken.</p> <p>Are we "destined" to meet the same people, no matter what path we take?</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70668&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> How Many Mildliner Mix Colours Are There? - Robb Knight • Posts • Atom Feed https://rknight.me/blog/how-many-mildliner-mix-colours-are-there/ 2026-05-09T10:58:44.000Z <p>A couple of weeks ago <a href="https://bencardy.co.uk">Ben</a> was kind enough to send me <a href="https://rknight.me/notes/202604201342/">a 3-pack of Mildliner Mix pens</a> — two-colour highlighters made by Zebra. This led me down a path of looking for the second set called &quot;Cool&quot; but the price of shipping meant I would have been paying ~£5 a pen which I wasn't willing to do.</p> <p>Then this week, as I am want to do, I went over to <a href="https://stationerypal.com">Stationery Pal</a> (that website is riddled with ads just a heads up) and they had a big banner on the home page about a <em>ten</em> pack of Mildliner Mix so I ordered them immediately. And if my maths is correct, ten is more than six, which is how many I was aware of until that moment. This was the image they had which I downloaded so I could update the <a href="https://mildliners.rknight.me">Mildliner site</a>.</p> <figure><img src="https://cdn.rknight.me/site/2026/zebra-mildliner-mix-chart-ten-pack.jpg" alt="A chart showing ten different colour combinations for Mildliner mix pens with their names below each one" /></figure> <p>I started adding them to the site and noticed that one of the colours I already had, Red and Gold, isn't going to be in the pack I ordered. I went back to <a href="https://www.zebrapen.com/products/mildliner-mix?variant=42742951084238">Zebra's website</a> and there's no mention of these additional colours, just the original six. So eleven is the number.</p> <p>I'm down a rabbit hole now thinking about rebuilding the reference site, working out how many of the <a href="https://www.zebrapen.com/products/mildliner-dot-stamp-assorted?variant=43095402741966">dot and stamp marker versions</a> there are, and if there's a secret extra one in the brush versions like there is in other ranges. Very normal stuff.</p> A new website, and a focus on small business - Johnny.Decimal https://johnnydecimal.com/blog/0193-a-new-website-and-focus-on-sbs/ 2026-05-09T04:02:40.000Z <p>For me, looking back through this website’s version history is like watching the final scenes of <em>Interstellar</em>. Years fly by; visuals of who we were two, three years ago. Three years feels so close but then you <a href="https://web.archive.org/web/20230428133318/https://johnnydecimal.com/">see this page</a> and: <em>no</em>, it just can’t be! That page looks so <em>old</em>.</p> <p>And so it is again. What started as an ID born in Japan – <code>41.14 New design language</code> – became an all-consuming project. As they do. I don’t even remember when it happened. One day I <em>wasn’t</em> rewriting all of our websites, the next day I was, and the git history tells me that was about 10 weeks ago. Time has lost all meaning.</p> <p>The major change is that there’s just one website now: <a href="https://johnnydecimal.com">johnnydecimal.com</a>. Last year I created JDHQ as its own thing because at the time integrating it with the main site would have been impossibly difficult. But the goal was never to have two websites.</p> <p>I still like the term ‘JDHQ’, and will continue to use it to refer to the interactive parts of the site: the bits where you sign in and do a thing. (You can <a href="https://johnnydecimal.com/sign-up/#pricing-email">create a free account</a> now.) It has a bright future; more below.</p> <h2 id="a-focus-on-small-business">A focus on small business</h2> <p>Before I talk more about the website, a point that I think is more important. We’ve made a decision to focus all of <em>our</em> efforts, as a business, on helping other small businesses.</p> <p>There’s so much overhead when you run a business, and when you’re small, you have to do it all yourself. With last year’s <a href="https://johnnydecimal.com/sbs/">Small Business System</a> (SBS) we hoped to give you a space to put everything: a hundred less decisions to make. Our dream was always to expand to become your ‘operations layer’, to provide you ops manuals and guidance and support. So that’s what we’ll be doing from now.</p> <p>You’ll find a calendar you can subscribe to in the sidebar of your SBS. The first events – 4× welcome Zoom sessions spread across timezones – are scheduled for next week. There’s also a WhatsApp group for our small business customers. Our job now is to support you: to make your life easier. Tell us what you need to succeed.</p> <p>Information will still flow to the rest of the system. Problems solved for small business are problems we all face; tools built to help them will help you at home.</p> <h2 id="no-more-numbers">No more numbers</h2> <p>The previous site assigned an ID to every page. This was a cute affectation – and that sidebar table of contents was a crowd favourite – but ironically limiting.</p> <p>The Johnny.Decimal system wasn’t designed to hold a preset list of pages in a specific order, but that’s what the old site did. This is in direct conflict with one of the major benefits of the web over print: you can update a website whenever you want. By giving each page a number, I inadvertently made the old site behave like a book.</p> <p>As a result, it scarcely changed. There’s content that I haven’t published because I would have had to figure out how to fit it into the structure. That’s no way to run a website. So the numbers have gone.</p> <p>(Technically, we do still have an ID for each page on the site. These are IDs in my own SBS and they allow us to store the artefacts for each page, e.g. the diagrams. You’ll see these IDs in the figure reference numbers. They’re meaningless and confer no order; which is how it’s meant to be.)</p> <h2 id="aspirationally-calm">‘Aspirationally calm’</h2> <p>Our design goal was to make a place of calm. The internet is very shouty these days. There’s a lot competing for your attention. I wanted our place to be somewhere you could relax.</p> <p>So there’s a lot more room. And maybe less of what gave the old site ‘character’? The ▒ shade characters at the start of headers have gone. The thick borders have gone. The line-drawing ‘brackets’ around navigation items have gone. We did try adding some of that back, but every time we decided: no. Too busy.</p> <p>I’ve been using this design for a month or so and when I go back to the old sites they’re jarring. We refer to them as ‘the old clunkers’. The new place is cohesive, I hope. It’s simple. Because Johnny.Decimal’s job isn’t to get in your face and be all clever. It’s to help you get your work done and then get out of the way.</p> <h2 id="next">Next</h2> <p>I have a <em>lot</em> of plans for JDHQ. This section got long, so I <a href="https://youtu.be/ccOtZPBi0tQ">recorded a roadmap video</a>. I’ll do these at the start of every month from now.</p> <h2 id="housekeeping">Housekeeping</h2> <p>Until an hour ago, there were 4 mailing lists: the ‘public’ list that anyone could sign up to, and a list for each of our products. These latter lists were intended for product updates, but I never used them.</p> <p>I’ve collapsed the lists. There’s just one now and if you got an email today, you’re on it. If you don’t want to be, there&#39;s an unsubscribe link in the footer.</p> <p>The site now has a <a href="https://johnnydecimal.com/support/version-history/">version history</a> whose entries appear in the RSS feed. The RSS feed remains the best way of keeping up to date – see <a href="https://johnnydecimal.com/blog/0118-rss/">RSS: a public service announcement</a> if you don’t know how it works.</p> <h2 id="thank-you">Thank you</h2> <p>We can only do this with your continued support. Thank you – especially to those of you who become lifetime members. It makes a massive difference.</p> <p>I say it every time, and I’ll say it again: tell us what you need. You ask, we make.</p> <p>j.</p> Serendipity - James' Coffee Blog https://jamesg.blog/2026/05/09/serendipity 2026-05-09T00:00:00.000Z <blockquote>The steam of the espresso machine — of focusing in the milk to make sure it is just right, of tapping to remove the bubbles, of preparing. Soft instrumental music plays in the background, more upbeat than the music to which I was listening earlier — easing me more into the day. How the smile of a barista lights up my day. Of noticing the care and attention put into the latte art.</blockquote><p>I have not been to a coffee shop in days, and so this morning – a morning where a drizzle of rain hung over the air, a refreshing air – I felt like I was seeing all of the rituals associated with making a cup of coffee from a new perspective. The care the barista puts into preparing a drink, the sound of the steam wand as it froths milk, the rapport between the staff members.</p><p>A hand-crafted (decaf) flat white was the best possible start to the morning on a day where the only thing I had planned was to have a coffee, read a bit of a book, and wonder “should I go see that movie I want to see?” The movie was The Devil Wears Prada 2. I had not seen the first one, but lots of actors I like appeared in the second one so I thought I would go see it.</p><p>Less than an hour before the morning screening, I booked a ticket. I usually like to prepare more, but perhaps my mind was already made up that I wanted to see the film and I was yet to realise it. It has been a year since I was last at the cinema, so I revelled in the chance to go again to see a movie that looked good. In summary, after watching the movie, I was impressed, and left excited to watch the first one too.</p><p>As I left the movie theatre, on the fourth floor of a shopping centre in the heart of the city, I heard the sound of bagpipes. The fourth floor has an open roof and so the bagpipes could have been coming from anywhere. I felt so much at home in hearing them. Where else in the world could I leave a movie screening and hear bagpipes? That sound was a portend for what was to come.</p><p>While I didn’t necessarily have a plan for the day, the more hours that passed the more I started to piece together things I was thinking about this week. I have started to get back into Magic: the Gathering, watching a few videos online of people playing games. I decided I wanted to go to a trading card shop to at least inquire about what has changed in the format since I last played seriously, nine years ago. It turns out, a lot has changed, but the worlds I could learn about are exciting.</p><p>On my way to the trading card shop, I noticed a crowd of people lining the streets on Waverley Bridge, the scene of a painting I really love. I stopped for a moment and overheard people talking about the event of the day – the tartan parade, dedicated to celebrating all things tartan. Last year, I had encountered the parade under similar circumstances: I was walking around and happened to be in the place where the parade was about to start, not knowing the event was scheduled. A lot has changed since last year, too.</p><p>Having fifteen minutes or so before the parade was scheduled to begin, I got some lunch and waited. Then, with great excitement, I watched the event from beginning to end – an hour of pipe bands, dancers, people from clans across Scotland, people who work for charities in Scotland, and people who have come from all over the world to celebrate tartan. There was a pipe band from Switzerland and contingent of people from Peru, Italy, and more. <em>I love seeing so many people coming together — in so many outfits and from so many places.</em>, I wrote as I was surrounded by music and colour and stories and life.</p><p>Early on in the parade, a larger-than-life (paper?) unicorn was carried by several people. “A unicorn!” remarked a child nearby with great excitement. I was surprised for a split second until I remembered the unicorn is our national animal, my favourite fact to share with people I meet from other places in the world. I can think of no better animal to represent the Scottish attitude than the unicorn – welcoming, playful, and always able to bring colour to a room.</p><p>There were also people dressed as dinosaurs at the parade for a reason I can’t remember. Nonetheless the dinosaurs made me laugh the kind of laugh where you feel nothing but pure joy. The emcee for the parade had some playful banter with the dinosaurs who roared, saying something to the effect of “I’m glad I’m up here” (on the double-decker, open-top bus with tartan livery from where the emcee announced all the groups in the parade) to the dinosaurs below. <em>I’m having a good time</em>, I thought.</p><p>I walked for miles today, from the coffee shop to the theatre, stopping for an hour afterwords to watch the tartan parade, to the card game store and back. Serendipity was my best friend. Then, just as I was getting ready to go home, I saw someone I haven’t seen in months. Seeing them smile and wave as I did the same, my world was brightened, to an extent where despite my best efforts to describe what I was feeling it was impossible to do so. I felt so much less alone than I had the moment before.</p><p>The small things – the warm morning coffee, the smile and wave from a friend, the unicorns; the serendipity of walking without a plan and being open to what you see – really do make life special.</p> Published on Citation Needed: "Issue 105 – The new boogeyman" - Molly White's activity feed 69fdfd6db8f2d866aa0c9684 2026-05-08T15:12:45.000Z <article class="entry h-entry hentry"><header><div class="description">Published an issue of <a href="https://www.citationneeded.news/"><i>Citation Needed</i></a>: </div><h2 class="p-name"><a class="u-syndication" href="https://www.citationneeded.news/issue-105" rel="syndication">Issue 105 – The new boogeyman </a></h2></header><div class="content e-content"><div class="media-wrapper"><a href="https://www.citationneeded.news/issue-105"><img src="https://www.citationneeded.news/content/images/size/w2000/format/webp/2026/05/trump-meme-event.png" alt="Trump, photographed from behind, steps towards a man reaching out to shake his hand from behind a cordon. A crowd of other attendees are mostly taking photos with their cell phones."/></a></div><div class="p-summary"><p>A crypto billionaire who escaped fraud allegations after investing hundreds of millions of dollars into the Trump family’s crypto projects is now accusing them of fraud</p></div></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp">Posted: <a class="u-url" href="https://www.citationneeded.news/issue-105"><time class="dt-published" datetime="2026-05-08T15:12:45+00:00" title="May 8, 2026 at 3:12 PM UTC">May 8, 2026 at 3:12 PM UTC</time>. </a></div><div class="social-links"> <span>Also posted to:</span><a class="social-link u-syndication mastodon" href="https://hachyderm.io/@molly0xfff/116539468955801664" title="Mastodon" rel="syndication">Mastodon</a><a class="social-link u-syndication bluesky" href="https://bsky.app/profile/molly.wiki/post/3mldx2h3dkk2m" title="Bluesky" rel="syndication">Bluesky</a><a class="social-link u-syndication youtube" href="https://www.youtube.com/watch?v=JIUppD0Clhw" title="Youtube" rel="syndication">Youtube</a></div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/crypto" title="See all feed posts tagged "crypto"" rel="category tag">crypto</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/crypto_lobby" title="See all feed posts tagged "crypto lobby"" rel="category tag">crypto lobby</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/justin_sun" title="See all feed posts tagged "Justin Sun"" rel="category tag">Justin Sun</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/trump_administration" title="See all feed posts tagged "Trump administration"" rel="category tag">Trump administration</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/world_liberty_financial" title="See all feed posts tagged "World Liberty Financial"" rel="category tag">World Liberty Financial</a>.</div></div></footer></article>