Remediate a vulnerable R 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 R package with renv, pak, or base R. If your project is also on Posit Connect, follow the steps in Update content on Connect after the update.

For Python packages, see Remediate a vulnerable Python package.

Before you start

You need this information:

  • The name of the package, for example jsonlite
  • The version that your project uses
  • A fixed version

If you do not have a fixed version, see Find a fixed version.

To see the version that your project uses, run this command in the R console of the project:

R
packageVersion("jsonlite")

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 renv.lock file, select the renv tab.
  • If you install packages with pak::pkg_install(), select the pak tab.
  • In all other cases, select the install.packages() tab.

Update the package in your project

Complete the following steps in the environment where you work on the project. This can be Posit Workbench, RStudio, Positron, or R on your computer.

  1. Open the project. If R starts in the project folder, renv also starts.

  2. In the R console, update the package. Then write the new version to renv.lock:

    R
    renv::update("jsonlite")
    renv::snapshot()

    renv::update() installs the newest version that your repository has. This can be a new major version. To install one exact version, use these commands instead:

    R
    renv::install("jsonlite@1.8.9")
    renv::snapshot()
  3. Restart R. Then make sure that the project has the fixed version or a later version:

    R
    packageVersion("jsonlite")

    In renv.lock, the Version of the package must show the same version.

  4. If you keep the project in Git, commit the changed renv.lock file. Other people who use the project then pull the commit and run this command:

    R
    renv::restore()
  5. If the project is also on Connect, follow the steps in Update content on Connect.

  1. Open R in the project.

  2. In the R console, update the package:

    R
    pak::pkg_install("jsonlite")

    This command installs the newest version that your repository has. This can be a new major version. To install one exact version, use this command instead:

    R
    pak::pkg_install("jsonlite@1.8.9")

    pak can install an exact older version from source code. If R then shows a compiler error, install the build tools for your system, or ask your administrator for help.

  3. Restart R. Then make sure that the project has the fixed version or a later version:

    R
    packageVersion("jsonlite")
  4. If the project is also on Connect, follow the steps in Update content on Connect.

  1. Open R in the project.

  2. In the R console, update the package:

    R
    install.packages("jsonlite")

    This command installs the newest version that your repository has. This can be a new major version. Base R cannot install one exact older version. To install one exact version, use the remotes package:

    R
    install.packages("remotes")
    remotes::install_version("jsonlite", "1.8.9")

    remotes can install an exact older version from source code. If R shows compilation failed, R gives only a warning and keeps the old version. Install the build tools for your system, or ask your administrator for help.

  3. Restart R. Then make sure that the project has the fixed version or a later version:

    R
    packageVersion("jsonlite")
  4. If the project is also on Connect, follow the steps in Update content on Connect.

If R shows a warning that a library is not writable, see R shows a warning that a library is not writable.

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.

  1. 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.

  2. Update the package in the source project. Do the steps in Update the package in your project, in the tab for your tool.

  3. If the project has a renv.lock file, open it. The Version of the package must show the fixed version or a later version.

  4. Publish the content again to the same location on Connect. Use the method that you used before:

    • Publish in RStudio or Positron: publish again, and select the same content.

    • rsconnect: run the same deploy command as before, for example rsconnect::deployApp().

    • Git-backed content: in the project folder, write a new manifest.json file with this command:

      R
      rsconnect::writeManifest()

      If R shows there is no package called 'rsconnect', install the package, then run rsconnect::writeManifest() again:

      R
      install.packages("rsconnect")

      Then commit manifest.json and any changed renv.lock file, and push the commit.

      Connect deploys the new commit at its next check. To deploy the commit immediately, see Updating content.

  5. In Connect, open the content settings and select the Source tab. Make sure that the R Packages section shows the fixed version or a later version. The R snapshot 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.

  1. In Package Manager, search for the package and open its page.

  2. Look at the Overview tab. It shows the newest version of the package. If a known vulnerability affects the newest version, the tab shows a Security Vulnerabilities section.

  3. Open the Other Versions tab. It lists the older versions. A version that a known vulnerability affects shows a vulnerability count badge.

  4. Select a version that is newer than your version and that no known vulnerability affects.

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 CRAN. 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:

  • renv::update() shows All packages appear to be up-to-date.
  • renv::install() with an exact version shows failed to find source.
  • pak::pkg_install() keeps the old version, even when you give an exact version.
  • install.packages() installs the same old version again, or a newer version that still has the problem.
  • remotes::install_version() shows that the version is invalid.

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. To see the URL, run this command in the R console:

R
getOption("repos")

For example, https://packagemanager.example.com/cran/2024-01-02 and https://packagemanager.example.com/cran/__linux__/noble/2024-01-02 are URLs with a date. If the URL has a date, do one of these steps:

  • If the project uses renv, set the URL again in the R console. When the project starts, renv sets the URL from the Repositories field of renv.lock. Use a later date or latest in place of the date:

    R
    options(repos = c(CRAN = "https://packagemanager.example.com/cran/latest"))

    Then do the steps in the renv tab of Update the package in your project again. renv::snapshot() writes the new URL to renv.lock.

  • If the project does not use renv, and the URL is in a file that you own, change the date to a later date, or to latest. This file can be the .Rprofile file of the project, or your R startup file ~/.Rprofile. Then update the package again. See Obtaining a repository URL.

  • If the URL is not in a file that you own, an administrator set it for the server. 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.

The fixed version needs a newer version of R

R shows is not available for this version of R, or pak shows Needs R >= and a version number. Ask your administrator for a newer version of R, for example on Workbench and on Connect.

R shows a warning that a library is not writable

If you update a package in a shared library, R shows this warning:

'lib = "/usr/local/lib/R/site-library"' is not writable

R then asks Would you like to use a personal library instead?, and then asks to create the personal library. Answer yes to both questions. R installs the fixed version in your personal library.

Restart R, then run this command:

R
packageVersion("jsonlite")

If R still shows the old version, ask your administrator for help. On some servers, R loads the shared library first.

The old version stays in the shared library for other users. An administrator owns the shared library. Ask the administrator of your server, for example your Workbench administrator, to update the package there.

Another package needs the old version

Another package of your project can need the old version. R does not always stop the update in this case. pak and install.packages() can install the new version with no error and no warning.

To find such a package, update the vulnerable package and the other packages of the project in one pak command. For example, for a project that uses httr:

R
pak::pkg_install(c("jsonlite", "httr"))

If a package needs the old version, pak stops with an error that names that package. Update that package 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.

Back to top