mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-04 11:52:03 +00:00
Fix arbitrary file write via path traversal in backup_parent_seed
The `backup_parent_seed` API endpoint was vulnerable to arbitrary file write via path traversal. The `path` parameter was used directly to create a `Path` object, which was then passed to `_pm.handle_backup_reveal_parent_seed`. This allowed an attacker to specify an arbitrary path (e.g., `../../evil_file`), which would be used by `encrypt_and_save_file` to write the encrypted seed to that location. This commit fixes the vulnerability by validating that the `path` parameter is a valid filename (i.e., does not contain path separators or parent directory references) before processing it. This ensures that the backup file is always created within the intended fingerprint directory. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
335de7abe3
commit
91f39007f0
2 files changed
+50
No files matched your search
@@ -567,6 +567,9 @@ def backup_parent_seed(
|
||||
if data is not None:
|
||||
p = data.get("path")
|
||||
if p:
|
||||
# Prevent directory traversal
|
||||
if "/" in p or "\\" in p or ".." in p:
|
||||
raise HTTPException(status_code=400, detail="Invalid filename")
|
||||
path = Path(p)
|
||||
_pm.handle_backup_reveal_parent_seed(path)
|
||||
return {"status": "ok"}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import sys
|
||||
import os
|
||||
from unittest.mock import MagicMock
|
||||
from fastapi.testclient import TestClient
|
||||
from pathlib import Path
|
||||
|
||||
# Add src to sys.path
|
||||
sys.path.insert(0, os.path.abspath("src"))
|
||||
|
||||
# Mock seedpass.api._pm before importing api
|
||||
import seedpass.api
|
||||
seedpass.api._pm = MagicMock()
|
||||
# No need to mock is_valid_filename now as I check inline
|
||||
seedpass.api._token = "testtoken" # Set a dummy token
|
||||
|
||||
from seedpass.api import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
def test_fix():
|
||||
evil_path = "/tmp/evil_file"
|
||||
response = client.post(
|
||||
"/api/v1/vault/backup-parent-seed",
|
||||
json={"path": evil_path},
|
||||
headers={"Authorization": "Bearer testtoken"}
|
||||
)
|
||||
|
||||
assert response.status_code == 400, f"Expected 400, got {response.status_code}"
|
||||
assert response.json() == {"detail": "Invalid filename"}
|
||||
|
||||
# Check that handle_backup_reveal_parent_seed was NOT called
|
||||
seedpass.api._pm.handle_backup_reveal_parent_seed.assert_not_called()
|
||||
print("Fix verified: Rejected arbitrary path.")
|
||||
|
||||
# Test valid filename
|
||||
valid_file = "backup.enc"
|
||||
response = client.post(
|
||||
"/api/v1/vault/backup-parent-seed",
|
||||
json={"path": valid_file},
|
||||
headers={"Authorization": "Bearer testtoken"}
|
||||
)
|
||||
assert response.status_code == 200, f"Expected 200, got {response.status_code}"
|
||||
seedpass.api._pm.handle_backup_reveal_parent_seed.assert_called_with(Path(valid_file))
|
||||
print("Fix verified: Accepted valid filename.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_fix()
|
||||
Reference in new issue
Block a user