Books: The Year Without Pants

I finished reading Scott Berkun’s book The Year Without Pants. The book tells the tale of Scott’s time at Automattic as the lead of Team Social, which worked on I’ve never read a book about a place that I’ve worked at, so I was curious to see things from his point of view.

I’ve worked at Automattic for over six years, well before Scott started there. We were always on separate teams and I never worked directly with Scott on any projects. As a result some of the things Scott talks about in the book take on a different angle than my own. While reading through the book I made notes on things that I wanted to expand on a bit, provide a different point of reference for, or just struck me as interesting. I’m including the page number for easy reference.

Page 10, talking about how for many people Automattic was the largest company they had ever worked for. I definitely didn’t fall into that camp. Oddly enough I’ve alternated between large and small companies, though not on purpose. Before Automattic I worked at a university that had thousands of employees. Before that I was at small regional ISP that never had more than 10 full time employees. Going back one more job I was at a large international company with more than 10,000 people across the planet. And the job before that was at a company with 20 people. That pretty much covers all of the jobs I’ve had as an adult.

Page 15, about IRC being an ancient chat program. When I mention to other people that we use IRC I’ll often describe it as being “as old as dirt”, meaning 1988. Being old doesn’t change the fact that it is still one of the best solutions to the problem of text based chat.

Page 16, about Automattic demanding great communication skills. In some ways we have to overcommunicate in order to make up for not all being in the same building.

Page 20, Caturday. Long running thing at Automattic from the world of LOLcats. On page 25 Scott shows a screenshot of some stats, and the week ends with Caturday. Some time ago a new hire at Automattic “fixed” the typo by changing it to Saturday. We had to explain the joke, then had them revert it back to Caturday :-)

Page 25, experts don’t go back to regular jobs because regular jobs are hard. This is worth keeping in mind the next time you read an article or book from a professional expert.

Page 28, on jamming practices from one culture into another. This is a hard lesson to learn and I think most who have learned it have only done so through experience. Culture isn’t something you can easily transplant. Culture, like trust, is hard to build and easy to destroy.

Page 29, about trust. Trust is a really big deal in any company culture. The lack of it usually results in grinding political structures. High degrees of trust can result in the whole being so much more than the sum of the parts.

Page 42, remember how I mentioned that I described IRC being as old as dirt? I’m not the only one who thinks that way :-)

Page 43, about many things at Automattic being inherited from the open source WordPress project. I don’t think it is an overstatement to say that this is one of the core attributes in the formation of Automattic. In many ways it looks like a group of people working on an open source project that just happens to also involve money, sometimes.

Page 46, about the WordPress theme P2. One day I’ll write a separate post about how P2 came to be. Naming things can be hard, and sometimes beyond your control.

Page 48, on the communication break down between P2, IRC, Skype, and email. The ratio varies between teams. For my experience I’d say P2 and IRC are closer to 50 / 50, Skype and email nearly rounding errors. IRC was good for talking about something right now ( synchronous ) and P2 was good for things that weren’t nearly so time sensitive ( asynchronous ) or needed a better way to be tracked.

Page 54, about the size of a company being the ultimate goal. I’ve had conversations with people about companies that stay intentionally small. In the technology field it isn’t often that you come across people who want to have a limit to how big their company gets. I think there is an idea worth exploring in there.

Page 61, regarding killing a project or experiment. It isn’t easy to shutdown something that you’ve put energy into. That said, we could be better about letting go.

Page 104, data-influenced culture versus a data-driven one. I’ll give an example of one experience I had that shows how this worked. A new A / B test was launched around a signup flow and I was fairly certain that the new version was going to do worse because the resulting experience was so bad for the user. It quickly became clear that the new version resulted in more revenue. As a team we talked it over and decided against using the new version, even though it meant giving up some of that increase in revenue. I was happy we were able to agree on that because the user experience in the new version was one I’d never want to use. The results of the A / B test were one part of our decision making process, but it wasn’t the only consideration.

