[Bloganuary] Leadership

This post is part of my attempt at Bloganuary 2024. Today’s prompt is:

What makes a good leader?

I pretty-much answered this in an RSS Only post about a year ago, while talking about the things I’m worst at when I’m a leader, and that I therefore admired in others (along with specific examples of real people I’d worked under). The features I picked out that I admired were:

  • An ability to keep track of all the moving parts in and around a team,
  • The courage to demonstrate and encourage emotional honesty in professional environments, and
  • A keenness to proactively support the people you lead.
A flotilla of paper boats on a table: a red boat leads the way ahead of two blue and two green boats.
An ability to fold origami watercraft is also a bonus in a good leader.

(Incidentally, did you know that I publish some of my posts “RSS Only”: that is, they don’t show up on my homepage, generally don’t appear in my social feeds, etc. The only way to know when one is published is to subscribe to my blog using RSS, or one of the other mechanisms by which my “RSS Only” content gets shared, e.g. email…)

Email no more than

Anyway: I haven’t changed my mind in the last year – for me personally, the qualities I look for in a leader are those that compensate for the things at which I’m weakest. I want a leader that can pull me, push me ahead, point the way, or just hang back and let me explore, depending on what the situation demands. And I still stick by the list I wrote a year ago.

×

Magician Roles

Because I work somewhere hip enough to let people tweak their job titles, mine is “Code Magician”.

Employee directory photocard showing "Dan Q, Code Magician on Fire (Woo), started Oct 18th, 2019".

LinkedIn isn’t as hip as Automattic, though. That’s why they keep emailing me sector updates… for the “Magician” sector… 😅

Email from LinkedIn with the subject "Hiring trends for Magician roles".

× ×

Length Extension Attack Demonstration

Prefer to watch/listen than read? There’s a vloggy/video version of this post in which I explain all the key concepts and demonstrate an SHA-1 length extension attack against an imaginary site.

I understood the concept of a length traversal attack and when/how I needed to mitigate them for a long time before I truly understood why they worked. It took until work provided me an opportunity to play with one in practice (plus reading Ron Bowes’ excellent article on the subject) before I really grokked it.

Would you like to learn? I’ve put together a practical demo that you can try for yourself!

Screenshot of vulnerable site with legitimate "download" link hovered.
For the demonstration, I’ve built a skeletal stock photography site whose download links are protected by a hash of the link parameters, salted using a secret string stored securely on the server. Maybe they let authorised people hotlink the images or something.

You can check out the code and run it using the instructions in the repository if you’d like to play along.

Using hashes as message signatures

The site “Images R Us” will let you download images you’ve purchased, but not ones you haven’t. Links to the images are protected by a SHA-1 hash1, generated as follows:

Diagram showing SHA1 being fed an unknown secret key and the URL params "download=free" and outputting a hash as a "download key".
The nature of hashing algorithms like SHA-1 mean that even a small modification to the inputs, e.g. changing one character in the word “free”, results in a completely different output hash which can be detected as invalid.

When a “download” link is generated for a legitimate user, the algorithm produces a hash which is appended to the link. When the download link is clicked, the same process is followed and the calculated hash compared to the provided hash. If they differ, the input must have been tampered with and the request is rejected.

Without knowing the secret key – stored only on the server – it’s not possible for an attacker to generate a valid hash for URL parameters of the attacker’s choice. Or is it?

Changing download=free to download=valuable invalidates the hash, and the request is denied.

Actually, it is possible for an attacker to manipulate the parameters. To understand how, you must first understand a little about how SHA-1 and its siblings actually work:

SHA-1‘s inner workings

  1. The message to be hashed (SECRET_KEY + URL_PARAMS) is cut into blocks of a fixed size.2
  2. The final block is padded to bring it up to the full size.3
  3. A series of operations are applied to the first block: the inputs to those operations are (a) the contents of the block itself, including any padding, and (b) an initialisation vector defined by the algorithm.4
  4. The same series of operations are applied to each subsequent block, but the inputs are (a) the contents of the block itself, as before, and (b) the output of the previous block. Each block is hashed, and the hash forms part of the input for the next.
  5. The output of running the operations on the final block is the output of the algorithm, i.e. the hash.
Diagram showing message cut into blocks, the last block padded, and then each block being fed into a function along with the output of the function for the previous block. The first function, not having a previous block, receives the IV as its secondary input. The final function outputs the hash.
SHA-1 operates on a single block at a time, but the output of processing each block acts as part of the input of the one that comes after it. Like a daisy chain, but with cryptography.

In SHA-1, blocks are 512 bits long and the padding is a 1, followed by as many 0s as is necessary, leaving 64 bits at the end in which to specify how many bits of the block were actually data.

Padding the final block

