Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Risk of leaking API keys via new "authenticated Badge API" feature in 4.12 #4227

Open
2 tasks done
m-erhardt opened this issue Oct 8, 2024 · 14 comments
Open
2 tasks done
Labels
enhancement New feature or request

Comments

@m-erhardt
Copy link

Current Behavior

I've just upgraded my DependencyTrack instance to 4.12 and read about the the new "authenticated Badge API" feature (#3596, #4059) in the changelog.

Whilst I am a strong supporter of security I am deeply concerned about the way this feature is implemented (in combination with how Git hosting platforms have implemented badge support).

Most Git repo hosting platforms like GitLab, GitHub, Gitea, Forgejo, etc embed badge-URLs in the HTML-DOM of the page (either via an explicit Badge-feature like GitLab or embedding an image in a Markdown file within the repo) and clients load the badge-svg directly from DependencyTrack.

Given the way the feature is implemented I would have to append an apiKey-URL-parameter to the badge URL which would then leak to all users/clients, even with readonly support to the repo. Plus I would need to commit the API key to the repo for platforms which only support badges via embedded images in Markdown.

This might be unproblematic and only require a secret-scanning exception when using a properly scoped API token which only has the VIEW_BADGES permission but considering the nature of users it is only a matter of time until a user uses/leaks an API key with way more permissions this way - putting the security of my DependencyTrack instance in a worse place than before the "authenticated Badge API" feature.

Is there anyone else sharing my concerns?

Proposed Behavior

This could potentially be resolved by

  • Allowing admins to enable/disable the "authenticated Badge API" feature on an instance/project basis (depending on the Security Model of the instance/project)
  • Using a project-specific nonce to authenticate requests to the badge API endpoints (instead of regular API keys)

Checklist

@m-erhardt m-erhardt added the enhancement New feature or request label Oct 8, 2024
@valentijnscholten
Copy link
Contributor

The way I read it is that the apiKey only needs VIEW_BADGES permission. If such a key leaks, it's no worse than the current unauthenticated badge?

@m-erhardt
Copy link
Author

m-erhardt commented Oct 9, 2024

I agree, IF a user configures this correctly it does not matter if API keys with only an VIEW_BADGE permission are exposed.
That's why I opened this issue as an "enhancement", not an actual security issue.

My thinking however follows the principle of Poka yoke. A system should be designed in a way that prevents the user from making dangerous mistakes.

InfoSec guys have tried educating developers and admins for years that API keys should be kept secret and how not to expose them.

Now DependencyTrack implements a feature that forces users to expose some API keys and expects every developer to always be fully aware of DependencyTracks security model.

My experience tells me it is probably a matter of weeks rather than months until a user accidentially exposes an API key with additional permissions this way.

@rkg-mm
Copy link
Contributor

rkg-mm commented Oct 11, 2024

Simple solution proposal:
If a group gets VIEW_BADGES Permission, ensure no other permission can be assigned additionally. If another one was assigned already, prevent assigning of VIEW_BADGES with some hint.

@m-erhardt
Copy link
Author

@rkg-mm : not perfect but certainly a huge step in the right direction.

I could still think of developers trying to implement a badge for their repo, seeing the apiKey-parameter and accidentially using an API key that was given to them i.e. for SBOM uploads.

So your proposed solution would make them aware of the mishap AFTER they've accidentialy exposed a more powerful API key.

As research from the past years has shown it takes malicious crawlers only minutes to pick up leaked secrets from public repos and start using them.

So to prevent further damage an immediate rollover of the exposed API key would still be required.

@SaberStrat
Copy link

SaberStrat commented Oct 13, 2024

I see how this adds a new angle for human error. But what are realistic safeguards for an API that shares sensitive information but is also typically used publicly?

One of your proposed solutions, allowing an admin to disable authentication for badges on an instance level, is already there.
It's planned to be an temporary feature, but unauthenticated access to badges could be kept around. Though I'm not sure what the use case for that would sound like...in case you don't trust your users to handle API keys or violates company compliance on exposing security keys?

The past option to entirely disable badges could be put back in too, if you want to lock down your instance more.
EDIT: That is already possible, if you switch on authentication for badges but don't give any team the VIEW_BADGES permission.

As for disabling it on a project basis, that should already be possible through Portfolio Access Control if your admin uses separate teams for badges.

But that is all irrelevant if you don't trust either users/clients to use the right API key or admins to create and/or hand out a key that doesn't accidentally have more permission than intended.

The other proposed solutions here suggest introducing a separate authentication methods (nonces) or an additional permission assignment logic that's exclusive to VIEW_BADGES. That would be a way, but just for badges?
Are there other enhancement proposals for Dependency-Track's current authentication and authorization that could benefit from additional methods and logic? @valentijnscholten