Page 111, vision. Someone having a clear vision of where things are going as a whole is a different dynamic in a company that focuses on individuals being super proactive about coming up with their own ideas on what to work on next. Not that you can’t have it, just that at some point you realize everyone can’t do everything. See also page 126 regarding clarity vs. quantity of ideas.

Page 132, “Without the time machine, all choices have the possibility of being wrong.” I need to put that on a t-shirt. Sometimes the value of making a decision outweighs any of the potential outcomes of the decision itself.

Page 134, on not being tied down too much by a pre-selected process. I’ve been asked before if Automattic uses [ insert current trendy methodology here ]. My answer has always been no. We work out what works best for us as a team, then start moving forward, adjusting along the way as needed.

Page 136, “To start big projects, you must have the capacity for delusion.” Probably also worth a t-shirt. At some point after going through enough big projects you learn that you always underestimate them at the beginning. Then after even more of them you learn that under estimating them is sometimes a good thing, because if you didn’t you would never actually start them.

Page 152, about work environments. When I talk with people about Automattic being a distributed company, I usually end up explaining that like most things it is about trade offs. Distributed vs. non-distributed is often less about which one is better and more about which trade offs you want to work with. The same is true of individuals. Not everyone is going to excel in a distributed situation, and that is fine, it doesn’t make them bad at what they do or who they are.

Page 171, talking about Team Social being stretched even further. When Scott joined Automattic I started working on the Akismet team. Our team was always stretched, with people in Melbourne ( Australia ), California, Utah, North Carolina, and England. From UTC that is +11, -7, -6, -4, and +1 for everyone playing along at home. Not the same broad and even distribution that Team Social ended up with, but not always easy either. But we made it work.

Page 198, a reference to the bike shed problem. Long time FreeBSD users will remember the bike shed post by PHK.

Page 200, on few people being willing to dive in and make changes. That is pretty much the opposite of my experience.

Page 200, about broken windows for good and bad. I think our ability to fix a bug that came up quickly is a good thing. There obviously has to be some balance with other things, but I would never want to lose our ability to go from getting a ping from a friend about something on our service being broken, to being able to reply that it has now been fixed, often in a matter of minutes.

Page 201, some people being afraid to post on a P2 because they think it is a megaphone and everyone is reading it. What is funny about reading that is that before we had P2, there was just one internal blog for all of Automattic and it was rarely used. It was common for it to only get one post per month. P2 changed that dramatically.

Page 225, “No one should be expected to carry the burden of a secret their peers would love to know.” Not worth putting on a t-shirt, but something that every leader should remember.

I could comment on every page in the book, but these were the points that I noted specifically as I read through it.

The book itself is an enjoyable read, and easy to get through. If you’ve ever wondered what things are like at Automattic, The Year Without Pants, is a pretty good window. Just keep in mind that it is from one point of view and that each team has a high degree of flexibility in doing things in a way that works best for them.

If you would rather live it than read about it, Automattic is hiring.

Mike Adams on Three Security Issues You Thought You’d Fixed

Mike Adams spoke about Three Security Issues You Thought You’d Fixed at WordCamp San Francisco 2013. Although this was at a WordPress event, the security issues he talks about apply more broadly to PHP and web sites in general.

I work with Mike at Automattic and we are hiring. If you enjoy bunny puns you should check out our list of open positions.

WordPress UI Ideas From Shaun Andrews

Shaun Andrews has been working on user interface ideas for WordPress. One of my favorites so far has been about browsing themes.

Reminds me of the Netflix and Amazon Prime interfaces on my old Roku box.

Go follow to see what he has been up to. Hopefully some of these will make it into WordPress 3.8.

Salt Lake City WordPress Meetup This Wednesday

The Salt Lake City WordPress Meetup is happening this Wednesday, August 28th. Brian Petty is going to talk about how to report bugs and submit patches back to the WordPress project.

It will be at the MoJo Themes office in Draper at 7pm. Check out for all the details.

WordCamp Salt Lake City 2013

WordCamp Salt Lake City is back for 2013!

This year we are moving the location to Sandy, Utah, which should make it easier for our friends in Utah county. The big day is Saturday 21 September 2013.

Do you have a WordPress topic that you are passionate about? Submit a presentation for consideration. Want to help us cover the bills? We have sponsorship opportunities too.

Registration is now open, with discounted early bird pricing.

WordCamp Salt Lake City has a history of bringing local ( and some not so local ) WordPress users, developers, designers and fans together in one spot on one day. I look forward to seeing everyone again.

Stateless CSRF Tokens

UPDATE: I posted improved versions of these functions in Better Stateless CSRF Tokens.

I’ve been thinking about CSRF tokens lately. If you are using the built in $_SESSION feature of PHP a common pattern goes something like this ( similar to what Chris Shiflett describes ) :



$token = base64_encode( openssl_random_pseudo_bytes( 32 ) );
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();


echo '<input type="hidden" name="token" value="' . $token . '" />';


if ( 
    isset( $_POST['token'] )
    && $_POST['token'] === $_SESSION['token'] 
) {
    if ( ( time() - $_SESSION['token_time'] ) <= 300 ) {
        // valid token, within time limit

A few notes about this approach. First, use openssl_random_pseudo_bytes instead of mt_rand ( suggested by Kevin Schroeder ) when possible. Second, be sure to only use === when comparing the token value. You want to avoid automatic type juggling.

Why worry about automatic type juggling when comparing CSRF tokens? Try this script:

$token = 'abc123';
$form_token = 0;

if ( $form_token == $token ) {
    echo "Valid token\n";
} else {
    echo "Invalid token\n";

Even though $token and $form_token clearly don’t contain the same values this script will display ‘Valid Token’ because of automatic type juggling. That makes your CSRF token basically useless as an attacker can set the token to zero and it will be considered valid. Switching to === will display the expected ‘Invalid token’.

This is all fine and good until you want to avoid using PHP sessions. Perhaps you have several web servers and don’t want to deal with shared session storage. Or have servers in multiple data centers and don’t want to try and sync state across them. What ever the reason, popping a token into $_SESSION isn’t an option in this case. In short you want some sort of stateless CSRF token.

One method is to generate a token based on known values that won’t change and lasts for a given period of time. This is what WordPress does. You can see the WordPress implementation in the inaccurately named wp_create_nonce and wp_verify_nonce functions ( WordPress nonces aren’t really nonces, they can be used more than once ). The high level version is that WordPress takes a known set of values like the user id, NONCE_KEY, descriptive action text, and current time; then runs them through an MD5 HMAC.

By default the tokens are good for 24 hours. You can adjust the time a WordPress nonce value is valid for by filtering nonce_life. That isn’t very flexible though. If you want to use different HMAC keys and timeouts across various requests then you end up having to filter both sides ( create and verify ).

I got to wondering what a more flexible approach to stateless CSRF tokens would look like. Here is what I’m thinking of:

function request_token_generate( $data_str, $key, $timeout = 900 ) {
    $now = microtime( true );
    $hash = hash_hmac( 'sha256', "$data_str|$now|$timeout", $key );

    return base64_encode( $hash ) . "|$now|$timeout";

function request_token_verify( $token, $data_str, $key ) {
    list( $hash, $hash_time, $timeout ) = explode( '|', $token, 3 );
    if ( empty( $hash ) || empty( $hash_time ) || empty( $timeout ) ) {
        return false;

    if ( microtime( true ) > $hash_time + $timeout ) {
        return false;

    $hash = base64_decode( $hash );
    $check_hash = hash_hmac( 
        'sha256', "$data_str|$hash_time|$timeout", $key 

    if ( $check_hash === $hash ) {
        return true;

    return false;

For request_token_generate you’ll need to provide a string containing unique data about the user and request, an HMAC key value, and an optional timeout. One example of the data string would be a combination of the internal user id, descriptive text about the action being taken, timestamp of when the password on the account was last changed, and the last 6 characters of the hashed password. Depending on the flow of the request you might want to include the URL that the form is expected to be on and the remote client IP address.

There is no specific limit on what you could include in the data string. Anything likely to be fairly unique to that user and request would be a good candidate. For that mater you could generate an additional unique key for each user at signup time that could be included.

$key = '5up3R53cr3T!';
$data_str = '45873' . 'delete_post_345' 
    . '2013-05-01 14:45:32' . '2dH6hi';
$request_token = request_token_generate( $data_str, $key );

echo "Token: $request_token\n";

That will produce a token that looks something like:


This is really 3 values separated by |, the first is the base64’d HMAC ( using SHA256 instead of MD5 ). The second value is the timestamp for when the token was generated and the third is how long the token is good for in seconds. Verifying the token is easy enough:

if ( request_token_verify( $request_token, $data_str, $key ) ) {
    echo "Valid token\n";
} else {
    echo "! INVALID ! token\n";

The verification side needs to have access to the same values that went into building $data_str and the HMAC key. You don’t need to know the timeout for the token because the timeout is included as part of the token value.

This approach prevents tampering by including the timestamp and the time out values as part of the HMAC call ( as does WordPress ). Testing this is easy enough:

$key = '5up3R53cr3T!';
$data_str = '45873' . 'delete_post_345' . '2013-05-01 14:45:32' . '0dH6hi';
$token = request_token_generate( $data_str, $key, 15 );

// confirm original works
echo "Should be valid: ";
if ( request_token_verify( $token, $data_str, $key ) ) {
    echo "Valid token\n";
} else {
    echo "! INVALID ! token\n";

// turn back time
list( $hash, $hash_time, $timeout ) = explode( '|', $token, 3 );
$hash_time = $hash_time - 100;
$fake_token = "$hash|$hash_time|$timeout";

echo "Should be INVALID: ";
if ( request_token_verify( $fake_token, $data_str, $key ) ) {
    echo "Valid token\n";
} else {
    echo "! INVALID ! token\n";

// alter timeout
list( $hash, $hash_time, $timeout ) = explode( '|', $token, 3 );
$fake_token = "$hash|$hash_time|10000";

echo "Should be INVALID: ";
if ( request_token_verify( $fake_token, $data_str, $key ) ) {
    echo "Valid token\n";
} else {
    echo "! INVALID ! token\n";

The first test checks that the unmodified token is valid. The second test attempts to set the timestamp back in time. The third attempts to increase the timeout value. The two altered tokens fail because the hash values no longer match.

Overall I’m happy with this approach to stateless CSRF tokens.

WordPress 10th Anniversary Party in Utah

You might have heard about WordPress turning 10 years old on May 27th. To celebrate local WordPress communities around the world are having anniversary parties on May 27th, 2013. This includes the greater Salt Lake City, Utah area. The details are at

When: Monday, May 27, 2013, 7:00 PM
Where: Sonny Brian’s; 33 East 11400 South in Sandy

View Larger Map

If you are coming be sure to RSVP so that we have an idea of how many people to expect. Bluehost is also giving away the 10th Anniversary WordPress t-shirts to the first 30 people who fill out this form on

It will be a fun time to hang out and chat with other local WordPress fans/users/designers/developers.

Code Garage Migration to VaultPress

Today VaultPress announced the Code Garage migration details. We really wanted to make sure that we had the details and options on this right. I know that migrations like this can often be annoying, so we went out of our way to make the process smooth and inviting.

Code Garage users that migrate to VaultPress will get their first two months on VaultPress free. For those who don’t want to migrate, we’ll refund your last payment.

Even if you aren’t a Code Garage customer, you should go read Peter’s CodeGarage Locker is Migrating to VaultPress post. He gives a personal history of how Code Garage came to be, how it grew, and how it ultimately was sold to Automattic.