Looking at the final block in a given message, it’s apparent that there are two pieces of data that could produce exactly the same output for a given function:

  1. The original data, (which gets padded by the algorithm to make it 64 bytes), and
  2. A modified version of the data, which has be modified by padding it in advance with the same bytes the algorithm would; this must then be followed by an additional block
Illustration showing two blocks: one short and padded, one pre-padded with the same characters, receiving the same IV and producing the same output.
A “short” block with automatically-added padding produces the same output as a full-size block which has been pre-populated with the same data as the padding would add.5
In the case where we insert our own “fake” padding data, we can provide more message data after the padding and predict the overall hash. We can do this because we the output of the first block will be the same as the final, valid hash we already saw. That known value becomes one of the two inputs into the function for the block that follows it (the contents of that block will be the other input). Without knowing exactly what’s contained in the message – we don’t know the “secret key” used to salt it – we’re still able to add some padding to the end of the message, followed by any data we like, and generate a valid hash.

Therefore, if we can manipulate the input of the message, and we know the length of the message, we can append to it. Bear that in mind as we move on to the other half of what makes this attack possible.

Parameter overrides

“Images R Us” is implemented in PHP. In common with most server-side scripting languages, when PHP sees a HTTP query string full of key/value pairs, if a key is repeated then it overrides any earlier iterations of the same key.

Illustration showing variables in a query string: "?one=foo&two=bar&one=baz". When parsed by PHP, the second value of "one" ("baz") only is retained.
Many online sources say that this “last variable matters” behaviour is a fundamental part of HTTP, but it’s not: you can disprove is by examining $_SERVER['QUERY_STRING'] in PHP, where you’ll find the entire query string. You could even implement your own query string handler that instead makes the first instance of each key the canonical one, if you really wanted.6
It’d be tempting to simply override the download=free parameter in the query string at “Images R Us”, e.g. making it download=free&download=valuable! But we can’t: not without breaking the hash, which is calculated based on the entire query string (minus the &key=... bit).

But with our new knowledge about appending to the input for SHA-1 first a padding string, then an extra block containing our payload (the variable we want to override and its new value), and then calculating a hash for this new block using the known output of the old final block as the IV… we’ve got everything we need to put the attack together.

Putting it all together

We have a legitimate link with the query string download=free&key=ee1cce71179386ecd1f3784144c55bc5d763afcc. This tells us that somewhere on the server, this is what’s happening:

Generation of the legitimate hash for the (unknown) secret key a string download=free, with algorithmic padding shown.
I’ve drawn the secret key actual-size (and reflected this in the length at the bottom). In reality, you might not know this, and some trial-and-error might be necessary.7
If we pre-pad the string download=free with some special characters to replicate the padding that would otherwise be added to this final8 block, we can add a second block containing an overriding value of download, specifically &download=valuable. The first value of download=, which will be the word free followed by a stack of garbage padding characters, will be discarded.

And we can calculate the hash for this new block, and therefore the entire string, by using the known output from the previous block, like this:

The previous diagram, but with the padding character manually-added and a second block containing "&download=valuable". The hash is calculated using the known output from the first block as the IV to the function run over the new block, producing a new hash value.
The URL will, of course, be pretty hideous with all of those special characters – which will require percent-encoding – on the end of the word ‘free’.

Doing it for real

Of course, you’re not going to want to do all this by hand! But an understanding of why it works is important to being able to execute it properly. In the wild, exploitable implementations are rarely as tidy as this, and a solid comprehension of exactly what’s happening behind the scenes is far more-valuable than simply knowing which tool to run and what options to pass.

That said: you’ll want to find a tool you can run and know what options to pass to it! There are plenty of choices, but I’ve bundled one called hash_extender into my example, which will do the job pretty nicely:

$ docker exec hash_extender hash_extender \
    --format=sha1 \
    --data="download=free" \
    --secret=16 \
    --signature=ee1cce71179386ecd1f3784144c55bc5d763afcc \
    --append="&download=valuable" \
    --out-data-format=html
Type: sha1
Secret length: 16
New signature: 7b315dfdbebc98ebe696a5f62430070a1651631b
New string: download%3dfree%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%e8%26download%3dvaluable

I’m telling hash_extender:

  1. which algorithm to use (sha1), which can usually be derived from the hash length,
  2. the existing data (download=free), so it can determine the length,
  3. the length of the secret (16 bytes), which I’ve guessed but could brute-force,
  4. the existing, valid signature (ee1cce71179386ecd1f3784144c55bc5d763afcc),
  5. the data I’d like to append to the string (&download=valuable), and
  6. the format I’d like the output in: I find html the most-useful generally, but it’s got some encoding quirks that you need to be aware of!

hash_extender outputs the new signature, which we can put into the key=... parameter, and the new string that replaces download=free, including the necessary padding to push into the next block and your new payload that follows.

