DEV Community

Sohan
Sohan

Posted on

Beware of the New Enemy Problem ⚠️

Google Zanzibar is a globally distributed authorization system capable of processing "more than 10 million client queries per second," and powers all of Google's services including YouTube, Docs and Cloud IAM. Zanzibar was first described in a paper presented in 2019 and can be read here.

In this paper, there's the first mention of The New Enemy Problem - Described as: “[a failure] to respect the ordering between ACL updates or when we apply old ACLs to new content.”

Essentially, this is the name Google gave to two undesirable properties we wish to prevent in a distributed authorization system:

  1. Neglecting an Access Control List (ACL) update order
  2. Misapplying old ACLs to new content

In other words, the New Enemy Problem is a scenario where unauthorized access can occur when changes to permissions and the resources they protect are not updated together consistently.

A New Enemy Example

Here's an example featuring Lex (a bad actor) and Kara

New Enemy Problem

Essentially, Lex had permissions to view SeCrEt PlaNs but his access was revoked. But due to a stale ACL check, he is now able to read this document. In this example, Lex is the New Enemy.

Where New Enemy is Present

There are different ways Authorization is implemented in the industry today. The most common pattern is for organizations to implement their own custom Authorization. Some of these approaches can be prone to not solving the New Enemy Problem.

For example: I'd earlier discussed why using JSON Web Tokens (JWTs) for Authorization isn't a good idea and one of the reasons is because of the New Enemy Problem. You could revoke someone's access on your server, but they'd still have access if they're holding a valid JWT from before.

How Zanzibar solves it

In the Zanzibar paper there is a description to get an opaque token to a snapshot of the permissions as evaluated at a single point in time. This token is called a Zookie (possibly a portmanteau of Zanzibar and cookie). By combining a token which represents the exact permissions used to protect a specific version of the content, and the content itself, we can make sure that the permissions we use to check access to that content in the future is at least as fresh as the permissions when the content was created.

Here's an example of how it works in SpiceDB - a database inspired by Google Zanzibar. A zookie is passed when making a permissions check request, and guarantees that the policy and individual relationships used to compute the answer will be at least as fresh as the Zookie presented requires.

def write_content(user, content_id, new_content):
    is_allowed, zookie = authzed.content_change_check(content_id, user)
    if is_allowed:
        storage.write_content(contentd_id, new_content, zookie)
        return success
    return forbidden
Enter fullscreen mode Exit fullscreen mode

And when accessing the data, we use the following pseudocode:

def read_content(user, content_id):
    content, zookie = storage.get_content(content_id)
    is_allowed = authzed.check(content_id, user, zookie)
    if is_allowed:
        return content
    return forbidden
Enter fullscreen mode Exit fullscreen mode

This is a mechanism for enforcing that we will never give access to a version of the content to which the user has had their access revoked! New Enemy problem solved.

Here's our previous example, but this time with Zookies.

New Enemy solution

I did it all for the Zookie

You may have picked up on the fact that there are probably some inconsistencies that can be introduced by using a version of the permissions that are at least as fresh, but not always the exact current permissions. So what are they?

Let’s say at some point a user is granted access to a document in a way that doesn’t cause the document to store a new zookie. It may take some time for that access grant to propagate everywhere, and we may issue some false negative responses to check requests. This is an explicit choice to improve the performance of the system, while always guaranteeing that no false positives are ever issued.

Permissions mutations also return a Zookie so if you can easily identify the content to which permission is being granted, you can optionally update the zookie on the content when the new permissions are granted. This will enforce a causal ordering between the permissions change and the next access request! This can alleviate the problem with false negatives, by trading off higher load to the datastore which stores the content. This will make sense for some use cases, but not for others.

New Enemies New Friends

Open Worldwide Application Security Project (OWASP) publishes a "Top 10 Security Risks for Web Apps" list and currently Broken Access Control sits at the top of their list. Authorization systems based on Google Zanzibar such as SpiceDB solve for the New Enemy Problem, and in turn improve Access Control mechanisms in your software.

A burgler is reading an empty document

secretplans.doc can't be found

Let me know in the comments how you've solved for the New Enemy problem in your Authorization code.

Top comments (0)