Skip to content

Add path traversal validation in error.py following notion-sdk-js#312

Merged
ramnes merged 3 commits intoramnes:mainfrom
tsinglinrain:feat/add-path-validation-error
Feb 2, 2026
Merged

Add path traversal validation in error.py following notion-sdk-js#312
ramnes merged 3 commits intoramnes:mainfrom
tsinglinrain:feat/add-path-validation-error

Conversation

@tsinglinrain
Copy link
Contributor

Summary

  • Add InvalidPathParameterError class for path traversal validation errors
  • Add validate_request_path() function to detect path traversal sequences
  • Add ClientErrorCode.InvalidPathParameter enum value
  • Add comprehensive tests with 100% coverage on errors.py

This PR follows the JavaScript SDK's PR #661 to add path traversal prevention.
Related Issue #283

Differences from JS SDK

The Python implementation has two intentional differences from the JS version:

1. Simplified URL-encoded detection

# JS version
if (/%2e/i.test(path)) { ... }
# Python version
if "%2e" in path.lower():

Using in with str.lower() is more Pythonic than using regex for simple substring matching. So that we do not need to import re and it is more straightforward and easier to read. The reason for using a regular expression in JavaScript is that String.prototype.includes() does not support a case-insensitive option.

2. Removed try-except block

// JS version - needs try-catch because decodeURIComponent throws on invalid encoding
  try {
    decoded = decodeURIComponent(path)
  } catch {
    return
  }
# Python version - unquote() never throws, it preserves invalid sequences
decoded = unquote(path)

Python's urllib.parse.unquote() handles invalid percent-encoding gracefully by preserving the original characters, unlike JavaScript's decodeURIComponent() which throws URIError. The try-except block is unnecessary in Python. Furthermore, it makes it difficult to achieve 100% coverage.

- Implemented `validate_request_path` to prevent path traversal attacks
…date_request_path` function

- Simplified the logic around `decoded = unquote(path)`
@codecov
Copy link

codecov bot commented Feb 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (b9d448d) to head (ed34105).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #312   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            7         7           
  Lines          480       496   +16     
=========================================
+ Hits           480       496   +16     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ramnes ramnes merged commit bde85bf into ramnes:main Feb 2, 2026
9 checks passed
@ramnes
Copy link
Owner

ramnes commented Feb 2, 2026

Great, thanks!

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.

2 participants