Remediate a vulnerable Python package
A vulnerable package is a package version that a published security advisory lists as affected. Posit Package Manager gets the advisories from the Open Source Vulnerabilities (OSV) database. It does not scan the code of packages. To fix the problem, update the package in your project to a fixed version. A fixed version is a version that the advisory does not list as affected.
This page shows how to remediate a vulnerable Python package with pip or uv. If your project is also on Posit Connect, follow the steps in Update content on Connect after the update.
For R packages, see Remediate a vulnerable R package.
Before you start
You need this information:
- The name of the package, for example
jinja2 - The version that your project uses, for example
3.0.3 - A fixed version, for example
3.1.6
If you do not have a fixed version, see Find a fixed version.
Then find the tool that installs the packages of your project. The steps on this page have a tab for each tool:
- If the project folder has a
uv.lockfile, select the uv tab. - If you install packages with
uv pip, select the pip tab. Useuv pipin place ofpython -m pip. - Otherwise, select the pip tab.
To see the version that your project uses, open a terminal in the project folder. Then run the command for your tool.
If the project has a virtual environment, activate it first. See step 1 in the pip tab of Update the package in your project. Then run this command:
Terminal
python -m pip show jinja2Run this command:
Terminal
uv pip show jinja2The Version line shows the version.
Update the package in your project
Complete the following steps in the environment where you work on the project. This can be Posit Workbench, Positron, VS Code, or a terminal on your computer.
Open a terminal in the project folder. Then find out whether the project has a virtual environment. A virtual environment is a folder that holds the packages of one project. Its name is often
.venvorvenv.If the project has a virtual environment, activate it. On macOS or Linux, run this command for a virtual environment in the
.venvfolder:Terminal
source .venv/bin/activateOn Windows, run this command in PowerShell:
PowerShell
.venv\Scripts\Activate.ps1In the Windows Command Prompt, run this command:
Command Prompt
.venv\Scripts\activate.batIf the folder has a different name, use that name in place of
.venv.If the project uses a conda environment, activate it with
conda activateand the name of the environment. This page does not cover packages that conda installs. If conda installed the package, update it with conda.If the project does not have a virtual environment,
python -m pipuses the Python that thepythoncommand starts. Make sure that this is the Python that runs the project. The output of this command shows the folder where that Python keeps its packages:Terminal
python -m pip --versionSet the fixed version in the
requirements.txtfile of the project. If the project does not have this file, go to step 3.If a tool made the file, do not edit the file. The first lines of the file name the tool, for example
pip-compile. These lines also show the command that made the file.If the source file, for example
requirements.in, has an old version of the package, change that line. Then run the command again, and add--upgrade-package jinja2. For example, for a file that showspip-compile --generate-hashes requirements.in, run this command:Terminal
pip-compile --generate-hashes --upgrade-package jinja2 requirements.inIf you wrote the file yourself, edit it:
- If the file has a line for the package, change the version on that line to the fixed version. Also change a line with no version or with a range, such as
jinja2orjinja2>=3.0. pip does not update an installed package when its version satisfies the line. - If the file does not have a line for the package, add a line. Without a line, pip keeps the old version.
Use one of these lines:
jinja2>=3.1.6installs the newest version that is 3.1.6 or later.jinja2==3.1.6installs exactly 3.1.6.
ImportantDo not run only
python -m pip install --upgrade jinja2in a project that has arequirements.txtfile. That command updates the package, but not the file. The nextpython -m pip install -r requirements.txtinstalls the old version again.- If the file has a line for the package, change the version on that line to the fixed version. Also change a line with no version or with a range, such as
If the project has a
requirements.txtfile, install the packages from the file:Terminal
python -m pip install -r requirements.txtIf the project does not have a
requirements.txtfile, install the fixed version directly:Terminal
python -m pip install "jinja2>=3.1.6"To install exactly 3.1.6, use this command instead:
Terminal
python -m pip install "jinja2==3.1.6"If the command shows
No module named pip, the virtual environment does not have pip. Useuv pipin place ofpython -m pip.If the command shows
externally-managed-environment, see pip shows anexternally-managed-environmenterror.Restart Python, the Jupyter kernel, or the app that uses the package. Then make sure that the project has the fixed version or a later version. The
Versionline of this command must show that version:Terminal
python -m pip show jinja2If you keep the project in Git, commit the changed
requirements.txtfile. Other people who use the project then pull the commit and run this command:Terminal
python -m pip install -r requirements.txtIf the project is also on Connect, follow the steps in Update content on Connect.
Open a terminal in the project folder.
Look for the package in the
dependencieslist ofpyproject.toml.If
pyproject.tomllists the package, set the fixed version there. This command updatespyproject.tomlanduv.lock, and installs the new version:Terminal
uv add "jinja2>=3.1.6"jinja2>=3.1.6installs the newest version that is 3.1.6 or later. To install exactly 3.1.6, use this command instead:Terminal
uv add "jinja2==3.1.6"Both commands stop a later update from installing the old version again.
If
pyproject.tomldoes not list the package, another package needs it. Update the vulnerable package with theuv lockcommand, then install it with theuv synccommand:Terminal
uv lock --upgrade-package jinja2 uv syncTo install one exact version, use these commands instead:
Terminal
uv lock --upgrade-package jinja2==3.1.6 uv syncRestart Python, the Jupyter kernel, or the app that uses the package. Then make sure that the project has the fixed version or a later version:
Terminal
uv pip show jinja2If the project also has a
requirements.txtfile, write the file again fromuv.lock. If you made the file withuv exportbefore, run the same command again. If not, use this command:Terminal
uv export --format requirements-txt --no-hashes --no-dev --no-emit-project -o requirements.txtIf you keep the project in Git, commit the changed
pyproject.toml,uv.lock, andrequirements.txtfiles. Other people who use the project then pull the commit and run this command:Terminal
uv syncIf the project is also on Connect, follow the steps in Update content on Connect.
Update content on Connect
Connect runs the package versions that you published. Connect does not update them. To fix content on Connect, update the source project and publish it again. For all the ways to publish, see Publishing with Connect.
To publish the content again, you must be the owner of the content or a collaborator on it. If you are a viewer of the content, send these steps to the owner of the content. The content list in Connect shows the owner of each content item.
Find the source project of the content. This is the folder that you published from. For Git-backed content, it is the Git repository of the content.
Update the package in the source project. Do the steps in Update the package in your project, in the tab for your tool.
If the project has a
requirements.txtfile, the publishing tools use it. Make sure that the file shows the fixed version. An oldrequirements.txtfile next to a newuv.lockfile deploys the old version.Publish the content again to the same location on Connect. Use the method that you used before:
Publish in Positron or VS Code: publish again, and select the same content.
rsconnect-python: run the same
rsconnect deploycommand as before.Git-backed content: run the same
rsconnect write-manifestcommand as before, with the--overwriteoption. Then commitmanifest.jsonand the changed dependency files, and push the commit.Connect deploys the new commit at its next check. To deploy the commit immediately, see Updating content.
In Connect, open the content settings and select the Source tab. Make sure that the Python Packages section shows the fixed version or a later version. The Python environment restore log of the active bundle also shows the installed packages.
If Connect still shows the old version after you publish, an administrator can manage the packages of this content on the Connect server. Send the content name, the package name, and the fixed version to your Connect administrator.
Find a fixed version
A fixed version is usually the first version with the fix, or a later version.
In Package Manager, search for the package and open its page.
Open the Other Versions tab. A version that a known vulnerability affects shows a vulnerability count badge. If you do not see your version, click Get more releases.
Select a version that is newer than your version and that no known vulnerability affects. Do not select a version with
a,b,rc, ordevin its number. These are pre-release versions.
If your version has a known vulnerability but no badge, Package Manager does not have the data for this vulnerability. The lack of a badge on other versions does not guarantee that no vulnerability affects them. Read the advisory.
An advisory is the public report of the problem. The OSV database is one source of advisories. Search osv.dev for the package name or the advisory ID. Then open the advisory for PyPI. It lists the affected versions and the version that has the fix.
Sometimes there is no clean fix:
- No version has the fix. All versions have the problem.
- The fix is only in a new major version. A new major version can change how the package works, and your code can stop working.
- The fix is only in a pre-release version. A pre-release version is a test version before the official release.
In each of these cases, ask your security team or your administrator what to do.
Troubleshooting
The update keeps the old version or cannot find the fixed version
Each tool shows a different result:
- pip shows
ERROR: No matching distribution found. uv addshows that the requirementsare unsatisfiable.uv lock --upgrade-packagekeeps the old version and shows no error.
Your repository URL can have a snapshot date that is before the fix. A repository URL with a date gives only the packages that were available on that date.
A date setting has the same result. uv has the exclude-newer setting, and pip 26.0 and later has the uploaded-prior-to setting.
For example, https://packagemanager.example.com/pypi/2024-12-01/simple is a URL with a date. Look for a URL with a date or for a date setting in these files that you own:
- The
--index-urlline inrequirements.txt - The
[[tool.uv.index]]table or theexclude-newersetting inpyproject.toml - Your uv configuration file
~/.config/uv/uv.toml - Your pip configuration, which you set with
pip config set, for exampleglobal.index-urlorglobal.uploaded-prior-to
To see which file sets each pip value, run this command:
Terminal
python -m pip config debugThen do one of these steps:
- If the URL or the date setting is in a file that you own, change the date to a later date, or change the URL to
latest. Then update the package again. See Obtaining a repository URL and Restricting packages by release date. - If the URL or the date setting is not in a file that you own, an administrator set it for the server, for example in
/etc/uv/uv.tomlor/etc/pip.conf. Ask that administrator for help. The date can be a rule of your organization.
The repository does not have the fixed version
Your Package Manager administrator can block a package version, or limit the packages in a repository. Ask your Package Manager administrator for help.
pip shows an externally-managed-environment error
If you install a package in the Python of your operating system without a virtual environment, pip shows error: externally-managed-environment. Your operating system manages the packages of that Python.
Make a virtual environment for the project in the project folder, and activate it. On macOS or Linux, run these commands:
Terminal
python3 -m venv .venv
source .venv/bin/activateOn Windows, see step 1 in the pip tab of Update the package in your project for the activate command.
Then install all the packages of the project in the virtual environment. If the project has a requirements.txt file, run this command:
Terminal
python -m pip install -r requirements.txtThen do the steps in the pip tab of Update the package in your project again.
Do not use the --break-system-packages option. It can stop programs of the operating system from working.
Another package needs the old version
Another package of your project can need the old version. Each tool shows a different result:
python -m pip install -r requirements.txtanduv addstop with an error that names that package.python -m pip install "jinja2>=3.1.6"installs the new version, but showsERROR: pip's dependency resolver does not currently take into account all the packages that are installed. The next lines name the package that needs the old version. That package can stop working.uv lock --upgrade-package jinja2keeps the old version with no error. To see the error, give the fixed version:Terminal
uv lock --upgrade-package jinja2==3.1.6
Update the package that the error names too, then update the vulnerable package again. If the error continues, ask your administrator for help.
Publishing fails because Connect cannot find the fixed version
Connect can use its own repository URL. That URL can have a snapshot date that is before the fix. Send the package name, the fixed version, and the error message to your Connect administrator.