It Is A War Out There – Take Control of Your Supply Lines with HtDTY

This is a repost promoting content originally published elsewhere. See more things Dan's reposted.

This post advocates minimizing dependencies in web pages that you do not directly control. It conflates dependencies during build time and dependencies in the browser. I maintain that they are essentially the same thing, that both have the same potential problems, and that the solution is the snappy new acronym HtDTY – Host the Damn Thing Yourself.

If your resources are large enough to cause a problem if you Host the Damn Things Yourself then consider finding ways to cut back on their size. Or follow my related advice – HtDToaSYHaBRW IMCYMbT(P)WDWYD : Host the Damn Thing on a Service You Have A Business Relationship With, It May Cost You Money But They (Probably) Won’t Dick With Your Data.

Host the Damn Thing Yourself (HtDTY) is an excellent suggestion; I’ve been a huge fan of the philosophy for ages, but I like this acronym. (I wish it was pronounceable, but you can’t have everything.)

Andrew’s absolutely right, but I’m not even sure he’s expressed all the ways in which he’s right. Here are my reasons to HtDTY, especially for frontend resources:

  1. Security: As Andrew observes, you can’t protect against supply chain attacks if your supply chain wide open to exploitation. And I’m glad that he points out that version pinning doesn’t protect you from this (although subsource integrity can).
  2. Privacy: Similarly, Andrew nailed this one. If you host your fonts on Google Fonts, for example, you’re telling one of the biggest data-harvesting companies on the Internet who’s accessing your website. Don’t do that (in that specific example, google-webfonts-helper is your friend).
  3. Resilience: Every CDN and third-party service you depend upon is another single-point-of-failure. Sure, Azure has much better uptime than your site… but it still goes down and not necessarily at the same times as your site does! And it’s not just about downtime. What if your user’s government poisons the DNS to block the CDN? What if the user’s privacy tools block your CDN’s domain (whether rightly, for the privacy reasons described above, or wrongly)? What if, y’know, you were hosting your images on Imgur but that’s not available in your users’ country? These are all real examples that happen in the real world. Why would you choose to make your site less-reliable by loading jQuery from a CDN rather than just… downloading a copy?
  4. Performance: Andrew rightly deconstructs the outdated argument that CDN caching improves your site’s performance. Edge caching might, in some circumstances, but still has the problems listed above. But this argument can go further than Andrew’s observation that CDNs aren’t that much of a benefit… because sticking to just one domain name means (a) fewer DNS lookups, (b) fewer TLS handshakes, (c) better compression, if e.g. your JavaScript assets are bundled or at least delivered in the same pipeline, and (d) all the benefits of HTTP/2 and HTTP/3, like early hints, pipelining, etc. Nowadays, it can often be faster to not-use a CDN (depending on lots of factors), in addition to all the above benefits.

So yeah: HtDTY. I dig it.

The Scroll Art Museum

This is a repost promoting content originally published elsewhere. See more things Dan's reposted.

Scroll art is a form of ASCII art where a program generates text output in a command line terminal. After the terminal window fills, it begins to scroll the text upwards and create an animated effect. These programs are simple, beautiful, and accessible as programming projects for beginners. The SAM is a online collection of several scroll art examples.

Here are some select pieces:

  • Zig-zag, a simple periodic pattern in a dozen lines of code.
  • Orbital Travels, sine waves intertwining.
  • Toggler, a woven triangular pattern restricted to two characters.
  • Proton Stream, a rapid, chaotic lightning pattern.

There are two limitations to most scroll art:

  • Program output is limited to text (though this could include emoji and color.)
  • Once printed, text cannot be erased. It can only scroll up.

But these restrictions compel creativity. The benefit of scroll art is that beginner programmers can create scroll art apps with a minimal amount of experience. Scroll art requires knowing only the programming concepts of print, looping, and random numbers. Every programming langauge has these features, so scroll art can be created in any programming language without additional steps. You don’t have to learn heavy abstract coding concepts or configure elaborate software libraries.

Okay, so: scroll art is ASCII art, except the magic comes from the fact that it’s very long and as your screen scrolls to show it, an animation effect becomes apparent. Does that make sense?

Here, let me hack up a basic example in… well, QBASIC, why not:

Anyway, The Scroll Art Museum has lots of them, and they’re much better than mine. I especially love the faux-parallax effect in Skulls and Hearts, created by a “background” repeating pattern being scrolled by a number of lines slightly off from its repeat frequency while a foreground pattern with a different repeat frequency flies by. Give it a look!

1% Guild

vole.wtf’s 1% guild wasn’t the easiest club to gain membership of, but somehow keeping my phone alive for long enough to snap this screenshot was even harder.

Screenshot from an Android phone at vole.wtf/one-percent, showing a picture of Dan alongside other people.

×

Hive’s Password Policy Makes Me Cry

Hey, let’s set up an account with Hive. After the security scares they faced in the mid-2010s, I’m sure they’ll be competent at making a password form, right?

Welcome to Hive 'choose a password' form, with no password entered, saying 'your password must be at least 8 characters'.Your password must be at least 8 characters; okay.

Just 8 characters would be a little short in this day and age, I reckon, but what do I care: I’m going to make a long and random one with my password safe anyway. Here we go:

The same form, with the password S1dfCeg7!Ex;C$Ngban9-A entered. The error message now shows 'Your password must be at least 12 characters log, contain at least one uppercase letter, one lowercase letter, one number, and one special character'I’ve unmasked the password field so I can show you what I tried. Obviously the password I eventually chose is unrelated to any of my screenshots.

Now my password must be at least 12 characters long, not 8 as previously indicated. That’s still not a problem.

Oh, and must contain at least one of four different character classes: uppercase, lowercase, numbers, and special characters. But wait… my proposed password already does contain all of those things!

The same form, now with the password 1111AAAAaaaa!!!! which is accepted as valid.Let’s simplify.

The password 1111AAAAaaaa!!!! is valid… but S1dfCeg7!Ex;C$Ngban9-A is not. I guess my password is too strong?

Composition rules are bullshit already. I’d already checked to make sure my surname didn’t appear in the password in case that was the problem (on a few occasions services have forbidden me from using the letter “Q” in random passwords because they think that would make them easier to guess… wot?). So there must be something else amiss. Something that the error message is misleading about…

A normal person might just have used the shit password that Hive accepted, but I decided to dig deeper.

The shit password again, but appended with a semicolon (;) triggers the message.Using the previously-accepted password again but with a semicolon in it… fails. So clearly the problem is that some special characters are forbidden. But we’re not being told which ones, or that that’s the problem. Which is exceptionally sucky user experience, Hive.

At this point it’s worth stressing that there’s absolutely no valid reason to limit what characters are used in a password. Sometimes well-meaning but ill-informed developers will ban characters like <, >, ' and " out of a misplaced notion that this is a good way to protect against XSS and injection attacks (it isn’t; I’ve written about this before…), but banning ; seems especially obtuse (and inadequately explaining that in an error message is just painfully sloppy). These passwords are going to be hashed anyway (right… right!?) so there’s really no reason to block any character, but anyway…

I wondered what special characters are forbidden, and ran a quick experiment. It turns out… it’s a lot:

  • Characters Hive forbids use of in passwords include - , . + = " £ ^ # ' ( ) { } * | < > : ` – also space
  • “Special” characters Hive they allow: ! @ $ % & ?

What the fuck, Hive. If you require that users add a “special” character to their password but there are only six special characters you’ll accept (and they don’t even include the most common punctuation characters), then perhaps you should list them when asking people to choose a password!

Or, better yet, stop enforcing arbitrary and pointless restrictions on passwords. It’s not 1999 any more.

The invalid password but with all the special characters transformed into exclamation points to make it valid.I eventually found a password that would be accepted. Again, it’s not the one shown above, but it’s more than a little annoying that this approach – taking the diversity of punctuation added by my password safe’s generator and swapping them all for exclamation marks – would have been enough to get past Hive’s misleading error message.

Having eventually found a password that worked and submitted it…

Hive error message: 'This activation URL seems to be invalid.'

…it turns out I’d taken too long to do so, so I got treated to a different misleading error message. Clearly the problem was that the CSRF token had expired, but instead they told me that the activation URL was invalid.

If I, a software engineer with a quarter of a century of experience and who understands what’s going wrong, struggle with setting a password on your site… I can’t begin to image the kinds of tech support calls that you must be fielding.

Do better, Hive.

× × × × × ×

Note #27434

Somebody just called me and quickly decided it was a wrong number. The signal was bad and I wasn’t sure I’d heard them right, so I followed up by replying by text.

It turns out they asked Siri to call Three (the mobile network). Siri then presumably searched online, found Three Rings, managed to connect that to my mobile number, and called me.

If Siri’s decided that I represent Three, this could work out even worse than that time Google shared my phone number.

Dogspinner

This is a repost promoting content originally published elsewhere. See more things Dan's reposted.

Dogspinner is the Monday morning distraction you didn’t know you needed. Get that dog up to full speed! (It’s worth it for the sound effects alone.)

I had some difficulty using it on desktop because I use the Forbidden Resolutions. But it probably works fine for most people and is probably especially great on mobile.

I’d love to write a longer review to praise the art style and the concept, but there’s not much to say. Just… go and give it a shot; it’ll improve your day, I’m sure.

Lowriders & websites

This is a repost promoting content originally published elsewhere. See more things Dan's reposted.

I think of ElonStan420 standing in that exhibit hall, eyeing those cars with disdain because all that time, energy, care, and expression “doesn’t really matter”. Those hand-painted pinstripes don’t make the car faster or cheaper. Chrome-plated everything doesn’t make it more efficient. No one is going to look under the hood anyway.

Don’t read the comments on HackerNews, Adam! (I say this, but I’ve yet to learn not to do so myself, when occasionally my writing escapes from my site and finds its way over there.)

But anyway, this is a fantastic piece about functionalism. Does it matter whether your website has redundant classes defined in the HTML? It renders the same anyway, and odds are good that nobody will ever notice! I’m with Adam: yes, of course it can matter. It doesn’t have to, but coding is both a science and an art, and art matters.

Should every website be the subject of maximal craft? No, of course not. But in a industry rife with KPI-obsessed, cookie-cutter, vibe-coded, careless slop, we could use more lowriders.

Well said, Adam.

Hot Boxes

I’d never put much thought into it before but a slow cooker is basically the opposite of an air frier.

They’re both relatively small (compared to an oven) hot boxes for cooking food. But an air frier uses the small space to contain as much energy as possible in thir vicinity of the food, while the slow cooker aims to maintain as low a temperature as possible until the food finally cooks itself out of boredom.

A seared shoulder of pork rubbed with spices sits in a syrupy cider mix atop some sliced white onions in a slow cooker pot.

Anyway, this is going to be pulled pork in like 8-10 hours. 😋

×

Do Contact Forms Attract More Spam than Email Addresses?

There’s a question being floated around my corner of the blogosphere, but I think my experience of the answer differs from other bloggers:

It started when David Bushell observed that, despite having his email address unobscured on his website, he gets more spam via his contact form. Luke Harris followed-up, providing a potential explanation which basically boils down to the idea that it’s both more cost-effective and provides better return-on-investment to spam contact forms than email addresses. And then Kev Quirk described his experience of switching from contact forms to “bare” email addresses and the protections he put in place (like plus-addressing), only to discover that he didn’t need it at all.

Disappearing Contact Forms

It makes me sad to see the gradual disappearance of the contact form from personal websites. They generally feel more convenient than email addresses, although this is perhaps part of the reason that they come under attack from spammers in the first place! But also, they provide the potential for a new and different medium: the comments area (and its outdated-but-beautiful cousin the guestbook).

Comments are, of course, an even more-obvious target for spammers because they can result in immediate feedback and additional readers for your message. Plus – if they’re allowed to contain hyperlinks – a way of leeching some of the reputability off a legitimate site and redirecting it to the spammers’, in the eyes of search engines. Boo!

