Skip to content

[MINOR] Reject traversal segments in note and folder paths#5248

Merged
jongyoul merged 1 commit into
apache:branch-0.12from
jongyoul:backport-5227-PR-0.12
May 14, 2026
Merged

[MINOR] Reject traversal segments in note and folder paths#5248
jongyoul merged 1 commit into
apache:branch-0.12from
jongyoul:backport-5227-PR-0.12

Conversation

@jongyoul
Copy link
Copy Markdown
Member

What is this PR for?
This is a backport of PR #5227 to branch-0.12. It adds path traversal protection by rejecting traversal segments in note and folder paths. Due to module structure differences between master and branch-0.12, the files were moved from zeppelin-server to zeppelin-zengine.

What type of PR is it?
Improvement

Todos

  • - Backport logic from master to branch-0.12
  • - Adjust file locations for branch-0.12 module structure

What is the Jira issue?

How should this be tested?

  • Verified with mvn test -pl zeppelin-zengine -Dtest=NotebookRepoPathValidationTest on branch-0.12. All 27 tests passed.

`NotebookRepo.buildNoteFileName` composes a filesystem path or object-store key from a user-supplied note path. The previous implementation required only a leading `/` but otherwise concatenated the value verbatim, so a value such as `/../etc/foo` would compose to a location outside the configured notebook root for backends that perform a raw filesystem operation (`FileSystemNotebookRepo`) or build an object key directly from the string (S3 / Azure / GCS).

This PR centralises a small validation helper at the `NotebookRepo` interface level so every backend gets the same defence, fixes one folder-level path that bypassed `buildNoteFileName`, and adds the missing `normalizeNotePath` call in `NotebookService.renameNote`.

Improvement

* [x] Add `NotebookRepo.rejectTraversalSegments` (URL-decoded, recursive, capped at 5 layers).
* [x] Call `rejectTraversalSegments` from the default `buildNoteFileName`, so every implementation is covered.
* [x] Apply it to `FileSystemNotebookRepo`'s folder-level `move` / `remove`, which build the path without going through `buildNoteFileName`.
* [x] Add the missing `normalizeNotePath` in `NotebookService.renameNote` to match `createNote`, `cloneNote`, and `moveFolder`.
* [x] `NotebookRepoPathValidationTest` (27): `..`, `.`, URL-encoded variants (`%2e%2e`, `%2E%2E`), double-encoded variants, and an excessive-encoding-layer payload. Realistic note names including Korean characters and `...` inside a segment are accepted.

N/A — `[MINOR]` change.

```
./mvnw install -pl zeppelin-server -am -DskipTests
./mvnw test -pl zeppelin-server -Dtest='NotebookRepoPathValidationTest,NotebookServiceTest' -DfailIfNoTests=false
./mvnw test -pl zeppelin-plugins/notebookrepo/filesystem
```

All test sets pass locally.

* Does the license files need to update? No
* Is there breaking changes for older versions? No — existing valid note paths render to byte-identical filenames; only paths containing literal traversal segments now produce a clear `IOException` instead of silently composing to an out-of-root location.
* Does this needs documentation? No

Closes apache#5227 from jongyoul/ZEPPELIN-fs-notebook-path.

Signed-off-by: Jongyoul Lee <jongyoul@gmail.com>
Copilot AI review requested due to automatic review settings May 14, 2026 05:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Backport of PR #5227 to branch-0.12, adding path traversal protection for note and folder paths. Due to module differences in 0.12, the validator and tests live in zeppelin-zengine instead of zeppelin-server.

Changes:

  • Introduces NotebookPathValidator with rejectTraversalSegments and decodeRepeatedly (URL-decoded, capped at 5 layers).
  • Wires the validator into NotebookRepo.buildNoteFileName, FileSystemNotebookRepo folder-level move/remove, and NotebookService.renameNote (which now also calls normalizeNotePath).
  • Adds NotebookRepoPathValidationTest covering traversal, URL-encoded, and excessive-encoding payloads as well as accepted realistic names.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookPathValidator.java New shared validator with traversal-segment rejection and bounded repeated URL decoding.
zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookRepo.java Calls validator from default buildNoteFileName so all backends are covered.
zeppelin-plugins/notebookrepo/filesystem/src/main/java/org/apache/zeppelin/notebook/repo/FileSystemNotebookRepo.java Validates folder paths in move/remove that don't go through buildNoteFileName.
zeppelin-server/src/main/java/org/apache/zeppelin/service/NotebookService.java Replaces local decodeRepeatedly with shared validator and adds missing normalizeNotePath in renameNote.
zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoPathValidationTest.java New tests for traversal rejection, encoded variants, and accepted paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Member

@ParkGyeongTae ParkGyeongTae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the backport to branch-0.12.

The validation is placed at the right level so notebook repo implementations get consistent protection, and the extra checks for filesystem folder move / remove paths cover the bypass cases. The test coverage for raw, encoded, double-encoded traversal segments and valid note names looks good to me.

@jongyoul jongyoul merged commit ba05113 into apache:branch-0.12 May 14, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants