Skip to content

spring-projects/security-advisories

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 

Repository files navigation

Spring Security Policy

As documented at https://spring.io/security-policy, this repository is used to report security advisories to any Spring Project.

Before creating a report, please read through this entire document. In particular, read What is a Valid CVE? before filing a report to confirm your issue qualifies.

What is a Valid CVE?

A valid CVE is a security vulnerability directly caused by Spring’s own code, where Spring itself allows untrusted input to be processed in an insecure way. Issues stemming from developer misuse, vulnerabilities in Spring’s dependencies, or transitive dependency versions do not qualify. The sections below provide concrete examples of both qualifying and non-qualifying issues.

Examples of Vulnerabilities

Real, accepted Spring security advisories are published at https://spring.io/security/. These serve as examples of valid CVEs; we link there rather than duplicate the content here.

Examples of Non-Vulnerabilities

Insecure Application Code

The following controller is a CVE in the application, not in Spring.

@RestController
class HasCveCommandController {

    /**
     * CVE: passes the untrusted {@code command} HTTP parameter directly to
     * {@link ProcessBuilder}, allowing an attacker to execute arbitrary commands
     * on the server. This is a vulnerability in the application, not in Spring.
     */
    @GetMapping("/cve")
    String cve(@RequestParam String command) throws Exception {
        Process process = new ProcessBuilder(command).start();
        return new String(process.getInputStream().readAllBytes());
    }

}

Spring’s role is to route the HTTP request and bind parameters — it has no knowledge of, or responsibility for, what the developer does with those values. The developer is responsible for validating or sanitizing untrusted input before passing it to any sensitive API such as ProcessBuilder, Runtime.exec, or similar. If such a controller is exploited to execute arbitrary commands, the CVE belongs to the application, not to Spring MVC.

Unsafe Deserialization

The Spring team’s stance is that, in order for deserialization to be considered a vulnerability in Spring, Spring must pass data from an untrusted source (that is, HTTP parameters) into a method that performs deserialization in a way that produces a CVE. The reason for this stance is that deserialization of arbitrary types is necessary but cannot be made secure.

Spring provides necessary tools for developers, but it is the responsibility of the developer to use them securely. This is no different from any other library or the JDK itself. If a developer passes untrusted data from an HTTP request to ProcessBuilder, then it is not a CVE in the JDK but in the application that used ProcessBuilder incorrectly. If a developer uses untrusted data to create an SQL query by using String concatenation, it is not a CVE in the SQL driver but in the application for not using prepared SQL statements. Similarly, if a developer passes untrusted data into a deserialization method, it is the developer who needs to ensure it is safe to do so.

Vulnerabilities in Dependencies

Vulnerabilities in Spring’s dependencies should be reported to the respective project and not to the Spring team.

Vulnerable Dependency Versions

The Spring team does its best to keep its dependencies up to date regardless of whether a dependency contains a vulnerability. However, we do not consider it a vulnerability in Spring when Spring defines a vulnerable dependency version, because developers can override these versions and because releasing for any transitive dependency would become unmanageable for the Spring portfolio.

It is up to the developer of the dependency to release a compatible version with the security fix. If this is made available, the Spring project will be updated to that dependency version prior to releasing the next version of the Spring project.

Typically, there is no special release for updating dependency versions. Instead, the Spring team encourages developers to override the version until the next Spring release.

Unsupported Versions

Reports about issues in Spring project versions that have reached end of life are not considered valid CVEs. You can find the supported versions on spring.io. For example, Spring Boot’s supported versions can be found at https://spring.io/projects/spring-boot#support.

Creating a Sample

Before creating an advisory, you must create a minimal sample, which will be shared using a temporary private fork, that demonstrates the vulnerability. The sample must be a complete, self-contained application that demonstrates the vulnerability.

A Minimal Sample

A minimal sample is somewhat subjective, but the best approach is to start by writing down the steps to reproduce the vulnerability. Then, remove any dependencies, code, or external services that are not used when reproducing the vulnerability. Unless specifically required to reproduce the issue, the sample application should be written in Java. Even if Spring Boot is not required, samples should use it to simplify the application setup and configuration.

Supported Versions

The sample must use the latest patch version of a supported generation. You can find the supported versions on spring.io. For example, Spring Boot’s supported versions can be found at https://spring.io/projects/spring-boot#support.

Application Specific Code