Unfortunately it does over-encode a little: it’s encoded all the& and = (as %26 and %3d respectively), which isn’t what we wanted, so you need to convert them back. But eventually you end up with the URL: http://localhost:8818/?download=free%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%e8&download=valuable&key=7b315dfdbebc98ebe696a5f62430070a1651631b.

Browser at the resulting URL, showing the "valuable" image (a pile of money).
Disclaimer: the image you get when you successfully exploit the test site might not actually be valuable.

And that’s how you can manipulate a hash-protected string without access to its salt (in some circumstances).

Mitigating the attack

The correct way to fix the problem is by using a HMAC in place of a simple hash signature. Instead of calling sha1( SECRET_KEY . urldecode( $params ) ), the code should call hash_hmac( 'sha1', urldecode( $params ), SECRET_KEY ). HMACs are theoretically-immune to length extension attacks, so long as the output of the hash function used is functionally-random9.

Ideally, it should also use hash_equals( $validDownloadKey, $_GET['key'] ) rather than ===, to mitigate the possibility of a timing attack. But that’s another story.

Footnotes

1 This attack isn’t SHA1-specific: it works just as well on many other popular hashing algorithms too.

2 SHA-1‘s blocks are 64 bytes long; other algorithms vary.

3 For SHA-1, the padding bits consist of a 1 followed by 0s, except the final 8-bytes are a big-endian number representing the length of the message.

4 SHA-1‘s IV is 67452301 EFCDAB89 98BADCFE 10325476 C3D2E1F0, which you’ll observe is little-endian counting from 0 to F, then back from F to 0, then alternating between counting from 3 to 0 and C to F. It’s considered good practice when developing a new cryptographic system to ensure that the hard-coded cryptographic primitives are simple, logical, independently-discoverable numbers like simple sequences and well-known mathematical constants. This helps to prove that the inventor isn’t “hiding” something in there, e.g. a mathematical weakness that depends on a specific primitive for which they alone (they hope!) have pre-calculated an exploit. If that sounds paranoid, it’s worth knowing that there’s plenty of evidence that various spy agencies have deliberately done this, at various points: consider the widespread exposure of the BULLRUN programme and its likely influence on Dual EC DRBG.

5 The padding characters I’ve used aren’t accurate, just representative. But there’s the right number of them!

6 You shouldn’t do this: you’ll cause yourself many headaches in the long run. But you could.

7 It’s also not always obvious which inputs are included in hash generation and how they’re manipulated: if you’re actually using this technique adversarily, be prepared to do a little experimentation.

8 In this example, the hash operates over a single block, but the exact same principle applies regardless of the number of blocks.

9 Imagining the implementation of a nontrivial hashing algorithm, the predictability of whose output makes their HMAC vulnerable to a length extension attack, is left as an exercise for the reader.

× ×

WCEU23 – Contributor Day

Among the many perks of working for a company with a history so tightly-intertwined with that of the open-source WordPress project is that license to attend WordCamps – the biggest WordPress conferences – is basically a given.

Dan, wearing an Automattic "Let's make the Web a better place" t-shirt, stands in front of a banner welcoming attendees to WordCamp Europe Athens 2023.
So yeah, right now I’m in Athens for WordCamp Europe 2023.

It’s frankly a wonder that this is, somehow, my first WordCamp. As well as using it1 and developing atop it2, of course, I’ve been contributing to WordPress since 2004 (albeit only in a tiny way, and not at all for most of the last decade!).

A table placeholder labelled "WP-CLI". It and s handful of Coke cans and disposable coffee cups are picked-out in colour on an otherwise monochrome and blurred picture.
If you already know what WP-CLI is… let’s be friends.

Today is Contributor Day, a pre-conference day in which folks new and old get together in person to hack on WordPress and WordPress-adjacent projects. So I met up with Cem, my Level 4 Dragonslayer friend, and we took an ultra-brief induction into WP-CLI3 before diving in to try to help write some code.

Dan takes a selfie from a round table covered in laptops, with people hacking at them.
Contributor Days are about many things, but perhaps their biggest value comes from lowering the barrier to becoming a new contributor to an open-source project by sitting you right next to somebody who already knows it well.

So today, as well as meeting some awesome folks, I got to write an overly-verbose justification for a bug report being invalid and implement my first PR for WP-CLI: a bugfix for a strange quirk in output formatting.

Screenshot showing a user running `wp plugin update --all --no-color` but the output putting the word "Success" in green.
The bug I fixed is slightly hard to describe (and even harder to explain why it matters), but here’s a summary: when you run a WP-CLI command that first displays a table and then the result, the result is likely to always appear in colour even if you specify --no-color.

I hope to be able to continue contributing to WP-CLI. I learned a lot about it today, and while I don’t use it as much as I used to in my multisite-management days, I still really respect its power as a tool.

