Python Artifactory Dependency Confusion Patch
This application is designed to work in conjunction with the Artifactory webhook to reserve names in the python public repository. When new python libraries are deployed to the internal Artifactory repository the webhook notifies the application and the name is reserved if available.
Python Dependency Confusion Supply Chain Attack
Supply chain attack vectors are becoming increasingly popular. This issue gained widespread attention through the blog post Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies. The Python environment is particularly vulnerable to such attacks.
If not configured properly, the Python dependency manager protocol can be exploited to install a malicious package instead of the intended one. The most common misconfiguration involves adding a private repository to the tool and allowing it to decide which version/package to download between the public and private repositories. By default, it will choose the package with the higher version number.
An attacker can exploit this by deploying a known library from a private repository into the public repository with a very high version number (e.g., version 999.9.9), thereby confusing the tool into installing the malicious package.
Artifactory
JFROG Artifactory is a popular private artifact repository that can also serve as a private repository for Python libraries. Artifactory includes built-in features to help mitigate dependency confusion attacks. However, it cannot fully solve the problem if the dependency management tool is not configured correctly.
Patching
The strategy of this application is to reserve the name on the public repository to prevent it from being taken by a malicious actor and used as an attack vector. If the name is already taken, it can optionally send a notification to a Slack webhook.
The application leverages the Artifactory webhook for deployed events to reserve the name.
Name reservation is done by publish a useless library with the same name into the python public repository with version 0.0.0
The package is meant to be used on an application that receives the Artifactory webhook POST request and send the JSON content to the library, as in the usage example.
Flowchart
Usage Example
Usage example code (requirements.txt) in a google cloud function:
import functions_framework
import traceback
import logging
from python_artifactory_dependency_confusion_patch import NotificationService, SlackNotification
from python_artifactory_dependency_confusion_patch import PublicNameReserver
logger = logging.getLogger("python_artifactory_dependency_confusion_patch")
notification_system = SlackNotification("<slack url>")
notification_service = NotificationService(notification_system, known_emails={"fix deps <fix@python.deps>"})
name_reserver = PublicNameReserver(notification_service)
@functions_framework.http
def reserve_name(request):
"""HTTP Cloud Function.
Args:
request (flask.Request): The request object.
<https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data>
Returns:
The response text, or any set of values that can be turned into a
Response object using `make_response`
<https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response>.
"""
request_json = request.get_json(silent=True)
try:
name_reserver.reserve_name_from_artifactory_body(request_json)
except Exception as exc:
print(f"Failed to process request {request_json}")
print(traceback.format_exc())
return ("", 200)
Note: "fix deps <fix@python.deps>" is the author email from the template
Note: For testing set TWINE_REPOSITORY_URL to test repository
Metadata
Release files for python-artifactory-dependency-confusion-patch 1.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_artifactory_dependency_confusion_patch-1.4.0.tar.gz | 12.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_artifactory_dependency_confusion_patch-1.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.0 kB
Release files / python_artifactory_dependency_confusion_patch-1.4.0.tar.gz
| Download URL | python_artifactory_dependency_confusion_patch-1.4.0.tar.gz |
|---|---|
| Size | 12.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e54a3c18cb1d832a8c725f367b1cff95b0f8da0134542814bed8933579138218
|
|
BLAKE2b-256 checksum How to use checksums |
4b4e0c29f30a19ee941fcc6d14189ff83469caecafaac4fffac97b2310ae2c86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.0.0 CPython/3.10.12
|
Release files / python_artifactory_dependency_confusion_patch-1.4.0-py3-none-any.whl
| Download URL | python_artifactory_dependency_confusion_patch-1.4.0-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
78cd0524199e30463c51ccfa2911e395afcf8ae0292de126e9beeca66e2cccef
|
|
BLAKE2b-256 checksum How to use checksums |
c416b95945dc54d3b63bd78ba906deb36f3be1ae48d5fa9b016d9f59ca9799ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.0.0 CPython/3.10.12
|