Files
SeedPass/verify_fix.py
T
google-labs-jules[bot]andPR0M3TH3AN 91f39007f0 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]>
2026-02-16 17:17:44 +00:00

48 lines
1.5 KiB
Python

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()