MacBook showing an Automattic "Work For Us" web page, alongside a bottle of Corona Extra. A rooftop terrace garden and swimming pool can be seen in the background.
Did I mention lately how awesome my employers are? I promise my blog’s not always gonna be me shilling for them… but today it is.

Footnotes

1 Even with the monumental stack of custom code woven into DanQ.me, a keen eye will probably spot that it’s WordPress-powered.

2 Perhaps my proudest “built on WordPress” moment was my original implementation of OpenID for WordPress, back in 2005, which is completely obsolete now. But I’ve done plenty of other things, both useful (like the multisite installation used by the University of Oxford) and pointless (like making WordPress a CMS for Gemini, Gopher, and Finger) too over the last 20 years.

3 WP-CLI is… it’s like Drush but for WordPress, if that makes sense to you? If not: it’s a multifaceted command-line tool for installing, configuring, maintaining, and managing WordPress installations, and I’ve been in love with it for years.

× × × × ×

Have Fun with Missions, Visions, and Values

I just spent a lightweight week in Rome with fellow members of Automattic‘s Team Fire.

Among our goals for the week was an attempt to strengthen the definition of who are team are, what we work on, and how and why we do so. That’s basically a team-level identity, mission, vision, and values, right?

In front of the Colosseum in Rome, Dan - wearing a rainbow-striped bandana atop which his sunglasses are perched - takes a selfie. Behind him stand a man with dark hair and a closely-trimmed beard wearing a purple "woo" t-shirt, a woman with long brown hair wearing beads and a multicoloured dress, a man wearing spectacles and a dark t-shirt on which the number "23" can be made out, and a man in sunglasses with a ginger beard, wearing an open blue shirt.
We were missing two members of our team, but one was able to remote-in (the other’s on parental leave!).

Fellow Automattician Ben Dwyer recently wrote about his experience of using a deck of Dixit cards to help his team refine their values in a fun and engaging way. I own a Dixit set, so we decided to give it a go too.

A deck of Dixit cards, bound by a twisted elastic band, sits on a flight itinerary for the journey "LGW to FCO" taking place on May 21, 2023 and costing $367.60.
The cards sat on my ‘plane tickets for a fortnight because it was just about the only way I’d remember to pack them.

Normally when you play Dixit, you select a card from your hand – each shows a unique piece of artwork – and try to describe it in a way that’s precise enough that some of the other players will later be able to pick it out of a line-up, but ambiguous enough that not all the other players will. It’s a delicate balancing act. Even when our old Geek Night was in full swing we didn’t used to play it often because our well-established group’s cornucopia of  in-jokes and references  made it trivially easy to “target” your descriptions at specific players1, but it’s still a solid icebreaker activity.

A trio of Dixit cards within a grid of nine. From left to right, they show: a heart, on fire, beneath a glass jar; a cubbyhole containing childrens' toys; a fairy leaping from a book towards a small person atop a stack of books.
Can you see your team’s values symbolised in any Dixit cards?

Perhaps it was the fantasy artwork that inspired us or maybe it just says something about how my team sees themselves, but what we came up with had a certain… swords-and-sorcery… even Dungeons & Dragons… feel to it.

Partial screenshot from a document entitled "Team Fire". The visible part is titled "Who we are (identity)" and reads:We are a band of brave adventurers who bring light into the wild forests of Extend. We tame the monsters who lurk in the dungeons beneath the Castle of Vendor Experience. The beasts we keep at bay include: PBS, which helps ensure code quality and extension standards compliance; the Vendor Dashboard, haunt of third-party developers, as well as their documentation and analytics platforms; Integrations with Payments Admin, to ensure that treasure is shared, and other tools.
The projects my team are responsible for aren’t actually monsters, but they can be complex, multifaceted, and unintuitive. And have a high AC.

Ou team’s new identity isn’t finalised, but I love the fact that we’ve been able to inject a bit of fun and whimsy into it. At our last draft, my team looks to be defined as comprising:

  • Gareth, level 62 Pathfinder, leading the way through the wilds
  • Bero, Level 5 Battlesmith, currently lost in the void
  • Dan (me!), Level 5 Arcane Trickster, breaking locks and stealing treasure
  • Cem, Level 4 Dragonslayer, smashing doors and bugs alike
  • Lae, Level 7 Pirate, seabound rogue with eyes on the horizon
  • Kyle, Level 5 Apprentice Bard, master of words and magic
  • Simran, Level 6 Apprentice Code Witch, weaving spells from nature

I think that’s pretty awesome.

Footnotes

1 Also: I don’t own any of the expansion packs and playing with the same cards over and over again gets a bit samey.

2 The “levels” are simply the number of years each teammate has been an Automattician, plus one.

× × × ×

Dan Q found GC7FB9H From Canterbury to the cache

This checkin to GC7FB9H From Canterbury to the cache reflects a geocaching.com log entry. See more of Dan's cache logs.

