Career Failures

In the SecuriTEA & Crumpets episode referenced above, around 38:50, Arkadiy says:

I’m so envious you get to work with Clint.

Which, like the Grinch, made my heart swell 3 times.

But, he actually could have! I interviewed at Airbnb, probably in 2017 or so, and fun fact: Arkadiy was one of my interviewers! I did not do well in his interview, and Airbnb did not make me an offer.

I wanted to share this and a few more examples of my career failures, in any case any of you are under the mistaken impression that my career has been like a continuous DJ Khaled song. Here are a few highlights:

Out of undergrad I applied to a number of PhD programs. Almost all of them rejected me, so I went to one of the few that accepted me.

During grad school, the papers my colleagues and I worked on were often rejected by conferences, and during my entire PhD, I failed to publish a single paper in a “Tier 1” academic security conference.

I decided I wanted to go to industry after grad school, partly because I liked it better, partly because I didn’t feel like I had a very strong chance of becoming a professor at a reputable university.

I became a Security Engineer at a start-up, which ended up folding after 1.5 years.

I applied a few places, including Salesforce, which, after the interview, they made me an offer at a “Junior Security Engineer” title. Fun fact: Astha Singhal was one of my interviewers, who is now a friend, but we didn’t really know each other well until her Netflix days.

I decided to join NCC Group as a Security Consultant. I was probably ~28 years old at the time. If I had gone directly to NCC Group after undergrad, I probably would have been the same level (and maybe have more hands-on skills) by 24.

During my NCC years, I was often stressed about if I was providing enough client value on projects, as I had many colleagues who were absolutely incredible.

I periodically tested the waters for outside opportunities, sometimes getting offers, sometimes not, like Airbnb. Oh by the way, the Airbnb role was to focus on static analysis. Now I lead a team at a company building a static analysis tool :laugh:

Oh yeah, I’ve interviewed for roles at Google several times, and never made it past the first round of interviews. Live coding makes me nervous, and studying algorithmic challenges is quite boring to me, so I don’t put in the necessary prep time. I distinctly remember an initial phone screen as I was finishing grad school where a Google Fonts engineer asked me to write a function to clone a graph. I then proceeded to flail embarrassingly for ~30 minutes, and at the end he asked me, “So do you have any questions for me?” I wanted to say, “No! You work on Fonts, you probably know nothing about the teams I care about working on.” But I probably asked some boring question instead.

CLINT 30% chance thought was going to abjectly fail at r2c.

Imagine There’s No Human Error

Alright, I’m about to connect two very disparate things, but wait for it.

Also, I’ll caveat this by saying I am not an expert in this domain, so I may be terribly ignorant.

Imagine there’s no human error…
By Netflix’s Lorin Hochstein. When an incident happens, one of the causes is often “human error.” This unfortunately tends to end root cause investigation. But humans are basically like machines in that given a series of inputs (your background experiences and knowledge, current hunger or sleepiness level, etc.) and some sort of “goodness” function you use to make a given decision, you pick the outcome that seems best.

So if a user did bad_thing instead of good_thing, we can ask ourselves, “Why did their current state and goodness function cause them to do that?” There’s no concept of “error” in this model.

From this view, the reason a vulnerability was introduced is never “this developer was dumb,” but rather, why did they make this decision? Were they unaware of the implications of the code they wrote? Were they under stress and under a tight deadline? Was the fix too complex or required too much effort?

Every decision is logical given the right “person-state” and goodness function.

To me, this has important implications on security tooling and how we build security programs.

OK, now the shift.

How Much Incel Terrorism Can We Prevent With Kindness?
Daniel Miessler hypothesizes that oftentimes violence is perpetrated by young men who’ve experienced some combination of broken or unhealthy home lives and parenting, economic instability and/or limited economic opportunities, serial rejection from romantic partners, bullying in school, etc.

Their behavior is inexcusable, but at least to me, it’s not impossible to see how a series of very bad life events could significantly alter someone’s goodness function for the worse.

To invert it, I also think of it this way: if you have a job you find fulfilling, friends who care about you, enough money to live comfortably, and a romantic partner you love, are you: spewing vitriol on the Internet, marching on the Capitol to overthrow democracy, committing acts of violence, or gatekeeping newcomers to your field? Probably not.

So the question I ask myself is, how can we structure schools, society, and organizations, and how can I act myself and how can we act as a community, such that, over time, more and more people’s goodness functions are happy and healthy?

I think about this a lot. More on this later.

Owning Your Platform

(19) ᴅᴀɴɪᴇʟ ᴍɪᴇssʟᴇʀ on Twitter: “Twitter might turn out to be another example of why you should build your personal digital presence off your domain, not a platform. A lot of people have spent tens of thousand of hours getting popular on Twitter. And it can just go away, like Medium or Blogspot.” / Twitter

You need to ask yourself: what would happen if platform X went way?

If the answer is that you’d be screwed, find ways to make that not true.

Take inventory of the platforms you use for your digital identity and “brand” Realize that all of them can go away, with Twitter as a case in point about volatility Make sure your core content is all primarily at your domain, with all other platforms being syndication channels Assume all channels are temporary, and always use your domain as home base

Joe Sullivan

[(99+) Post LinkedIn](

IMO, this is the most fair and balanced view of the Uber trial and verdict out there. Very much recommend reading this over spending time on the recent vague, uninformed comments and articles.

This is not a simple and straightforward case. Jody Westby details the nuances of the legal, privacy, governance, and reporting requirements that together form the whole of what happened here. Not to mention, what should have happened here.

Big kudos to Jody Westby for such an excellent article. I hope it gets widespread attention by being published in Forbes.

Uber Trial: A Lost Opportunity For Cyber Governance

Resume Advice

Gergely Orosz has a nice Twitter thread:

“After reviewing 200+ dev resumes from software engineers who are job hunting - new grads, seniors, principals - here are the 9 most common pieces of feedback I’ve given.”

  1. Too many personal details on the resume. Many devs have their photo, birth date - some even marital status, number of kids.
    • DONT DO THIS. You are exposing yourself for biases, have nothing to gain & much to lose. These details are not required by tech companies.
  2. Not having the things easy to find on the first page that hiring managers and recruiters look for. Relevant languages & technologies, work experience (titles, companies), and dates to give an idea of the number of years’ experience you have.
  3. Talking about the “what” you did, but not the results, impact and contribution, with specifics. Too many resumes list “Company X, worked on System X”. You want to convey the impact your work had, and how you (significantly) moved the needle.
  4. Being verbose about things hiring managers don’t care about. This is especially for experienced candidates. I don’t care about the Symbian project you did 15 years ago, or the 3 internships you did 10 years ago. Focus on the recent impact, achievements, and skills.
  5. “The basics” missing. Spelling mistakes and poor grammar convey poor attention to detail. Hard to read formats, BOLDING every SECOND word, date formats flipped, compared to the country you are applying to.
  6. “Abusing” the one-page resume. This is especially for ambitious new grads. I’ve seen tiny fonts, so that two pages of projects with intricate detail could be listed on that one page. Be concise and focus on the most important things. Project #6 is not that important.
  7. Having the exact same resume for all positions. In the day of ATSes (Appliaction Tracking Systems), you NEED to customize your resume for the position, especially when you will be up against hundreds of them. Tailor and cut down your “master” resume for that job listing.
  8. Putting your weaknesses front and center. A backend-heavy fullstack dev attached links to the terrible UI of the app they built. Another dev listed all their “novice” languages. Your resume should sell you - you can talk about weaknesses on interviews. This is not the place.
  9. Links on the resume pointing to poor work. Github links pointing to a repo with no decent projects - not even a readme. A link to Medium bringing the first post about on how this person hates their team. You don’t have to add links. But if you add them, make them count.

Code Patterns for API Authorization: Designing for Security

I’ve be wanting to write basically the same blog post for awhile, but damnit, Tanner Prynn beat me to it, and he did a great job.

Tanner describes four different common patterns when implementing authorization for web apps and APIs, and compares their security trade-offs.

#1: Ad-hoc: each route defines its own permission checks and logic.

def get_message(context, message_id):
 message = get_message(message_id)

 if context.user == message.recipient:
   return message

 return "Not authorized"

Authn is performed as a one-off, direct object ID comparison within the controller method, which means this is very hard to audit at scale. Once you get to a certain size/complexity of app, basically no one fully knows what access controls should be. “Ha!” you scoff, stroking your distinguished security greybeard, “Surely every dev team should know what their product’s access controls should be.” Well, in a number of pen tests I performed, for very complicated apps (e.g. you have users, admins, teams, orgs, the teams/orgs can have relationships, …), that’s actually sometimes not the case.

Testing these apps can best be done via dynamic testing, for example with Burp Suite extensions like AutoRepeater or Autorize.

#2: Route-based: each route explicitly declares what permissions it requires, generally by a decorator or in a routing file, and middleware checks the authz before running the route logic

def get_message(message_id):
  return get_message(message_id)

Pro: authz checks are very clear.


  • Sometimes cannot effectively model the authz you want. For example, there are often cases where you need more context to make the decision (you want to check whether a user has access to a specific object), so you implement that check again in the route itself.
  • Sometimes you may fail open (no annotation => no authz checked)

On democracy

One meta concern I have is about the future of American democracy.

  • Americans continue to become more polarized, and there’s no central leadership trying to unify and heal us.
  • Trump has been systematically firing everyone who disagrees with or investigates him (e.g. inspector generals).
  • U.S. police have attacked journalists more than 120 times since May 28: “in the majority of the cases we have recorded the journalists are clearly identifiable as press, and it is clear that they are being deliberately targeted.”
  • Governments often use times of unrest to gain additional powers to “keep the peace.” Does Trump seem like someone who willingly gives up power once he has it?
  • It’s unclear if Trump will step down if he doesn’t win the election. TODO michael cohen link

Last year I visited Yad Vashem, the Holocaust museum in Jerusalem. It was one of those most moving experiences I’ve ever had, bar none. It was incredible to see what humans can do to each other, and justify to themselves.

One of the biggest things that stuck out to me was how fast everything happened.

It seems obvious and inevitable when we read about it in books or see exhibits in a museum, but what happened and where things were headed was not obvious from the inside at the time.

From Hitler’s rise to power, to his initial concerning rhetoric, to individuals vandalizing synagogues and Jewish owned businesses, to official government policy to round up undesirables - that all happened in few months.

One Jewish man was later asked, “Why don’t you leave when hooligans started throwing rocks through your business’s windows and harrassing you?” He replied, “Because we’re German, we’ve lived here our whole lives. Yeah, there was some harrassment, but that’s just the way it is being a Jew. And yes, there was some concerning rhetoric, but we thought those were just words to rally people.”

Things can change quickly.

Do I think we’re in the same situation? No, but I would caution us to be very careful when checks and balances are eroded, and power is consolidated.

We take for granted that America is the land of the free, but that’s not a guaranteed future. We fought a war to make create America that way, hopefully we won’t have to fight another.

Work Is Work

H/T Jon Hawes for the link to this.

If agile, flat organizations, code reviews, monorepos, open offices, fancy type systems, etc. were actually the causal factors they’re purported to be, then why do so many organizations adopt those practices without success?

If you squint hard enough, an organization doing work is just an incredibly complex, dynamic, distributed, parallel process.

Modeling organizations as parallel processes can inform the way we design them.

The work capacity of an organization scales, at most, linearly as new members are added.

As an organization hires more employees, work on productivity improvements must be a constant priority. Internal tooling, training, and services must be developed and fielded to ensure that all members are able to work on problems of continuously increasing impact. The ceaseless pursuit of force multipliers is the only possible route to superlinear productivity improvements as an organization grows.

It must be emphasized that this linear bound on work capacity is a ceiling, not a floor. One cannot do better than linear, but one can certainly do worse. There are many other factors which act as a drag on work capacity, and organization-wide improvements in productivity are critical in mitigating them.

Contention costs grow superlinearly as new members are added. Parallel solutions to tasks are rarely perfectly concurrent, and often require some sequential critical sections.

Shared resources aren’t necessarily physical things, like bathrooms or printers; they can be digital, like files in a source code repository or tickets in a bug tracker, or organizational, like code reviews or work assignments. As with writing highly-concurrent applications, building high-performing organizations requires a careful and continuous search for shared resources, and developing explicit strategies for mitigating their impact on performance.

As with heavily layered applications, the more distance between those designing the organization and the work being done, the greater the risk of unmanaged points of contention. Top-down organizational methods can lead to subdivisions which seem like parallel efforts when listed on a slide but which are, in actuality, highly interdependent and interlocking. Staffing highly sequential efforts as if they were entirely parallel leads to catastrophe.

Coherence costs grow quadratically as new members are added. Working on complex tasks using parallel resources (or with a group of people) requires communication.

Communication takes time. If the relative percentage of people who need to talk to each other to get something done stays constant as the organization grows, the total time spent communicating will grow quadratically as the work capacity of the organization grows linearly.

We can consider group meetings as a batching strategy to reduce the number of entities involved in point-to-point communications, but the effectiveness of this strategy depends heavily on the relative overlap of groups and the group structures.

The only scalable strategy for containing coherence costs is to limit the number of people an individual needs to talk to in order to do their job to a constant factor.

If the organization’s intent is to increase value delivery by hiring more people, work efforts must be as independent as possible. Leaders should develop practices and processes to ensure that the work efforts which their strategies consider parallel are actually parallel. Shared resources should be continuously managed for contention, and where possible, the resources a group needs should be colocated with that group (e.g., if the work involves a lot of design, staff a designer to that group).

If an organization is largely working on the same types of problems it was in previous years, it’s cause for concern. Teams dedicated to internal tooling should be staffed and given the explicit direction of building tools and optimizing processes to help increase their co-workers’ productivity. Go long on high-leverage tools, but stay grounded in whether or not they actually help.

  1. Keep the work parallel, the groups small, and the resources local.
  2. Prioritize the development of force multipliers.
  3. If possible, factor work products into independent modules; if not, grow slowly and optimize.

If your work product–e.g. codebase, documents, etc.–can be factored into independent modules, do so. The key word there is independent. Slicing your shit up into a hundred microservices will not help you if everyone needs to change ten of them to get anything done. Some problems are not particularly amenable to partition; these are also problems which do not benefit much from additional workers.

Organization leaders should keep the development of a product portfolio as an explicit goal. Feature or product ideas which are complimentary to the organization’s overall business strategy but don’t naturally coexist with the main product can be developed as separate products by independent teams.

  1. Keep responsibility assignment matrices small, sparse, and local.

As an organization matures, ad-hoc roles are often developed into full teams. This specialization is often critical for building internal economies of scale, but the formalization of new constituencies should be kept in check

Where a matrix indicates a high-touch relationship between two groups (e.g., a group of engineers working on a feature and the lawyers trying to ensure the legal compliance of that feature), efforts should be made to reduce the cost of that interaction by colocating their members (e.g., embed a lawyer with the engineers).

  1. Prioritize asynchronous information distribution over synchronous.

A significant source of failure demand for meetings and status updates is the desire of organizational leaders to keep abreast of who’s doing what. This situational awareness is indeed important, but trying to maintain it by calling meetings, messaging people on Slack, and catching people on the hallways is a significant systemic drag on organizational productivity.

A better model for staying informed of developments as the organization scales is for groups to publish status updates as part of the regular cadence of their work. Leaders can asynchronously read these updates and, should the need arise, initiate additional, synchronous conversation to ask questions, provide feedback, etc.

Synchronous meetings should be reserved for low-latency collaboration on complex issues; likewise, collaboration should be reserved for synchronous meetings.

Companies are groups of people being compensated for having to spend some of their finite lifetimes not being with their partners, children, pets, or super weird hobbies. They deserve to be members of organizations which honor that time by ensuring that their work has value and meaning.

Darklang: A New Way of Building Serverless Backends

Nerd sniped by my friends Yoann and Martin

Former CEO/co-founder of CircleCI, PhD in compilers and static analysis

Demo: Office Sign-in Application

Philosophy: Why Dark with CTO Paul Biggar

What is Dark?

Citizen Kane Lame

There’s been a few articles recently about Citizen, a crime and neighborhood watch app.

‘FIND THIS FUCK:’ Inside Citizen’s Dangerous Effort to Cash In On Vigilantism
As an LA wildfire broke out, Citizen CEO Andrew Frame saw it as an opportunity. They offered first $10,000, then up to $30,000 for a tip that lead to the suspect’s arrest.

But the man whose name and face they shared with the world was innocent.

Tech companies want to juice engagement metrics. For Citizen, that means more people reporting more incidents, regardless of if they’re real, or how solid the evidence is.

“It’s basically an anxiety sweatshop,” a Citizen source said. “On days when things are ‘slow,’ they relax the standards around incidents because a dip in incident count is really bad,” they added. The company sends congratulatory emails announcing which analysts reported the highest number of incidents, another source added.

After all, if users don’t feel safe, they’ll want to pay Citizen for protection.

Just like how social media and consumer products don’t want you to be happy. Why? If you were happy, you’d probably be spending time with friends, not doom scrolling Twitbook or buying things you don’t need.

“In a healthy society we are typically not incentivized to sensationalize mundane events and code them as crime. I can’t help but think it plays into people’s anxieties and fears and magnifies people’s fears of the other,” Gilliard said. “What’s really dangerous is the ways they’re starting to serve as infrastructure, where people start to feel like they have to use them to maintain society and order.”

Oh and also: Hacktivist posts massive Citizen scrape to dark web.

Obvious Bot is Obvious

✉️ Wrapping Up

Have questions, comments, or feedback? Just reply directly, I'd love to hear from you.

If you find this newsletter useful and know other people who would too, I'd really appreciate if you'd forward it to them 🙏

Thanks for reading!