As for how other tools do it, I know of SonarQube, that presents a badge url generation UI under a project's settings, which creates a project specific badge URL with a project specific and renewable token. It separates the process from the usual permission management, reducing the chances of human error. But it still hands out a token to the user/client.

@valentijnscholten
Copy link
Contributor

What is the use-case of having authentication on badges? I can understand you might not want to share this information "publicly". But if you put a secret in the url, you'll more or less lost straightaway? Are there use-cases where having a secret in the url to display badges makes sense? Honest question.

Either way, the apiKey is meant to interact with the API. The secret in the url is not really matching that purpose. Might it make more sense to just have a per project settings to show badges publicly/with-a-secret/not-at-all?

@SaberStrat
Copy link

Well, one first needs to find where badges from your DT instance are used. Not a huge hurdle, but a hurdle compared to open access to anyone who knows the address of your instance and project names and versions. But if you combine it with portfolio access control, you can really limit access properly, along with the ability to revoke keys and access granularly on a project basis. At least that's how Steve's original suggestion for it made sense to me.

The lack of the ability to limit access to projects' evaluations, i.e. exposing all of my DT instance's projects' vulnerability counts, was what kept me from turning badges on on my instance. Steve's suggestion was a welcome and natural one, given DT's current access control system. Doesn't mean alternatives couldn't be implemented with badges in mind...up to DT's maintainers to decide.

API keys are the current way to authorise requests, i.e. connect them to teams, and thus make use of DT's current implementation of access control to projects. Using that, it is already possible to control "with-a-secret/not-at-all." Offering access publicly (without a secret) on a project basis would need to be implemented as a new feature. But what would be the use case of that? Some projects being more sensitive than others?

@m-erhardt
Copy link
Author

@SaberStrat : It's not that I generally do not trust my users to handle secrets. Not every user is always fully aware of the differentiated security model of every system they use. So sometimes when educating users/developers we need to oversimplify.

An oversimplification that works pretty good is "treat all API keys/passwords/credentials/private keys as secrets and store them as such".

It is visually impossible to distinct an API key which grants full administrative permssions to a system from an API key that only grants read-only access to a particular feature.

That's why the idea that some DependencyTrack API keys can and need to be exposed while others need to remain secret bothers me so much. It just bears a huge potential for mishaps.

The security model of my DependencyTrack instance would allow me to run the badge API endpoint without any authentification but I agree that other, internet-accessible instances, have this requirement as it is a potential "information disclosure weakness".

That's why I suggested an alternative authentification mechanism (nonces) in the first place.

@SaberStrat
Copy link

The security model of my DependencyTrack instance would allow me to run the badge API endpoint without any authentification but I agree that other, internet-accessible instances, have this requirement as it is a potential "information disclosure weakness".

That's why I suggested an alternative authentification mechanism (nonces) in the first place.

Interesting points of view, thank you for explaining.

What do you think @nscuro, should we

  • still go through with the removal of unauthenticated access to badges with the current API key based authentication, or
  • keep the option for unauthenticated access to badges in for DT users who don't want to risk using API keys and postpone the removal until we have a more foolproof authentication/authorization method for badges? For example maybe with Provide Support for Secure API Authentication #4249?

@valentijnscholten
Copy link
Contributor

valentijnscholten commented Oct 15, 2024

@SaberStrat I am still interested to know how you would use these urls with a secret in it to authenticate for badges. Let's say you have the URL https://dt.com/project/12345/badges?token=9876. What will you do with it? Will it be put in a README? On an intranet? Some dashboard or scorecard? Or only in emails? Is there a scenario where you can use these without "leaking" the token too broadly?

@sschuberth

This comment has been minimized.

@valentijnscholten
Copy link
Contributor

Correct, fixed.

@SaberStrat
Copy link

@valentijnscholten I don't know yet what the best implementation might be be, and it's not guaranteed I will before 4.13, which was originally intended to be the version to remove unauthenticated access to badges. But since @m-erhardt has a use case where unauthenticated access is safer for him than working with API keys, there might be reason to postpone the removal (or even keep it altogether).

@SaberStrat
Copy link

Will have to read up how nonces work and could work here.

Off the top of my head, I'm indeed thinking of some URL containing a project-specific (or project-version-specific) token. It should be possible to use it in Markdown docs (e.g. READMEs), HTML docs, so should be a URL without the need of a header. But I'm not all that versed with all use cases of badges either, so I can't say for sure if there aren't other formats that would be sufficiently universal too and safer than what URL allow.
But, if targeted for use in committed files, whether that project specific token is likely to leak or not would be up to the way the DT instance is used. The badge API as it is now, could be kept around and can be used with an API key.

Badges are by nature things that are potentially shown off publicly. Vulnerabilities don't have to be shared with the public, but can - like this project does here on GitHub for example. So it should be possible to display them in public, but should be possible to limit what can be accessed with that URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants