the fundamental issue that maybe we just shouldn’t have magical blobs that grant you access to basically everything
But that’s not what bearer tokens are? They’re a cryptographically secure identity. They’re not magic, and they only give the service you’re using access that you approve.
I think the argument is that a combination of poorly defined permissions (tokens providing broad authorization) and poorly managed storage of tokens leads to a huge payday for anyone who manages to crack their way into that storage.
In the case of a Git repository, once you’ve given someone - it doesn’t matter who - a token for reading your code, it’s game over if that token gets leaked. Now anyone with the token can access your code.
I’m running into this problem right now (GitHub Actions deploying to my private hardware). I’m solving it by (1) using more tokens with finer grained permissions and (2) rotating those tokens frequently (maybe hourly?). If you get my bearer token, you have at most an hour and all you can do is deploy a different version (i.e., tag) of an image from my docker repository. Of course, if you can manage to publish an image to my docker repository and grab my bearer token, then you can do anything that my service is allowed to do (which also isn’t much).
EDIT: thinking about it more, I wonder if I could store the same secret on github and my deployment target such that github uses the secret to (symmetrically) encrypt the current timestamp and send that to my server, and the server would decrypt using the same secret and verify that the time is within some reasonable margin (say 1 minute). On top of that, I would rotate the signing secrets for good measure. Anyone who gets an encrypted timestamp has much less time to use it.
In the case of a Git repository, once you’ve given someone - it doesn’t matter who - a token for reading your code, it’s game over if that token gets leaked. Now anyone with the token can access your code.
Tokens are revocable and expire. It requires quick action to exploit.
The sibling comments point this out, but more directly: this “identity” is a “something you have.”
The service that issued the token stamped my business card and said: “Yup, that’s @apg!” It might have even done so by forcing me to go to my identity provider, first. But, if someone steals that stamped business card, and the service is only looking for a stamp, and for an assertion that no one has revoked that stamp, than it’s not a very strong identity.
Hmm… I don’t know about this tradeoff. That’s a lot of machinery that the client would need to add, for only low to moderate benefit. Most people would probably just continue using bearer tokens due to the complexity.
(I say low to moderate benefit because in many cases, the attacker could just make requests via a compromised system and act under its identity.)
I think my first step would be to increase the granularity of the permission model, maybe more like what you’d see in a capability system. Github currently exposes hilariously broad scopes for their Personal Access Tokens (https://github.com/settings/tokens/new). For example, the repo scope gives “full control of private repositories”. No! I want to be able to say “read-only permission to repos X, Y, and Z”, or “read and write, but only under org X”. Currently my only way to express these sorts of access restrictions is to create a service account and give it the necessary permissions, then create a token for that account. Very cumbersome. It would serve them well to smooth out that path: Reify service accounts, and provide a way to control their access to resources using a dedicated UI.
Granted, it requires running a Vault service, but that’s more or less a cost you pay once and then amortize over multiple scenarios to realize the benefits.
Aha! Good to know about their Apps having fine-grained permissions. I wish they would allow creation of long-lived personal access tokens with that granularity.
I know that’s conspiracy theory territory, but I wonder if GH even wants to change this situation. 3rd party services have limited options for good integration, get bought out and integrated and then work great under GH ownership. Same for the notification API not matching the notification screen and a few other API things that just don’t work as well as they could. They had years to fix them and the requests keep appearing in many places, yet they’re indifferent.
But that’s not what bearer tokens are? They’re a cryptographically secure identity. They’re not magic, and they only give the service you’re using access that you approve.
I think the argument is that a combination of poorly defined permissions (tokens providing broad authorization) and poorly managed storage of tokens leads to a huge payday for anyone who manages to crack their way into that storage.
In the case of a Git repository, once you’ve given someone - it doesn’t matter who - a token for reading your code, it’s game over if that token gets leaked. Now anyone with the token can access your code.
I’m running into this problem right now (GitHub Actions deploying to my private hardware). I’m solving it by (1) using more tokens with finer grained permissions and (2) rotating those tokens frequently (maybe hourly?). If you get my bearer token, you have at most an hour and all you can do is deploy a different version (i.e., tag) of an image from my docker repository. Of course, if you can manage to publish an image to my docker repository and grab my bearer token, then you can do anything that my service is allowed to do (which also isn’t much).
EDIT: thinking about it more, I wonder if I could store the same secret on github and my deployment target such that github uses the secret to (symmetrically) encrypt the current timestamp and send that to my server, and the server would decrypt using the same secret and verify that the time is within some reasonable margin (say 1 minute). On top of that, I would rotate the signing secrets for good measure. Anyone who gets an encrypted timestamp has much less time to use it.
Tokens are revocable and expire. It requires quick action to exploit.
The sibling comments point this out, but more directly: this “identity” is a “something you have.”
The service that issued the token stamped my business card and said: “Yup, that’s @apg!” It might have even done so by forcing me to go to my identity provider, first. But, if someone steals that stamped business card, and the service is only looking for a stamp, and for an assertion that no one has revoked that stamp, than it’s not a very strong identity.
Hmm… I don’t know about this tradeoff. That’s a lot of machinery that the client would need to add, for only low to moderate benefit. Most people would probably just continue using bearer tokens due to the complexity.
(I say low to moderate benefit because in many cases, the attacker could just make requests via a compromised system and act under its identity.)
I think my first step would be to increase the granularity of the permission model, maybe more like what you’d see in a capability system. Github currently exposes hilariously broad scopes for their Personal Access Tokens (https://github.com/settings/tokens/new). For example, the
repo
scope gives “full control of private repositories”. No! I want to be able to say “read-only permission to repos X, Y, and Z”, or “read and write, but only under org X”. Currently my only way to express these sorts of access restrictions is to create a service account and give it the necessary permissions, then create a token for that account. Very cumbersome. It would serve them well to smooth out that path: Reify service accounts, and provide a way to control their access to resources using a dedicated UI.We use this to solve the problems you mention:
https://github.com/martinbaillie/vault-plugin-secrets-github#permission-sets
Granted, it requires running a Vault service, but that’s more or less a cost you pay once and then amortize over multiple scenarios to realize the benefits.
Aha! Good to know about their Apps having fine-grained permissions. I wish they would allow creation of long-lived personal access tokens with that granularity.
And more to the point: it enables a lot of harm for not much benefit.
It protects against someone pretending to be an authorized dumb terminal that you are in front of, but doesn’t secure the computing device.
And the inaccessibility of the keys can be used to prevent you from asserting control of the software you run.
I know that’s conspiracy theory territory, but I wonder if GH even wants to change this situation. 3rd party services have limited options for good integration, get bought out and integrated and then work great under GH ownership. Same for the notification API not matching the notification screen and a few other API things that just don’t work as well as they could. They had years to fix them and the requests keep appearing in many places, yet they’re indifferent.