Complete security item 3 hardening and redaction sweep

This commit is contained in:
thePR0M3TH3AN committed 2026-02-25 18:23:40 -05:00
1 parent fcbe2b2943
commit 56b68bd0ac
11 files changed
+201 -55

No files matched your search

+72
View File
@@ -284,6 +284,78 @@ async def test_vault_import_via_upload(client, tmp_path):
assert called.get("sync") is True
@pytest.mark.anyio
async def test_vault_import_upload_sets_secure_temp_permissions(client, monkeypatch):
cl, token = client
called = {}
chmod_calls = []
unlink_calls = []
def import_db(path):
called["path"] = path
api.app.state.pm.handle_import_database = import_db
api.app.state.pm.sync_vault = lambda: called.setdefault("sync", True)
real_chmod = api.os.chmod
real_unlink = api.os.unlink
def tracking_chmod(path, mode):
chmod_calls.append((Path(path), mode))
return real_chmod(path, mode)
def tracking_unlink(path):
unlink_calls.append(Path(path))
return real_unlink(path)
monkeypatch.setattr(api.os, "chmod", tracking_chmod)
monkeypatch.setattr(api.os, "unlink", tracking_unlink)
headers = {"Authorization": f"Bearer {token}"}
res = await cl.post(
"/api/v1/vault/import",
files={"file": ("c.json.enc", b"{}")},
headers=headers,
)
assert res.status_code == 200
assert res.json() == {"status": "ok"}
tmp_path_used = called["path"]
assert any(path == tmp_path_used and mode == 0o600 for path, mode in chmod_calls)
assert tmp_path_used in unlink_calls
@pytest.mark.anyio
async def test_vault_import_upload_temp_file_removed_on_failure(client, monkeypatch):
cl, token = client
called = {}
unlink_calls = []
def import_db(path):
called["path"] = path
raise ValueError("boom")
api.app.state.pm.handle_import_database = import_db
api.app.state.pm.sync_vault = lambda: called.setdefault("sync", True)
real_unlink = api.os.unlink
def tracking_unlink(path):
unlink_calls.append(Path(path))
return real_unlink(path)
monkeypatch.setattr(api.os, "unlink", tracking_unlink)
headers = {"Authorization": f"Bearer {token}"}
with pytest.raises(ValueError):
await cl.post(
"/api/v1/vault/import",
files={"file": ("c.json.enc", b"{}")},
headers=headers,
)
assert called["path"] in unlink_calls
assert not called.get("sync", False)
@pytest.mark.anyio
async def test_vault_import_upload_too_large(client):
cl, token = client
+14
View File
@@ -1,3 +1,5 @@
import logging
from local_bip85.bip85 import BIP85
@@ -50,3 +52,15 @@ def test_default_word_count_from_entropy_bytes():
bip85.derive_entropy(index=5, entropy_bytes=20, app_no=39)
assert ctx.last_path == "m/83696968'/39'/0'/20'/5'"
def test_derive_entropy_logs_do_not_expose_key_material(caplog):
bip85 = BIP85(b"\x00" * 64)
ctx = DummyCtx()
bip85.bip32_ctx = ctx
sensitive_hex = "00" * 32
with caplog.at_level(logging.DEBUG):
bip85.derive_entropy(index=0, entropy_bytes=16, app_no=39, word_count=12)
assert sensitive_hex not in caplog.text
+8
View File
@@ -1,4 +1,5 @@
import hashlib
import logging
import sys
from pathlib import Path
from tempfile import TemporaryDirectory
@@ -23,6 +24,13 @@ def test_generate_fingerprint_deterministic():
assert fp1 == fp2
def test_generate_fingerprint_does_not_log_seed_phrase(caplog):
seed = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
with caplog.at_level(logging.DEBUG):
generate_fingerprint(seed)
assert seed not in caplog.text
def test_encryption_round_trip():
with TemporaryDirectory() as tmpdir:
key = base64.urlsafe_b64encode(os.urandom(32))