When you're trying to minimize the new risk that you are bringing in through open source, its important to take a close look at any new packages your teams bring in. It's important to know how a package stacks up against your organization's risk tolerance. In this article, we'll explore how you can do so using Tidelift's APIs.
To evaluate a package with Tidelift's API, use the Tidelift package APIs.
When evaluating a package, you should focus on these items in the API output:
tidelift_recommendation
You should make sure that you are using packages that are good bets to:
- remain maintained
- use secure development practices
- fix security issues that may arise
Tidelift evaluates packages on a set of maintenance and secure development criteria.
A recommendation from Tidelift indicates a package that is a good choice to to use for application development. Conversely, a package that is not recommended, is one that should not be used for new development, and should be migrated away from in existing codebases.
For information on why the package is recommended (or not), see the tidelift_recommendation_reasons field.
alternative_packages
When a package isn't recommended, you need to know what you should use instead, to plan a migration. Where possible, Tidelift returns alternative packages that can be used instead of a package that isn't recommended.
license
You need to make sure that you are using software that doesn't impose restrictions that affect your organization based on where and how you use the software.
Tidelift reads upstream license definitions, and corrects them to ensure they are in machine readable form. Where the license is ambiguous or missing, Tidelift researches the license.
The license field provides details about what the license is, and where the license information came from. You can use this to ensure you do not use software that is licensed against your policies.
latest_recommended_release
When you are bringing in new software, you want to make sure that you are using a version of it that won't bring issues into your codebase.
Tidelift evaluates releases to check for a number of possible issues, including whether it will bring issues into your software via the release's dependencies.
The latest recommended release from Tidelift is the most recent release that passes all these checks.
releases
As noted, Tidelift evaluates each release of the software. The releases array gives the date each release of the software was published, and whether it passes Tidelift's checks. To get more information on a specific release, you can use Tidelift's release API.
For a description of all fields returned, see the Tidelift API documentation.
Evaluating a single package
Let's evaluate the Python package urllib3. The API is called with parameters for the package manager (pypi) and the package name (urllib3).
https://api.tidelift.com/external-api/v1/packages/pypi/urllib3
NOTE
All calls to Tidelift's API require an API key. For more information on how to call Tidelift APIs, examples for different programming languages, and API keys, see How to access Tidelift APIs.
Example using curl
curl -H "Accept: application/json" -H "Authorization: bearer <your Tidelift API key>" \
https://api.tidelift.com/external-api/v1/packages/pypi/urllib3
The API returns results in JSON format.
{
"name": "urllib3",
"platform": "pypi",
"purl": "pkg:pypi/urllib3",
"description": "HTTP library with thread-safe connection pooling, file post, and more.",
"tidelift_recommendation": "recommended",
"is_lifted": true,
"tidelift_recommendation_reasons": [
"is lifted"
],
"alternative_packages": [],
"last_changed_on": "2024-01-31",
"versioning_scheme": "semver",
"security_policy_url": "https://tidelift.com/docs/security",
"contributors_count": 320,
"package_manager_url": "https://pypi.org/project/urllib3/",
"sdlc_policy": "https://support.tidelift.com/hc/en-us/articles/4406288074260-Lifter-tasks-overview",
"sdlc_evidence": "https://support.tidelift.com/hc/en-us/articles/4406288074260-Lifter-tasks-overview",
"repository": {
"url": "https://github.com/urllib3/urllib3",
"source": "package_manager"
},
"license": {
"expression": "MIT AND PSF-2.0",
"source": "verified_by_maintainer"
},
"latest_release": {
"version": "2.2.0",
"published_at": "2024-01-30T15:18:04.000Z"
},
"latest_stable_release": {
"version": "2.2.0",
"published_at": "2024-01-30T15:18:04.000Z"
},
"latest_recommended_release": {
"version": "2.2.0",
"published_at": "2024-01-30T15:18:04.000Z"
},
"releases": [
{
"version": "2.2.0",
"published_at": "2024-01-30T15:18:04.000Z",
"tidelift_recommendation": "recommended"
},
{
"version": "2.1.0",
"published_at": "2023-11-13T12:29:42.000Z",
"tidelift_recommendation": "recommended"
},
{
"version": "2.0.7",
"published_at": "2023-10-17T17:46:48.000Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.6",
"published_at": "2023-10-02T17:22:34.000Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.5",
"published_at": "2023-09-20T07:30:33.000Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.4",
"published_at": "2023-07-19T15:51:22.000Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.3",
"published_at": "2023-06-07T11:02:23.021Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.2",
"published_at": "2023-05-03T22:39:48.367Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.1",
"published_at": "2023-04-30T09:01:54.505Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.0",
"published_at": "2023-04-27T17:02:34.149Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.0a4",
"published_at": "2023-04-25T18:58:36.576Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.0a3",
"published_at": "2023-01-11T13:06:37.317Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.0a2",
"published_at": "2022-11-23T22:50:36.321Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "2.0.0a1",
"published_at": "2022-11-15T15:45:34.909Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "1.26.18",
"published_at": "2023-10-17T17:47:01.000Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "1.26.17",
"published_at": "2023-10-02T17:22:28.000Z",
"tidelift_recommendation": "not_recommended"
},
<a number of releases removed for brevity>
{
"version": "0.3",
"published_at": "2023-07-20T16:29:29.285Z",
"tidelift_recommendation": "not_recommended"
},
{
"version": "0.2",
"published_at": "2009-12-11T08:47:22.000Z",
"tidelift_recommendation": "not_recommended"
}
],
"repository_statistics": {
"last_52_weeks_contributors": 17,
"last_commit_at": "2024-01-29",
"one_year_closed_pull_requests": 257,
"one_year_total_pull_requests": 280,
"one_year_closed_issues": 140,
"one_year_total_issues": 207,
"status": "Active"
},
"quality_checks": {
"no_executable_artifacts_in_the_source_repository": {
"status": "passed"
},
"no_known_vulnerabilities_on_latest_release": {
"status": "passed"
},
"no_known_issues_in_dependencies_for_latest_release": {
"status": "passed"
},
"discoverable_security_policy": {
"status": "passed"
},
"two_factor_authentication_at_source_repository": {
"status": "passed"
},
"two_factor_authentication_for_package_manager": {
"status": "passed"
},
"release_managers_are_reviewed": {
"status": "passed"
},
"package_has_a_defined_machine_readable_license": {
"status": "passed"
},
"package_has_a_clean_release_available": {
"status": "passed"
},
"package_is_not_deprecated": {
"status": "passed"
},
"package_appears_maintained": {
"status": "passed"
},
"package_has_a_stable_release_greater_than_two_years_old": {
"status": "passed"
},
"releases_are_discoverable_upstream": {
"status": "passed"
},
"responsive_to_security_issues": {
"status": "passed"
},
"security_vulnerabilities_have_recommendations": {
"status": "passed"
},
"uses_code_review_practices": {
"status": "passed"
},
"uses_fuzzing_tools": {
"status": "passed"
}
},
}
Evaluating packages at scale
Tidelift offers a bulk API that can return information on up to 1000 packages.
To call this API, use a POST call and pass the list of packages to be evaluated as JSON in the body of the POST request.
To perform an evaluation of the python packages urllib3 and requests, you would pass the following:
{
"packages": [
{
"platform": "pypi",
"name": "urllib3"
},
{
"platform": "pypi",
"name": "requests"
}
]
}
This API returns the same data as the individual package API, and you can use the same fields for each package to evaluate it.
Example using curl
curl -H "Accept: application/json" -H "Authorization: bearer <your Tidelift API key>" -X POST \
https://api.tidelift.com/external-api/v1/packages/lookup --json @<file with the above json data>
What if you don't know the name of the package?
Tidelift offers a search API to look up package names that can be used with our package APIs. This API can be called with one or multiple of:
- the package manager
- a name substring
- a source repository (such as a GitHub URL)
This API returns the package manager name and platform.
For example, if we wanted to find the package manager and package name for a package hosted at https://github.com/browserify/resolve, we would issue a GET request to:
https://api.tidelift.com/external-api/v1/packages?source_repository_url=https://github.com/browserify/resolve
Example using curl
curl -H "Accept: application/json" -H "Authorization: bearer <your Tidelift API key>" \
https://api.tidelift.com/external-api/v1/packages?source_repository_url=https://github.com/browserify/resolve
This gives us the npm package "resolve", and its repackaging on the "maven" repository as well:
{
"current_page": 1,
"next_page": null,
"prev_page": null,
"total_pages": 1,
"total_count": 2,
"per_page": 100,
"results": [
{
"platform": "maven",
"name": "org.webjars.npm:resolve"
},
{
"platform": "npm",
"name": "resolve"
}
]
}