Well that was quite the adventure!

The first wayoint is right across the road from where some work colleagues and I are staying for an “away week”. I decided to dash out during a break in the weather to try and solve this multi between meetings. But I was quickly confused because… this isn’t the way I was taught to do Roman numerals. I’d always been told that you should never have four of the same letter in a row, e.g. you should say XIV, not XIIII. Once I’d worked out what I was doing wrong, though, I was okay!

The second and third waypoints had me braving some frankly scary roads. The drivers here just don’t seem to stop unless you’re super assertive when you step out!

Once I had the final numbers and ran it through geochecker I realised that the cache must be very close to where I’d had lunch earlier today! Once I got there it took me a while to get to the right floor, after which the hint made things pretty obvious.

Great trail, really loved it. And just barely made it back before the rain really started hammering down. TFTC, FP awarded, and greetings from Oxford, UK!

Dan holding an orange mint tin in a city centre.

×

Dan Q found GC9QCKH When in Rome live as the Romans do (bb Tribute 05)

This checkin to GC9QCKH When in Rome live as the Romans do (bb Tribute 05) reflects a geocaching.com log entry. See more of Dan's cache logs.

Took until the fourth hiding place before I found the cache. Out for a walk with work colleagues on the way to dinner. Greetings from Oxfordshire, UK!

Alongside the River Tiber, with a wide-arched stone bridge in the background, Dan sits on a wall and waves to the camera.

×

Travelling light

Now that travel for work is back on the menu, I’ve been trying to upgrade my “pack light” game.

I’ve been inspired in part by Beau, who I first met during my trip to South Africa in 2019 during my Automattic onboarding. Beau travelled from the US for a two week jaunt with nothing but hand luggage, and it blew my mind.

A modest-sized backpack in blue and yellow, with a WordPress logo stiched on, sits on an airport departure lounge bench. Alongside it is a burgundy-coloured British passport.
Gotta flight? Pack light, pack tight. That’s right! Corporate branding is just a bonus.

For my trip to Vienna earlier this year for a divisional meetup, I got by with just a backpack and a laptop bag. Right now, I’m waiting to fly to Rome for a week, and I’ve ditched the laptop bag in favour of just a single carry-on backpack. About 7kg of luggage, and well within the overhead locker size limit.

I’m absolutely sold on this approach. I get to:

  • walk past the queues for luggage drop (having checked-in online),
  • keep the entirety of my luggage with me at all times (which ensures it goes where I do),
  • breeze through security1, thanks to smart packing2
  • walk right out of the airport at the other end without having to wait for the flingers to finish smashing everybody’s luggage into the carousels.
Minimalist carbon fibre wallet, balanced on two fingertips, with parts of a Halifax Mastercard credit card showing from behind an elasticated band.
I’ve been working on simplifying my everyday carry, too. My wallet is the Carbon Fibre Liquid Wallet, which is about the size of a deck of playing cards (something I also often carry!) and holds a handful of cards, a bundle of cash, a bottle opener, and all my regular keys. The hook on the end is for attaching the pendrive with my password safe for travel.

As somebody who’s travelled “heavy” for most of my life – and especially since the children came along – it’s liberating to migrate to a “pick up a bag and go” mindset. To begin with, the nagging thought that I must’ve forgotten something essential was challenging, but I think I’ve gotten past that stage now.

Travelling light feels like carefree: like being a kid again, when all you needed was the back on your back and you were ready for an adventure. Once again, I’ve got a bag on my back3 and I know that everything I need for an adventure is right here with me4.

Footnotes

1 If you’ve travelled with me before, you might have noticed that I sometimes have trouble at borders on account of my damn stupid name, as predicted by the Passport Office. I’ve since learned all the requisite tricks to sidestep these problems, but that’s probably worthy of a post in its own right.

2 A little smart packing goes a long way. In the photo above, you might see my pre-prepared liquids bag in a side pocket, my laptop slides right out for separate scanning, my wallet and phone just dump out of my pockets, and I’m done.

3 I don’t really have a bag on my back right now. I’m sat in a depature lounge at Gatwick Airport. But you get the idea.

4 Do I really have everything I need? I’ve not brought a waterproof coat and, looking at the weather forecast at my destination, this might have been a mistake. But worst case I can buy a cheap poncho at the other end. That’s the kind of freedom that being an adult gets you, replacing the childlike freedom to get soaked and not care.

× ×

Automattic Acquires ActivityPub Plugin for WordPress

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

Automattic has acquired the ActivityPub plugin for WordPress from German developer Matthias Pfefferle, who will be joining the company to continue improving support for federated platforms. Pfefferle, who is also the author of the Webmention plugin, said his new role is to see how Automattic’s products can benefit from open protocols like ActivityPub.

