chore: import upstream snapshot with attribution
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,466 @@
|
||||
"""
|
||||
Comprehensive tests for security/file_write_verifier.py
|
||||
|
||||
Tests cover:
|
||||
- _sanitize_sensitive_data function
|
||||
- write_file_verified function
|
||||
- write_json_verified function
|
||||
- FileWriteSecurityError exception
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestSanitizeSensitiveData:
|
||||
"""Tests for the _sanitize_sensitive_data function."""
|
||||
|
||||
def test_sanitizes_password_key(self):
|
||||
"""Test that password keys are redacted."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {"username": "admin", "password": "secret123"}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result["username"] == "admin"
|
||||
assert result["password"] == "[REDACTED]"
|
||||
|
||||
def test_sanitizes_api_key(self):
|
||||
"""Test that api_key is redacted."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {"api_key": "sk-123456", "name": "test"}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result["api_key"] == "[REDACTED]"
|
||||
assert result["name"] == "test"
|
||||
|
||||
def test_sanitizes_various_sensitive_keys(self):
|
||||
"""Test that all sensitive key variations are redacted."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {
|
||||
"apikey": "value1",
|
||||
"api-key": "value2",
|
||||
"secret": "value3",
|
||||
"secret_key": "value4",
|
||||
"token": "value5",
|
||||
"access_token": "value6",
|
||||
"refresh_token": "value7",
|
||||
"private_key": "value8",
|
||||
"credentials": "value9",
|
||||
"auth": "value10",
|
||||
"authorization": "value11",
|
||||
}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
for key in data:
|
||||
assert result[key] == "[REDACTED]"
|
||||
|
||||
def test_case_insensitive_matching(self):
|
||||
"""Test that matching is case insensitive."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {"PASSWORD": "secret", "Api_Key": "key123", "TOKEN": "tok"}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result["PASSWORD"] == "[REDACTED]"
|
||||
assert result["Api_Key"] == "[REDACTED]"
|
||||
assert result["TOKEN"] == "[REDACTED]"
|
||||
|
||||
def test_sanitizes_nested_dicts(self):
|
||||
"""Test that nested dictionaries are sanitized."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {
|
||||
"config": {
|
||||
"api_key": "secret",
|
||||
"settings": {"password": "hidden", "name": "test"},
|
||||
}
|
||||
}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result["config"]["api_key"] == "[REDACTED]"
|
||||
assert result["config"]["settings"]["password"] == "[REDACTED]"
|
||||
assert result["config"]["settings"]["name"] == "test"
|
||||
|
||||
def test_sanitizes_lists_of_dicts(self):
|
||||
"""Test that lists containing dicts are sanitized."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {
|
||||
"users": [
|
||||
{"name": "user1", "password": "pass1"},
|
||||
{"name": "user2", "password": "pass2"},
|
||||
]
|
||||
}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result["users"][0]["password"] == "[REDACTED]"
|
||||
assert result["users"][1]["password"] == "[REDACTED]"
|
||||
assert result["users"][0]["name"] == "user1"
|
||||
|
||||
def test_preserves_non_sensitive_data(self):
|
||||
"""Test that non-sensitive data is preserved."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {"name": "test", "value": 123, "flag": True, "items": [1, 2, 3]}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result == data
|
||||
|
||||
def test_handles_primitive_values(self):
|
||||
"""Test that primitive values pass through unchanged."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
assert _sanitize_sensitive_data("string") == "string"
|
||||
assert _sanitize_sensitive_data(123) == 123
|
||||
assert _sanitize_sensitive_data(True) is True
|
||||
assert _sanitize_sensitive_data(None) is None
|
||||
|
||||
def test_handles_list_of_primitives(self):
|
||||
"""Test that lists of primitives pass through."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = [1, 2, "test", True]
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result == data
|
||||
|
||||
def test_handles_non_string_keys(self):
|
||||
"""Test handling of non-string dictionary keys."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
_sanitize_sensitive_data,
|
||||
)
|
||||
|
||||
data = {1: "value1", "password": "secret"}
|
||||
result = _sanitize_sensitive_data(data)
|
||||
|
||||
assert result[1] == "value1"
|
||||
assert result["password"] == "[REDACTED]"
|
||||
|
||||
|
||||
class TestFileWriteSecurityError:
|
||||
"""Tests for the FileWriteSecurityError exception."""
|
||||
|
||||
def test_exception_can_be_raised(self):
|
||||
"""Test that the exception can be raised and caught."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
FileWriteSecurityError,
|
||||
)
|
||||
|
||||
with pytest.raises(FileWriteSecurityError) as exc_info:
|
||||
raise FileWriteSecurityError("Test error message")
|
||||
|
||||
assert "Test error message" in str(exc_info.value)
|
||||
|
||||
def test_exception_inherits_from_exception(self):
|
||||
"""Test that FileWriteSecurityError inherits from Exception."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
FileWriteSecurityError,
|
||||
)
|
||||
|
||||
assert issubclass(FileWriteSecurityError, Exception)
|
||||
|
||||
|
||||
class TestWriteFileVerified:
|
||||
"""Tests for the write_file_verified function."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_get_setting(self):
|
||||
"""Fixture to mock the get_setting_from_snapshot function."""
|
||||
with patch(
|
||||
"local_deep_research.config.search_config.get_setting_from_snapshot"
|
||||
) as mock:
|
||||
yield mock
|
||||
|
||||
def test_writes_file_when_setting_matches(self, tmp_path, mock_get_setting):
|
||||
"""Test that file is written when setting matches required value."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.txt"
|
||||
content = "test content"
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_file_verified(
|
||||
filepath, content, "test.setting", required_value=True
|
||||
)
|
||||
|
||||
assert filepath.exists()
|
||||
assert filepath.read_text() == content
|
||||
|
||||
def test_raises_error_when_setting_mismatch(
|
||||
self, tmp_path, mock_get_setting
|
||||
):
|
||||
"""Test that error is raised when setting doesn't match."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
FileWriteSecurityError,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.txt"
|
||||
mock_get_setting.return_value = False
|
||||
|
||||
with pytest.raises(FileWriteSecurityError) as exc_info:
|
||||
write_file_verified(
|
||||
filepath,
|
||||
"content",
|
||||
"test.setting",
|
||||
required_value=True,
|
||||
context="test operation",
|
||||
)
|
||||
|
||||
assert "test operation" in str(exc_info.value)
|
||||
assert "test.setting=True" in str(exc_info.value)
|
||||
|
||||
def test_raises_error_when_setting_not_found(
|
||||
self, tmp_path, mock_get_setting
|
||||
):
|
||||
"""Test that error is raised when setting doesn't exist."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
FileWriteSecurityError,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.txt"
|
||||
mock_get_setting.side_effect = KeyError("Setting not found")
|
||||
|
||||
with pytest.raises(FileWriteSecurityError):
|
||||
write_file_verified(filepath, "content", "nonexistent.setting")
|
||||
|
||||
def test_writes_binary_file(self, tmp_path, mock_get_setting):
|
||||
"""Test writing binary content."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.bin"
|
||||
content = b"\x00\x01\x02\x03"
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_file_verified(filepath, content, "test.setting", mode="wb")
|
||||
|
||||
assert filepath.exists()
|
||||
assert filepath.read_bytes() == content
|
||||
|
||||
def test_uses_custom_encoding(self, tmp_path, mock_get_setting):
|
||||
"""Test writing with custom encoding."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.txt"
|
||||
content = "日本語テスト"
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_file_verified(filepath, content, "test.setting", encoding="utf-8")
|
||||
|
||||
assert filepath.exists()
|
||||
assert filepath.read_text(encoding="utf-8") == content
|
||||
|
||||
def test_passes_settings_snapshot(self, tmp_path, mock_get_setting):
|
||||
"""Test that settings_snapshot is passed to get_setting_from_snapshot."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.txt"
|
||||
snapshot = {"test.setting": True}
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_file_verified(
|
||||
filepath, "content", "test.setting", settings_snapshot=snapshot
|
||||
)
|
||||
|
||||
mock_get_setting.assert_called_once_with(
|
||||
"test.setting", settings_snapshot=snapshot
|
||||
)
|
||||
|
||||
def test_accepts_path_object(self, tmp_path, mock_get_setting):
|
||||
"""Test that Path objects are accepted."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_file_verified,
|
||||
)
|
||||
|
||||
filepath = Path(tmp_path) / "test.txt"
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_file_verified(filepath, "content", "test.setting")
|
||||
|
||||
assert filepath.exists()
|
||||
|
||||
|
||||
class TestWriteJsonVerified:
|
||||
"""Tests for the write_json_verified function."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_get_setting(self):
|
||||
"""Fixture to mock the get_setting_from_snapshot function."""
|
||||
with patch(
|
||||
"local_deep_research.config.search_config.get_setting_from_snapshot"
|
||||
) as mock:
|
||||
yield mock
|
||||
|
||||
def test_writes_json_when_setting_matches(self, tmp_path, mock_get_setting):
|
||||
"""Test that JSON is written when setting matches."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_json_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.json"
|
||||
data = {"key": "value", "number": 42}
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_json_verified(filepath, data, "test.setting")
|
||||
|
||||
assert filepath.exists()
|
||||
written_data = json.loads(filepath.read_text())
|
||||
assert written_data == data
|
||||
|
||||
def test_sanitizes_sensitive_data(self, tmp_path, mock_get_setting):
|
||||
"""Test that sensitive data is sanitized before writing."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_json_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.json"
|
||||
data = {"name": "test", "password": "secret123", "api_key": "key456"}
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_json_verified(filepath, data, "test.setting")
|
||||
|
||||
written_data = json.loads(filepath.read_text())
|
||||
assert written_data["name"] == "test"
|
||||
assert written_data["password"] == "[REDACTED]"
|
||||
assert written_data["api_key"] == "[REDACTED]"
|
||||
|
||||
def test_uses_default_indent(self, tmp_path, mock_get_setting):
|
||||
"""Test that default indent of 2 is used."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_json_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.json"
|
||||
data = {"key": "value"}
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_json_verified(filepath, data, "test.setting")
|
||||
|
||||
content = filepath.read_text()
|
||||
# With indent=2, there should be newlines and spaces
|
||||
assert "\n" in content
|
||||
assert " " in content
|
||||
|
||||
def test_custom_json_kwargs(self, tmp_path, mock_get_setting):
|
||||
"""Test that custom JSON kwargs are passed through."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_json_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.json"
|
||||
data = {"b": 2, "a": 1}
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_json_verified(
|
||||
filepath, data, "test.setting", sort_keys=True, indent=4
|
||||
)
|
||||
|
||||
content = filepath.read_text()
|
||||
# With sort_keys, 'a' should come before 'b'
|
||||
assert content.index('"a"') < content.index('"b"')
|
||||
# With indent=4, should have 4 spaces
|
||||
assert " " in content
|
||||
|
||||
def test_writes_list_data(self, tmp_path, mock_get_setting):
|
||||
"""Test writing list data."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_json_verified,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.json"
|
||||
data = [{"name": "item1"}, {"name": "item2", "password": "secret"}]
|
||||
|
||||
mock_get_setting.return_value = True
|
||||
|
||||
write_json_verified(filepath, data, "test.setting")
|
||||
|
||||
written_data = json.loads(filepath.read_text())
|
||||
assert len(written_data) == 2
|
||||
assert written_data[1]["password"] == "[REDACTED]"
|
||||
|
||||
def test_raises_error_when_setting_mismatch(
|
||||
self, tmp_path, mock_get_setting
|
||||
):
|
||||
"""Test that error is raised when setting doesn't match."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
write_json_verified,
|
||||
FileWriteSecurityError,
|
||||
)
|
||||
|
||||
filepath = tmp_path / "test.json"
|
||||
|
||||
mock_get_setting.return_value = False
|
||||
|
||||
with pytest.raises(FileWriteSecurityError):
|
||||
write_json_verified(filepath, {"key": "value"}, "test.setting")
|
||||
|
||||
|
||||
class TestSensitiveKeys:
|
||||
"""Tests for SENSITIVE_KEYS constant."""
|
||||
|
||||
def test_sensitive_keys_is_frozenset(self):
|
||||
"""Test that SENSITIVE_KEYS is a frozenset."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
SENSITIVE_KEYS,
|
||||
)
|
||||
|
||||
assert isinstance(SENSITIVE_KEYS, frozenset)
|
||||
|
||||
def test_sensitive_keys_contains_expected_values(self):
|
||||
"""Test that SENSITIVE_KEYS contains expected sensitive key names."""
|
||||
from local_deep_research.security.file_write_verifier import (
|
||||
SENSITIVE_KEYS,
|
||||
)
|
||||
|
||||
expected_keys = {
|
||||
"password",
|
||||
"api_key",
|
||||
"secret",
|
||||
"token",
|
||||
"credentials",
|
||||
}
|
||||
|
||||
for key in expected_keys:
|
||||
assert key in SENSITIVE_KEYS
|
||||
Reference in New Issue
Block a user