A DanQ.me comment form pre-filled with a diversity of spam tropes, by 'Spammer McSpamface'.
Well this was painful to write.

But I’ve got to admit: there have been many times that I’ve read an interesting article and not interacted with it simply because the bar to interaction (what… I have to open my email client!?) was too high. I’d prefer to write a response on my blog and hope that webmention/pingback/trackback do their thing, but will they? I don’t know in advance, unless the other party says so openly or I take a dive into their source code to check.

Your Experience May Vary

I’ve had both contact/comment forms and exposed email addresses on my website for many years… and I feel like I get aproximately the same amount of spam on both, after filtering. The vast majority of it gets “caught”. Here’s what works for me:

My contact/comments forms use one of a variety of unobtrustive “honeypot”-style traps. These “reverse CAPTCHAs” attempt to trick bots into interacting with them in some particular way while not inconveniencing humans.

  • Antispam Bee provides the first line of defence, but I’ve got a few tweaks of my own to help counteract the efforts of determined spammers.
  • Once you’ve fallen into a honeypot it becomes much easier to block subsequent contacts with the same/similar content, address, (short-term) IP, or the poisoned cookie you’re given.
  • Keyword filtering provides a further line of defence. E.g. for contact forms that post directly back to the Web (i.e. comment forms, and perhaps a future guestbook form), content with links goes into a moderation queue unless it shares a sender email with a previously-approved sender. For contact forms that result in an email, I’ve just got a few “scorer” rules relating to geo IP, keywords, number and density of links, etc. that catch the most-insidious of spam to somehow slip through.

also publish email addresses all over the place, but they’re content-specific. Like Kev, I anticipated spam and so use unique email addresses on different pieces of content: if you want to reply-by-email to this post, for example, you’re encouraged to use the address b27404@danq.me. But this approach has actually provided secondary benefits that are more-valuable:

  • The “scrapers” that spam me by email would routinely send email to multiple different @danq.me addresses at the same time. Humans don’t send the same identical message to me to different addresses published on my site and from different senders, so my spam filter picks up on this rightaway.
  • As a fringe benefit, this helps me determine the topic on an email where it’s unclear. E.g. I’ve had humans email me to say “I tried to follow the guide on your page but it didn’t work for me” and I wouldn’t have had a clue which page had they not reached out via a page-specific email alias.
  • I enjoy the potential offered by rotating the email address generation mechanism and later treating all previously-exposed addresses as email honeypots.
An email spam inbox. A significant number of detected spam messages have the subject line "PAY OR BE EXPOSED" but have different senders.
They’ve all got different “sender” addresses, but that fact that this series of emails were identical except for the different recipient aliases meant that catching them was very easy for my spam filters.

Works For Me!

This strategy works for me: I get virtually no comment/contact form spam (though I do occasionally get a false positive and a human gets blocked as-if they were a robot), and very little email spam (after my regular email filters have done their job, although again I sometimes get false positives, often where humans choose their subject lines poorly).

It might sound like my approach is complicated, but it’s really not. Adding a contact form honeypot is not significantly more-difficult than exposing automatically-rotating email aliases, and for me it’s worth it: I love the convenience and ease-of-use of a good contact/comments form, and want to make that available to my visitors too!

(I also allow one-click reactions with emoji: did you see? Scroll down and send me a bumblebee! Nobody seems to have found a way to spam me with these, yet: it’s not a very expressive medium, I guess!)

× ×

Note #27400

Did I just rank my LPG provider 10/10, or 1/10? I genuinely don’t know.

Slider from a web questionnaire, asking "In a scale of 0 to 10: How likely are you to recommend Flogas for bulk gas?". The slider below, though, is a scale from 0 to 100, not 0 to 10. The value 10 is selected on the slider, but this is only one-tenth of the way along its length.

×

Impossible Countdown

Or: Sometimes You Don’t Need a Computer, Just a Brain