This is so exciting I might burst. Want to know why?

  1. Matt Mullenweg‘s commitment to ActivityPub makes me happy. WordPress made Pingback and Trackback take off, back in the day, and I believe that – in the same way – Automattic can help make ActivityPub more accessible and mainstream too.
  2. Matthias Pfefferle is both an IndieWeb and an ActivityPub star; I use (and I’ve extented upon) a lot of code he’s written every day and I sponsor him on Github! The chance that we get to work directly together is pretty slim, but it’s a chance right?

Susan A. Kitchens expressed concern that this could increase the level of ActivityPub spam out there (which right now is very low). I worry about that too. But I’m still optimistic that we can make something awesome off the back of this acquisition and keep the interpersonal Web federated, the way it ought to be.

Announcers and Automation

Nowadays if you’re on a railway station and hear an announcement, it’s usually a computer stitching together samples1. But back in the day, there used to be a human with a Tannoy microphone sitting in the back office, telling you about the platform alternations and destinations.

I had a friend who did it as a summer job, once. For years afterwards, he had a party trick that I always quite enjoyed: you’d say the name of a terminus station on a direct line from Preston, e.g. Edinburgh Waverley, and he’d respond in his announcer-voice: “calling at Lancaster, Oxenholme the Lake District, Penrith, Carlisle, Lockerbie, Haymarket, and Edinburgh Waverley”, listing all of the stops on that route. It was a quirky, beautiful, and unusual talent. Amazingly, when he came to re-apply for his job the next summer he didn’t get it, which I always thought was a shame because he clearly deserved it: he could do the job blindfold!

There was a strange transitional period during which we had machines to do these announcements, but they weren’t that bright. Years later I found myself on Haymarket station waiting for the next train after mine had been cancelled, when a robot voice came on to announce a platform alteration: the train to Glasgow would now be departing from platform 2, rather than platform 1. A crowd of people stood up and shuffled their way over the footbridge to the opposite side of the tracks. A minute or so later, a human announcer apologised for the inconvenience but explained that the train would be leaving from platform 1, and to disregard the previous announcement. Between then and the train’s arrival the computer tried twice more to send everybody to the wrong platform, leading to a back-and-forth argument between the machine and the human somewhat reminiscient of the white zone/red zone scene from Airplane! It was funny perhaps only because I wasn’t among the people whose train was in superposition.

Clearly even by then we’d reached the point where the machine was well-established and it was easier to openly argue with it than to dig out the manual and work out how to turn it off. Nowadays it’s probably even moreso, but hopefully they’re less error-prone.

The "Mercado de Abasto" (central wholesale fruit and vegetable market) of Rosario, Argentina, 1931. Horses with carts work alongide automobiles and an omnibus.

When people talk about how technological unemployment, they focus on the big changes, like how a tipping point with self-driving vehicles might one day revolutionise the haulage industry… along with the social upheaval that comes along with forcing a career change on millions of drivers.

But in the real world, automation and technological change comes in salami slices. Horses and carts were seen alongside the automobile for decades. And you still find stations with human announcers. Even the most radically-disruptive developments don’t revolutionise the world overnight. Change is inevitable, but with preparation, we can be ready for it.

Footnotes

1 Like ScotRail’s set, voiced by Alison McKay, which computers can even remix for you over a low-fi hiphop beat if you like.

Bisect your Priority of Constituencies

Your product, service, or organisation almost certainly has a priority of constituencies, even if it’s not written down or otherwise formally-encoded. A famous example would be that expressed in the Web Platform Design Principles. It dictates how you decide between two competing needs, all other things being equal.

At Three Rings, for example, our priority of constituencies might1 look like this:

  1. The needs of volunteers are more important than
  2. The needs of voluntary organisations, which are more important than
  3. Continuation of the Three Rings service, which is more important than
  4. Adherance to technical standards and best practice, which is more important than
  5. Development of new features

These are all things we care about, but we’re talking about where we might choose to rank them, relative to one another.

Semicircular illustration showing five facets of growing relative importance. From least to most, they are: new features, standards-compliance, service continuity, organisation needs, volunteer needs.
The priorities and constituencies portrayed in this illustration are ficticious. Any resemblence to real priorities and constituencies, whether living or dead, is entirely coincidental.

The priorities of an organisation you’re involved with won’t be the same: perhaps it includes shareholders, regulatory compliance, different kinds of end-users, employees, profits, different measures of social good, or various measurable outputs. That’s fine: every system is different.

But what I’d challenge you to do is find ways to bisect your priorities. Invent scenarios that pit each constituency against itself another and discuss how they should be prioritised, all other things being equal.

Using the example above, I might ask “which is more important?” in each category:

  1. The needs of the volunteers developing Three Rings, or the needs of the volunteers who use it?
  2. The needs of organisations that currently use the system, or the needs of organisations that are considering using it?
  3. Achieving a high level of uptime, or promptly installing system updates?
  4. Compliance with standards as-written, or maximum compatibility with devices as-used?
  5. Implementation of new features that are the most popular user requests, or those which provide the biggest impact-to-effort payoff?