Application-specific code is expected, but it should only exist if it is necessary to reproduce the issue. Additionally, it cannot be the source of the vulnerability.

Review any application-specific code and determine if it is the source of the vulnerability. Is the application code following best practices? Should the application code be doing what it is doing?

External Services

Unless specifically required, external services (e.g. a database, message broker, or other service) should not be required to run the sample. When possible and required, external services should be automatically started using Spring Boot’s Development-time Services.

Using a Realistic Environment

When writing the steps to reproduce the exploit, ensure that the steps are described in a realistic environment. For example, CSRF occurs in a browser and thus the steps to reproduce the exploit should be explained through a browser. This means that providing a shell script to demonstrate the exploit is invalid in this scenario because it can do things that will not happen in a browser and CSRF attacks are a browser specific attack.

Creating a Report

Reports must be both concise (minimal) and precise (contain all necessary information). If they do not meet these requirements, you will be asked to fix the report before we proceed with triaging the issue.

Before you create a report:

Please copy the template below and paste it into the description of a new draft security advisory. Please be as concise as possible while still providing all necessary information. If the report is too long, you will be asked to fix it before we proceed with triaging the issue.

### Summary of the CVE

<!--
1–3 sentence summary of the CVE
-->

### Advisory Checklist

Ensure that you have completed ([and marked as complete](https://www.markdownguide.org/extended-syntax/#task-lists)) all of the following requirements:

* [ ] The report includes a 1–3 sentence Summary of the CVE
* [ ] The report includes a sample following the [Creating a Sample](https://github.com/spring-projects/security-advisories?tab=readme-ov-file#creating-sample) guidelines.
  * [ ] The sample is [minimal](https://github.com/spring-projects/security-advisories?tab=readme-ov-file#creating-sample-minimal), is written in Java (unless the issue is specific to Kotlin), and does not have any unnecessary dependencies or complexity
  * [ ] The sample uses the [latest patch version of a supported generation](https://github.com/spring-projects/security-advisories?tab=readme-ov-file#creating-sample-supported-versions)
  * [ ] The sample demonstrates a vulnerability in the Spring Project and not the [application code](https://github.com/spring-projects/security-advisories?tab=readme-ov-file#creating-sample-application-code)
  * [ ] The sample has been [shared on the sample branch](https://github.com/spring-projects/security-advisories?tab=readme-ov-file#collaboration-sample).
* [ ] Instructions on how to run the sample
* [ ] Instructions on how to reproduce the issue
* [ ] The expected result
* [ ] The actual result and explain why it is a vulnerability

### Instructions on running the minimal sample

<!--
Provide instructions on how to run the minimal sample.

Use the instructions to review the sample and ensure that it is a [minimal sample](https://github.com/spring-projects/security-advisories?tab=readme-ov-file#creating-sample-minimal).
-->

### Instructions on reproducing the issue

<!--
Use these instructions to figure out if your sample is a minimal sample.
Try removing code and dependencies that are not used when following these instructions.

Do the instructions use application-specific code?
If so, double check that the application code is not the source of the vulnerability.
-->

### Describe the expected result

<!--
Provide a brief description of the expected behavior.

For example, when a path containing `../` is provided, it should be rejected with a 400 Bad Request response to prevent directory traversal attacks.
-->

### Describe the actual result and explain why it is a vulnerability

<!--
Provide a brief description of the actual behavior.

For example, when a path containing `../` is provided, it is resolved to a directory on the filesystem that should not be accessible.
-->

Collaborating with Code

Collaboration should use a temporary private fork of this repository.

This section outlines how to collaborate on a security advisory and is divided into the following subsections. Each subsection describes the goal to achieve and provides example scripts as one way to accomplish it — you are free to use any approach that achieves the same result.

Warning

The scripts are examples that need to be changed to reflect your environment.

If you want to update the instructions throughout this documentation, you can update the corresponding AsciiDoc document attribute (:name: value) at the top of this README and re-render the README to see the changes.

  • A Hypothetical CVE Report — introduces the hypothetical CVE used as a running example throughout this section

  • Clone Temporary Private Fork — clone the temporary private fork locally so subsequent steps can work against it

  • Sharing the Sample — push a minimal reproducer to an orphan branch on the private fork so the team can review it

  • Using the Sample — check out the reporter’s sample locally to run and reproduce the issue

  • Producing a Fix — commit a fix and share it on the private fork for team review

A Hypothetical CVE Report

Throughout this documentation, we will use an example report related to a hypothetical CVE in Spring Framework related to path validation. For the example report we will assume that the CVE is in https://github.com/spring-projects/spring-framework on branch 7.0.x.

Clone Temporary Private Fork

The goal of this step is to clone the temporary private fork locally so subsequent steps can work against it.

The example script below clones a temporary private fork, but you are free to clone it any way you want. Before cloning, you will need to ensure that the temporary private fork [has been created](https://docs.github.com/en/code-security/tutorials/fix-reported-vulnerabilities/collaborate-in-a-fork#creating-a-temporary-private-fork).

# -o uses a uniquely named remote (instead of origin) to avoid accidentally pushing to the wrong repository.
git clone \
  -o ghsa-path-validation \
  git@github.com:spring-projects/security-advisories-ghsa-CHANGE-ME.git \
  ~/code/ghsa-path-validation
cd $_

Sharing the Sample

Before you report a security advisory, you should already have a minimal reproducer (a sample). As the reporter, the goal is to push your sample to an orphan branch named sample on the private temporary fork so the team can review it without publishing to the public repository or a public issue.

The following example scripts show one way to achieve that goal:

Review each block before you run it and align the defaults in A Hypothetical CVE Report with your environment.

Creating the Sample Branch

The goal is to create an orphan branch named sample on the private temporary fork clone.

Clone Temporary Private Fork must be completed first so the clone of the private temporary fork exists. The example script below creates the branch and adds an empty initial commit so the ref exists for subsequent steps.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
# git switch requires Git 2.23+ (--orphan removes tracked files from the working tree).
git switch --orphan sample
# Empty commit so refs/heads/sample exists (otherwise checkout/switch sample fails later or in a new shell).
git commit --allow-empty -m "Start sample branch"

Committing the Sample Branch

The goal is to have the sample committed on branch sample. The example script below copies the sample directory and commits it.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
# rsync copies the sample without bringing over `.git` (or any nested `.git` directories).
rsync -a --exclude=.git ~/code/sample-cve/ .
git add -A
git commit -m "Add sample"

Pushing the Sample Branch

The goal is to have branch sample pushed to the advisory remote so reviewers can access it. The example script below pushes the branch and prints the GitHub URL.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
git push -u ghsa-path-validation sample

Using the Sample

As a team member, the goal is to have the reporter’s sample checked out locally so you can run and reproduce the issue. You need access to the private temporary fork (for example as a collaborator on the draft advisory).

The example script below is one way to achieve that: it switches to branch sample in the fork clone. Clone Temporary Private Fork must be completed first so the clone exists.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
git switch sample

Producing a Fix

The goal of this section is to produce a fix and share it on the private temporary fork for review.

The following example scripts show one way to achieve that goal:

Review each block before you run it and align the defaults in A Hypothetical CVE Report with your environment.

Adding the Remote and Branch

The goal is to have a local branch tracking the affected branch (e.g. 7.0.x) of the public repository (e.g. spring-projects/spring-framework) so you can apply a fix. The example script below adds the public repository as a remote and creates a local branch from it.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
# HTTPS URL and a dedicated remote alias reduce the chance of pushing to the wrong GitHub repository.
git remote add spring-framework https://github.com/spring-projects/spring-framework.git
git fetch spring-framework
git switch -c 7.0.x spring-framework/7.0.x

Committing the Fix

The goal is to have a fix committed on the branch (e.g. 7.0.x). Edit the codebase, run tests or the reporter’s reproducer to verify, then stage and commit — the example script below shows the commit step.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
# Edit sources as needed, then stage and commit.
git add -A
git commit -m "Fix CVE"

Pushing the Fix

The goal is to have the fix branch pushed to the advisory remote so the team can review it on the private fork. The example script below pushes the branch and prints the GitHub URL.

# Ensure in the clone directory
cd ~/code/ghsa-path-validation
git push -u ghsa-path-validation 7.0.x

Notifying the Reporter

After Pushing the Fix, notify the reporter and provide instructions on how to review the fix. If possible, you should consider updating the sample branch to demonstrate the fix. For example, you might update the sample branch to:

  • Align the version of the vulnerable dependency with the fix

  • If necessary, add a local Maven repository URL (e.g. Maven Local)

  • Provide the user with instructions on how to publish the fix locally (e.g. run ./mvn install) on the fix branch (e.g. 7.0.x) of the private fork

Contributors