I was watching an episode of 8 Out Of 10 Cats Does Countdown the other night1 and I was wondering: what’s the hardest hand you can be dealt in a Countdown letters game?

Rachel Riley, wearing a pink and black dress, stands in front of a partially-filled Countdown board showing the letters 'DANQ.ME'.
Or maybe I was just looking for an excuse to open an image editor, I don’t know.

Sometimes it’s possible to get fixated on a particular way of solving a problem, without having yet fully thought-through it. That’s what happened to me, because the first thing I did was start to write a computer program to solve this question. The program, I figured, would permute through all of the legitimate permutations of letters that could be drawn in a game of Countdown, and determine how many words and of what length could be derived from them2. It’d repeat in this fashion, at any given point retaining the worst possible hands (both in terms of number of words and best possible score).

When the program completed (or, if I got bored of waiting, when I stopped it) it’d be showing the worst-found deals both in terms of lowest-scoring-best-word and fewest-possible-words. Easy.

Here’s how far I got with that program before I changed techniques. Maybe you’ll see why:

#!/usr/bin/env ruby
WORDLIST = File.readlines('dictionary.txt').map(&:strip) # https://github.com/jes/cntdn/blob/master/dictionary
LETTER_FREQUENCIES = { # http://www.thecountdownpage.com/letters.htm
  vowels: {
    A: 15, E: 21, I: 13, O: 13, U: 5,
  },
  consonants: {
    B: 2, C: 3, D: 6, F: 2, G: 3, H: 2, J: 1,
    K: 1, L: 5, M: 4, N: 8, P: 4, Q: 1, R: 9,
    S: 9, T: 9, V: 1, W: 1, X: 1, Y: 1, Z: 1,
  }
}
ALLOWED_HANDS = [ # https://wiki.apterous.org/Letters_game
  { vowels: 3, consonants: 6 },
  { vowels: 4, consonants: 5 },
  { vowels: 5, consonants: 4 },
]

At this point in writing out some constants I’d need to define the rules, my brain was already racing ahead to find optimisations.

For example: given that you must choose at least four cards from the consonants deck, you’re allowed no more than five vowels… but no individual vowel appears in the vowel deck fewer than five times, so my program actually had free-choice of the vowels.

Knowing that3, I figured that there must exist Countdown deals that contain no valid words, and that finding one of those would be easier than writing a program to permute through all viable options. My head’s full of useful heuristics about English words, after all, which leads to rules like:

  • None of the vowels can be I or A, because they’re words in their own right.
  • Five letter Us is a strong starting point, because it’s very rarely used in two-letter words (and this set of tiles is likely to be hard enough that three-letter words are already an impossibility).
  • This eliminates the consonants M (mu, um: the Greek letter and the “I’m thinking” sound), N (nu, un-: the Greek letter and the inverting prefix), H (uh: another sound for when you’re thinking or hesitating), P (up: the direction of ascension), R (ur-: the prefix for “original”), S (us: the first-person-plural pronoun), and X (xu: the unit of currency). So as long as we can find four consonants within the allowable deck letter frequency that aren’t those five… we’re sorted.
Rachel Riley, wearing a blue dress, places the last tile on a board to complete the tileset 'U J Y U Q V U U Z'.
I came up with U J Y U Q V U U Z, but there are definitely many other tile-sets that are completely valid within the rules of Counddown (albeit insanely unlikely to turn up organically) but for which there are no valid words to be found.

I enjoyed getting “Q” into my proposed letter set. I like to image a competitor, having already drawn two “U”s, a “J”, and a Y”, being briefly happy to draw a “Q” and already thinking about all those “QU-” words that they’re excited to be able to use… before discovering that there aren’t any of them and, indeed, aren’t actually any words at all.

Even up to the last letter they were probably hoping for some consonant that could make it work. A K (juku), maybe?

But the moral of the story is: you don’t always have to use a computer. Sometimes all you need is a brain and a few minutes while you eat your breakfast on a slow Sunday morning, and that’s plenty sufficient.

Update: As soon as I published this, I spotted my mistake. A “yuzu” is a kind of East Asian plum, but  it didn’t show up in this countdown solver! So my impossible deal isn’t quite so impossible after all. Perhaps U J Y U Q V U U C would be a better “impossible” set of tiles, where that “C” makes it briefly look like there might be a word in there, even if it’s just a three or four-letter one… but there isn’t. Or is there…?

Revised "impossible countdown" board, showing letters 'U J Y U Q V U U C'.

Footnotes

1 It boggles my mind to realise that show’s managed 28 seasons, now. Sure, I know that Countdown has managed something approaching 9,000 episodes by now, but Cats Does Countdown was always supposed to be a silly one-off, not a show in it’s own right. Anyway: it’s somehow better than both 8 Out Of 10 Cats and Countdown, and if you disagree then we can take this outside.

2 Herein lay my first challenge, because it turns out that the letter frequencies and even the rules of Countdown have changed on several occasions, and short of starting a conversation on what might be the world’s nerdiest surviving phpBB installation I couldn’t necessarily determine a completely up-to-date ruleset.

3 And having, y’know, a modest knowledge of the English language

× × ×

Note #27366

I’m looking at a listing for a ¼” to ⅝” screw adapter, for which the seller warns that I should “please allow 1-3cm error”.

A 3cm error would mean that a ⅝” screw could result in a screw thread anywhere between 1⅘” and… minus half an inch, I guess? (I don’t even know how to make the concept of negative lengths fit into my brain.)

I suppose this seller could send me an empty envelope and declare that it contained an infinitesimally small adapter. At which point… I’d be the one that was screwed!

Highlighted item description from an eBay listing. The highlighted section shows that the listing is for a quarter inch to a five-eighth of an inch adapter made of a premium aluminium alloy, and that the buyer should "please allow 1-3cm error due to manual measurement".

×

Egencia Mailing List Accessibility

A special level of accessibility failure on Egencia‘s mailing list subscription management page: the labels for choosing which individual mailing lists to subscribe to are properly-configured, but the “unsubscribe all” one isn’t. Click the words “unsubscribe all” and… nothing happens.

But it gets better: try keyboard-navigating through the form, and it’s hard not to unsubscribe from everything, even if you didn’t want to! As soon as the “unsubscribe all” checkbox gets focus, you get instantly unsubscribed: no interaction necessary.

The real (economic) AI apocalypse is nigh

This is a repost promoting content originally published elsewhere. See more things Dan's reposted.

“OK,” the young man said, “but what can we do about the crash?” He was clearly very worried.

“I don’t think there’s anything we can do about that. I think it’s already locked in. I mean, maybe if we had a different government, they’d fund a jobs guarantee to pull us out of it, but I don’t think Trump’ll do that, so –”

“But what can we do?

We went through a few rounds of this, with this poor kid just repeating the same question in different tones of voice, like an acting coach demonstrating the five stages of grieving using nothing but inflection. It was an uncomfortable moment, and there was some decidedly nervous chuckling around the room as we pondered the coming AI (economic) apocalypse, and the fate of this kid graduating with mid-six-figure debts into an economy of ashes and rubble.

I firmly believe the (economic) AI apocalypse is coming.

I’m not sure I entirely agree with Doctorow on this one. I’ll probably read his upcoming book on the subject, though.

I agree that, based on the ways in which AI is being used, financed, and marketed… we’re absolutely in an unsustainable bubble. There’s a lot of fishy accounting, dubious business models, and overpromised marketing. I’m not saying AI’s useless: it’s not! But it’s yet proven itself to be revolutionary, nor even on the path to being so, and it’s so expensive that it seems unlikely that the current “first dose is free” business model is almost-certainly unsustainable.

But I’m not convinced that a resulting catastrophic economic collapse is inevitable. Maybe I’m over-optimistic, but I like to imagine that the bubble can fizzle-out gradually and the actually-valuable uses of AI can continue to be used in a sustainable way. (I’m less-optimistic that we’ll find a happy-solution to prevent AI from being used to rip off artists, but that’s another story.)

But we’ll see.