Illustrated priority list from above, which each item split into two and re-named such that they are, from least to most important: popular features, impact features, compliance, usability, uptime, updates, future clients, current clients, other volunteers, our volunteers.
These might not be your answers to the same questions. They’re not even necessarily mine, and they’re even less-likely to be representative of Three Rings CIC. It’s just illustrative.

The aim of the exercise isn’t to come up with a set of commandments for your company. If you come up with something you can codify, that’s great, but if you and your stakeholders just use it as an exercise in understanding the relative importance of different goals, that’s great too. Finding where people disagree is more-important than having a unifying creed2.

And of course this exercise applicable to more than just organisational priorities. Use it for projects or standards. Use it for systems where you’re the only participant, as a thought exercise. A priority of constituencies can be a beautiful thing, but you can understand it better if you’re willing to take it apart once in a while. Bisect your priorities, and see what you find.

Footnotes

1 Three Rings doesn’t have an explicit priority of constituencies: the example I give is based on my own interpretation, but I’m only a small part of the organisation.

2 Having a creed is awesome too, though, as I’ve said before.

Do What You’re Bad At

This blog post is also available as a video. Would you prefer to watch/listen to me tell you about how I’ve learned to enjoy doing what I’m bad at?

There are a great number of things that I’m bad at. One thing I’m bad at (but that I’m trying to get better at) is being more-accepting of the fact that there are things that I am bad at.

Against a pale background, Dan, deep in thought and with a finger to his lips, staring into space. A stylised thought bubble above him shows that he is thinking about himself thinking about himself thinking about himself, and so on (implied to infinity).
I’ve also been thinking about how I’m bad at thinking about how I’m bad at thinking about how I’m bad at thinking about…

I’m pretty bad in a pub quiz. I’m bad at operating my pizza oven without destroying cookware. I’m especially bad at learning languages. I’m appallingly bad at surfing. Every time my work periodically leans in that direction I remember how bad I am at React. And I’ve repeatedly shown that I’m bad at keeping on top of blogging, to the extent that I’ve periodically declared bankruptcy on my drafts folder.

So yeah, pretty bad at things.

But hang on: that assessment isn’t entirely true.

Photograph showing a yellow banana on a pink background. The banana has a silver chain wrapped around it three times. Photo courtesy Deon Black.
I’m also particularly bad at choosing suitable stock photos for use in blog posts.

Being Bad

As a young kid, I was a smart cookie. I benefited from being an only child and getting lots of attention from a pair of clever parents, but I was also pretty bright and a quick learner with an interest in just about anything I tried. This made me appear naturally talented at a great many things, and – pushed-on by the praise of teachers, peers, and others – I discovered that I could “coast” pretty easily.

But a flair for things will only carry you so far, and a problem with not having to work hard at your education means that you don’t learn how to learn. I got bitten by this when I was in higher education, when I found that I actually had to work at getting new information to stick in my head (of course, being older makes learning harder too, as became especially obvious to me during my most-recent qualification)!

Dan, aged around 4, dressed in a duffel coat, bobble hat and gloves, kneeling on a red plastic sledge in a snow-filled garden. The garden is bordered by a wire fence, and in the background a man can be seen scraping icee off a car.
Ignore the fact that you’ve now seen me trying to sledge uphill and just accept that I was a clever kid (except at photography), okay?

A side-effect of these formative experiences is that I grew into an adult who strongly differentiated between two distinct classes of activities:

  1. Things I was good at, either because of talent or because I’d thoroughly studied them already. I experienced people’s admiration and respect when I practised these things, and it took little effort to stay “on top” of these fields, and
  2. Things I was bad at, because I didn’t have a natural aptitude and hadn’t yet put the time in to learning them. We don’t often give adults external reinforcement for “trying hard”, and I’d become somewhat addicted to being seen as awesome… so I shied away from things I was “bad at”.

The net result: I missed out on opportunities to learn new things, simply because I didn’t want to be seen as going through the “amateur” phase. In hindsight, that’s really disappointing! And this “I’m bad at (new) things” attitude definitely fed into the imposter syndrome I felt when I first started at Automattic.

Being Better

Leaving the Bodleian after 8½ years might have helped stimulate a change in me. I’d carved out a role for myself defined by the fields I knew best; advancing my career would require that I could learn new things. But beyond that, I benefited from my new employer whose “creed culture” strongly promotes continuous learning (I’ve vlogged about this before), and from my coach who’s been great at encouraging me towards a growth mindset.

A cake with icing printed with a picture of Dan in a library. Beneath are iced the words "Good Luck Dan".
“Good Luck Dan”, my Bodleian buddies said. But perhaps they should’ve said “Keep Learning Dan”.

