Blue Team – The Song

In the world of penetration testing, as I’m often involved in with ROS, those taking on the role of attackers are referred to as the “red team”, and those defending as the “blue team”. Red team people are often regarded as the rock stars of INFOSEC, but one key difference is that red-teamers only have to succeed in their efforts once, whereas blue-teamers have to succeed every time. Unfortunately, when the blue team succeeds, nothing notable happens, so they don’t get much of the glory.

This song is a tribute to the unsung heroes of the blue team; Gotta keep out the bad guys, baby!

Unsurprisingly, the “gotta keep out the bad guys” line was about the first thing I thought of, and everything stemmed from that. There were lots of blue-teamy things I could have written about, but I preferred to keep it short. The string-bend bass riff was the first bit of music, then the funky guitar parts, though I ended up dialling them back a bit in favour of some chuggy rhythm guitar. As in my other tracks, I was keen to use Synthesizer V for vocals, and the backing vocals came out really well. I wrote the lead guitar solo, then thought a higher vocal part alongside it might work, and it was also a chance to have a dig at the red team; it’s my favourite bit of the song.

There are a lot of guitar parts overall (all played by me), and only some small pad and organ keyboards for backing. I was especially happy that I managed to pull off the more aggressive bass parts and the lead solo. As usual, the drums were all done with Logic’s Drummer instrument, which does a great job without getting drunk and falling asleep during rehearsals, and its excellent “follow” mode meant that the drums could match what I’d played on the bass, rather than being some disconnected pattern.

As usual, I’m not too happy with my vocals (PRs welcome!), but Logic’s Flex Pitch editor works enough magic to get the job done. This track could really do with someone that can get a bit more grungy in the verses, with a hint of Elvis for the chorus.

[Intro]
Don’t break a sweat
from a constant threat.
We’ve got the tools to meet them
and firewall rules to defeat them.

[Verse]
We’ll take our time
to build our defences.
No need to be concerned,
we know the consequences.

They’re going to attack
our networking stack,
but we can keep them guessing as
their port scans come to nothing.

[Chorus]
Because, I’m on the blue team, baby,
we’ve got to always win.
Gotta keep out the bad guys,
can’t ever let them in.

Come join the blue team, baby,
we need your awesome skills.
Come watch that bad actor
try to guess my second factor.

[Solo]
Oooh red team stays outside,
don’t want you here.
Just go away
and don’t come back.
You’ve gotta find another way.

[Verse]
Alarm bells ring
from a tripwire’s string.
Logs tell a sad, sad story
of a search for a way in.

SOC screens flash
for a matching hash
We’ve seen this one before
and there’ll be many more

[Chorus]
That’s why I’m on the blue team, baby, (ooh yeah)
we’ve got to always win. (blue team, blue team)
Gotta keep out the bad guys, (ooh yeah, gotta keep out the bad guys baby)
can’t ever let them in.

Come join the blue team, baby,
we need your awesome skills.
Show your strength, let it shine,
help take those APTs offline

We’re on the blue team, (ooh yeah)
got to always win. (blue team, blue team)
Gotta keep out the bad guys, (ooh yeah, gotta keep out the bad guys baby)
can’t ever let them in.

We’re on the blue team, baby,
we’ve got to always win.
We’re the unsung heroes.
(gotta keep out the bad guys, baby)

If you like this song, please consider supporting me by buying my album, “Developer Music” on Bandcamp, and sharing links to my song posts on here. If you can sing (or play something) and would like to be involved in musical projects like this, please get in touch, as I could really use your help!

Butter crinkle crunch biscuits revisited

A while ago I wrote up my attempt at making a copy of Fox’s butter crinkle crunch biscuits, which are no longer available to buy. In that article I mentioned various things I thought I’d try, and others commented with some suggestions, so I thought I’d revisit the recipe.

Update 2023-03-14: there is a revised version of this recipe.

Since then I have obtained some “Uncle Roy’s” butter flavouring (triacetin). I found that the recommended 5–6 drops did nothing, but I got a reasonable amount of butteriness with about 60 drops (about 1.5 tsp)! Unfortunately the carrier solvent for this flavouring (Monopropylene Glycol) tastes quite harsh and bitter, and a hint of it remained in the end product. Uncle Roy’s offers a “super strength” version of this flavouring that might reduce this effect.