But perhaps the biggest stimulus to remind me to keep actively learning, even (especially?) when it’s hard, might have been the pandemic. Going slightly crazy with cabin fever during the second lockdown, I decided to try and teach myself how to play the piano. Turns out I wasn’t alone, as I’ve mentioned before: the pandemic did strange things to us all.

I have no real experience of music; I didn’t even get to play recorder in primary school. And I’ve certainly got no talent for it (I can hear well enough to tell how awful my singing is, but that’s more a curse than a blessing). Also, every single beginners’ book and video course I looked at starts from the assumption that you’re going to want to “feel” your way into it, and that just didn’t sit well with the way my brain works.

Animation showing Dan, wearing a black t-shirt and tracksuit bottoms, playing an upright piano.
90% of what I do in front of a piano might be described as “Dan Mucks About (in B Minor)”, but that’s fine by me.

I wanted a theoretical background before I even sat down at a keyboard, so I took a free online course in music theory. Then I started working through a “beginners’ piano” book we got for the kids. Then I graduated to “first 50 Disney songs”, because I know how virtually all of them sound well enough that I’d be able to hear where I was going wrong. Since then, I’ve started gradually making my way through a transcription of Einaudi’s Islands. Feeling like I’d got a good handle on what I was supposed to be doing, I then took inspiration from a book JTA gave me and started trying to improvise.

Most days, I get no more than about 10 minutes on the piano. But little by little, day by day, that’s enough to learn. Nowadays even my inner critic perfectionist can tolerate hearing myself play. And while I know that I’ll probably never be as good as, say, the average 8-year-old on YouTube, I’m content in my limited capacity.

Three books on a blue-and-white tablecloth: John Thompson's Easiest Piano Course (Part One), First 50 Disney Songs, and Essential Einaudi - Islands. Beneath them sits a simplified diagram showing the circle of fifths.
Let’s start at the very beginning. (A very good place to start.)

If I’m trying to cultivate my wonder syndrome, I need to stay alert for “things I’m bad at” that I could conceivably be better at if I were just brave enough to try to learn. I’m now proudly an “embarrassingly amateur” pianist, which I’m at-long-last growing to see as better than a being non-pianist.

Off the back of that experience, I’m going to try to spend more time doing things that I’m bad at. And I’d encourage you to do the same.

× × × × ×

Automattic International

(This is yet another post about Automattic. Seee more posts about my experience of working at Automattic.)

Off the back of my recent post about privileges I enjoy as a result of my location and first language, even at my highly-multinational employer, and inspired by my colleague Atanas‘ data-mining into where Automatticians are located, I decided to do another treemap, this time about which countries Automatticians call home:

Where are the Automatticians?

Treemap showing countries of Automatticians. North America and specifically the USA dominates, the UK has the most in Europe, etc.
If raw data’s your thing (or if you’re just struggling to make out the names of the countries with fewer Automatticians), here’s a CSV file for you.

To get a better picture of that, let’s plot a couple of cartograms. This animation cycles between showing countries at (a) their actual (landmass) size and (b) approximately proportional to the number of Automatticians based in each country:

Animation showing countries "actual size" changing to proportional-to-Automattician-presence.
This animation alternates between showing countries at “actual size” and proportional to the number of Automatticians based there. North America and Europe dominate the map, but there are other quirks too: look at e.g. how South Africa, New Zealand and India balloon.

Another way to consider the data would be be comparing (a) the population of each country to (b) the number of Automatticians there. Let’s try that:

Animation showing countries proportional to population changing to proportional-to-Automattician-presence.
Here we see countries proportional to their relative population change shape to show number of Automatticians, as seen before. Notice how countries with larger populations like China shrink away to nothing while those with comparatively lower population density like Australia blow up.

There’s definitely something to learn from these maps about the cultural impact of our employee diversity, but I can’t say more about that right now… primarily because I’m not smart enough, but also at least in part because I’ve watched the map animations for too long and made myself seasick.

A note on methodology

A few quick notes on methodology, for the nerds out there who’ll want to argue with me:

  1. Country data was extracted directly from Automattic’s internal staff directory today and is based on self-declaration by employees (this is relevant because we employ a relatively high number of “digital nomads”, some of whom might not consider any one country their home).
  2. Countries were mapped to continents using this dataset.
  3. Maps are scaled using Robinson projection. Take your arguments about this over here.
  4. The treemaps were made using Excel. The cartographs were produced based on work by Gastner MT, Seguy V, More P. [Fast flow-based algorithm for creating density-equalizing map projections. Proc Natl Acad Sci USA 115(10):E2156–E2164 (2018)].
  5. Some countries have multiple names or varied name spellings and I tried to detect these and line-up the data right but apologies if I made a mess of it and missed yours.
× × ×