The other suggestions were to reduce the amount of sugar, add more oats, and to add milk powder. There was also a suggestion to use ammonium bicarbonate as the raising agent, but I couldn’t find that.

Unfortunately, putting all these together didn’t work very well. The dough ended up quite dry, though sticky enough to hold together. I think this prevented the raising agent from working properly, as they remained stubbornly flat while cooking, so I think adding some liquid (perhaps a bit of water or milk) or increasing the butter a bit, would help give the baking powder somewhere to react. This drying might have been an effect of adding the milk powder and increasing oats.

Not quite butter crinkle crunches

While I say “unfortunately”, they are still quite nice (I mean, just look at the ingredients!). I think next time I’ll lower the temperature and cook them a bit longer to give more chance for the solvents to boil off, and the raising agent to do its thing, aiming for a more consistent crunchy texture.

Just for reference (as I don’t recommend following this exactly!), here is a revised ingredients list; the instructions remain unchanged from before:

  • 175g white flour
  • 50g white sugar
  • 25g dark muscovado sugar (adds a slightly caramel-y taste)
  • 60g oats (porridge, not jumbo)
  • 50g milk powder
  • 125g butter
  • 50g golden syrup
  • 2tsp baking powder
  • Pinch of salt
  • 1.5tsp of butter flavouring
  • 1/4tsp vanilla powder
  • A small bowl of Demerara sugar (cassonade in France) for rolling

If you have a go at these, please leave a comment, as I’d love to know if you manage to do any better!

Mud vs Sheep vs Bike, the song

Mud vs Sheep vs Bike (MvSvB) is an event that my friend Fraser and I started in about 1993. I’ve written about it on here before. Essentially it’s just a bunch of friends going mountain biking in Wales, but it has achieved a kind of independent existence in our collective consciousness. It’s loosely named after the famous “Man vs Horse vs Bike” race that I regretted once entering in about 1991. MvSvB has been held at various youth hostels and other group rental accommodations, but most often at what was my Dad’s farm near Llandovery in Wales.

Certain MvSvB traditions have been established, most importantly:

  • Banoffee pie
  • T-shirts
  • Getting wet and muddy
  • Getting lost
  • Punctures and disintegrating wheels
  • Being chased by fierce sheepdogs
  • Beer

Banoffee pie is a critical component of the coping mechanisms required to spend much time in Welsh weather, and is a great source of the calories required for biking up hills (at least that’s our excuse). Some terms for the unaware: liquid sun = rain, Welsh not raining = light drizzle.

I’ve designed most of the T-shirts to date, starting in 1995, when I learned that half-toning really isn’t a good approach for screen printing on fabrics. The designs usually tried to have 1 or 2-colour prints using strong mountain bike themes with in-jokes, references to mud, sheep, bikes, hills, etc. This year I came up with a bold design, based on a picture of a friend on a bike, carefully redrawn with an Apple Pencil on my iPad (using Linearity Curve), and printed using a groovy high-tech direct-to-fabric printing process by my friends at Vektor.

Since I moved to France in 2009, I’ve missed out on a few events, Fraser moved to New Zealand, we’ve mostly had growing kids to contend with, the whole age thing, and so MvSvB events have dwindled. But 2023 is the comeback year, the kids are big enough to leave at home, and we can reunite to enjoy a collective mid-life crisis.

To commemorate what we are officially calling the 30th anniversary of MvSvB, I wrote this song about it, celebrating all the nasty weather, excessive eating and drinking, impromptu bike maintenance, and generally messing about on bikes with friends.

I came up with the first line first; always a good start. I wanted to have a sparse, slightly gloomy sounding verse so that I could pair it with an excessively happy chorus. Of course It just would work without rain ambience and bike and sheep noises. Next up came the bass line; I’ve never really played slap bass before (on my Sire Marcus Miller M2 bass), but I am pretty happy with the result – I’m sure it sounds better than when I played it due to the wonders of Logic Pro’s flex pitch editor! Next was the guitar, which is very simple. Drums are courtesy of Logic’s excellent Drummer instrument, which I got to follow my bass part in places. I had quite a lot of lyrics for the chorus, and despite the 130bpm tempo, it manages to sound fairly leisurely. The timing of those lyrics gave me a pattern which led to a melody, which led to some very basic chords, and voila, one functioning chorus!

I’ve been very keen to try out Synthesizer V, which I had bought at fair expense earlier this year, only to find that it’s borderline unusable in DAWs like Logic. However with a little perseverance I found it was workable so long as I didn’t even consider touching the tempo. This gave me the first set of vocals – two backing lines that I made in a similar style to how I worked in Tailwind, except with these synthetic voices. I had planned to sing the main parts myself, but found it just really didn’t work, so I enlisted the help of Lucas H on Fiverr who did a great job with a quick turnaround. With all these working together, I’ve ended up with 5 vocal parts in some places, and it makes for a great ensemble sound that I wasn’t quite expecting, but I’m very happy with.

I don’t care if it’s raining,
get back on your bike
I know you’re hung over
from drinking last night
But that’s not my problem
there’s mountains to ride
and there’s no way I’m
letting you stay inside

Sheep getting restless
and puddles so deep
there’s mud to my elbows
and I’ve had no sleep
but I don’t care
‘cos we’re here to have fun
to every last drop
of this liquid Welsh sun

There’s mud and there’s sheep and there’s rides with our friends
There’s banoffee and T-shirts and hills without end
There’s maps and confusion and roads to nowhere
There’s mud and there’s bikes and that’s why we are here

No punctured excuses
or unspoken wheels
we’re chained to the bars
as we grind up the hills.
We’re spinning for summits
and covered in grime
leaving tread on the tracks
of a great mountain climb

There’s mud and there’s sheep and there’s rides with our friends
There’s banoffee and T-shirts and hills without end
There’s maps and confusion and roads to nowhere
There’s mud and there’s bikes and that’s why we are here

Pedal, pedal... up the hills
Pedal, pedal... up the hills

There’s mud and there’s sheep and there’s rides with our friends
We always come back here, again and again
There’s mountains and rivers and crates of cold beer
There’s mud and there’s bikes and that’s why we are here

Laravel duplicate key error despite unique validation

In a Laravel API, it’s really common to create users with an endpoint like this in a user controller:

public function store(Request $request): UserResource|JsonResponse
{
    $validator = Validator::make(
        $request->all(),
        [
            'email' => 'required|string|max:255|email|unique:users',
            'name'  => 'required|string|max:255',
        ],
        [
            'email.unique' => 'That email address already has an account.',
        ]
    );
    if ($validator->fails()) {
        return response()->json(
            [
                'error'   => true,
                'message' => $validator->errors()->all(),
            ],
            Response::HTTP_UNPROCESSABLE_ENTITY
        );
    }
    $user = User::create(
        $request->only(
            [
                'email',
                'name',
            ]
        )
    );Code language: PHP (php)

There’s a problem here though – that unique validation on the email field is subject to a race condition. If two requests are received very close together, both can pass validation, but then the second one will fail with a duplicate key error on the User::create call. While that sounds unlikely, it happens for real sometimes, and you’ll see something like this in your web logs when it does:

192.168.0.1 - - [06/Oct/2023:07:08:54 +0000] "POST /users/ HTTP/2.0" 201 1276 "-" "okhttp/4.9.2"
192.168.0.1 - - [06/Oct/2023:07:08:55 +0000] "POST /users/ HTTP/2.0" 500 17841 "-" "okhttp/4.9.2"Code language: JavaScript (javascript)

The 201 response is a successful creation, but it’s followed a second later by a 500 failure for the duplicate request. The Laravel log will then contain one of these:

[2023-10-06 07:08:55] staging.ERROR: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'user@example.com'
 for key 'users.users_email_unique' (Connection: mysql, SQL: insert into `users` (`email`, `name`) values (user@example.com, Test)Code language: JavaScript (javascript)

To deal with that we can trap the creation error, and return an error response that looks the same as the validation error:

try {
    $user = User::create(
        $request->only(
            [
                'email',
                'name',
            ]
        )
    );
} catch (QueryException $e) {
    //1062 is the MySQL code for duplicate key
    if ($e->errorInfo[1] !== 1062) {
        //Rethrow anything except a duplicate key error
        throw $e;
    }
    return response()->json(
        [
            'error'   => true,
            'message' => 'That email address already has an account.',
        ],
        Response::HTTP_UNPROCESSABLE_ENTITY
    );
}Code language: PHP (php)

This way, as far as the client is concerned, it was a straightforward validation failure with an appropriate 422 error code, and we don’t get spurious 500s clogging up our error logs.