Files
wehub-resource-sync 7a0da7932b
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
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

489 lines
18 KiB
Python

"""
Behavioral tests for data_sanitizer module.
Tests the DataSanitizer class which removes or redacts sensitive
information from data structures.
"""
class TestSanitizeBasicDictionary:
"""Tests for sanitizing basic dictionaries."""
def test_removes_api_key(self):
"""api_key is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"username": "user", "api_key": "secret123"}
result = DataSanitizer.sanitize(data)
assert "api_key" not in result
assert result["username"] == "user"
def test_removes_password(self):
"""password is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"username": "user", "password": "secret123"}
result = DataSanitizer.sanitize(data)
assert "password" not in result
assert result["username"] == "user"
def test_removes_secret(self):
"""secret is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"name": "service", "secret": "abc123"}
result = DataSanitizer.sanitize(data)
assert "secret" not in result
assert result["name"] == "service"
def test_removes_access_token(self):
"""access_token is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"user_id": 1, "access_token": "token123"}
result = DataSanitizer.sanitize(data)
assert "access_token" not in result
assert result["user_id"] == 1
def test_removes_refresh_token(self):
"""refresh_token is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"user_id": 1, "refresh_token": "refresh123"}
result = DataSanitizer.sanitize(data)
assert "refresh_token" not in result
def test_removes_private_key(self):
"""private_key is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"key_id": "k1", "private_key": "-----BEGIN..."}
result = DataSanitizer.sanitize(data)
assert "private_key" not in result
def test_removes_auth_token(self):
"""auth_token is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"session": "s1", "auth_token": "auth123"}
result = DataSanitizer.sanitize(data)
assert "auth_token" not in result
def test_removes_session_token(self):
"""session_token is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"user": "u1", "session_token": "sess123"}
result = DataSanitizer.sanitize(data)
assert "session_token" not in result
def test_removes_csrf_token(self):
"""csrf_token is removed from dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"form": "f1", "csrf_token": "csrf123"}
result = DataSanitizer.sanitize(data)
assert "csrf_token" not in result
def test_removes_apikey_no_underscore(self):
"""apikey (without underscore) is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"service": "s1", "apikey": "key123"}
result = DataSanitizer.sanitize(data)
assert "apikey" not in result
class TestSanitizeCaseInsensitive:
"""Tests for case-insensitive key matching."""
def test_removes_API_KEY_uppercase(self):
"""API_KEY in uppercase is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"name": "test", "API_KEY": "secret"}
result = DataSanitizer.sanitize(data)
assert "API_KEY" not in result
def test_removes_Api_Key_mixed_case(self):
"""Api_Key in mixed case is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"name": "test", "Api_Key": "secret"}
result = DataSanitizer.sanitize(data)
assert "Api_Key" not in result
def test_removes_PASSWORD_uppercase(self):
"""PASSWORD in uppercase is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"user": "u1", "PASSWORD": "secret"}
result = DataSanitizer.sanitize(data)
assert "PASSWORD" not in result
def test_removes_Secret_capitalized(self):
"""Secret capitalized is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"id": 1, "Secret": "mysecret"}
result = DataSanitizer.sanitize(data)
assert "Secret" not in result
class TestSanitizeNestedStructures:
"""Tests for nested dictionaries and lists."""
def test_removes_key_in_nested_dict(self):
"""api_key in nested dictionary is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"user": {"name": "test", "api_key": "secret"}}
result = DataSanitizer.sanitize(data)
assert "api_key" not in result["user"]
assert result["user"]["name"] == "test"
def test_removes_key_in_deeply_nested_dict(self):
"""api_key in deeply nested dictionary is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"a": {"b": {"c": {"password": "secret", "value": 1}}}}
result = DataSanitizer.sanitize(data)
assert "password" not in result["a"]["b"]["c"]
assert result["a"]["b"]["c"]["value"] == 1
def test_removes_key_in_list_of_dicts(self):
"""api_key in list of dictionaries is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = [{"name": "a", "api_key": "k1"}, {"name": "b", "api_key": "k2"}]
result = DataSanitizer.sanitize(data)
assert all("api_key" not in item for item in result)
assert result[0]["name"] == "a"
assert result[1]["name"] == "b"
def test_removes_key_in_mixed_nested_structure(self):
"""api_key in mixed nested structure is removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {
"users": [{"id": 1, "password": "p1"}, {"id": 2, "password": "p2"}],
"config": {"api_key": "main_key"},
}
result = DataSanitizer.sanitize(data)
assert all("password" not in user for user in result["users"])
assert "api_key" not in result["config"]
class TestSanitizePrimitives:
"""Tests for primitive values."""
def test_returns_string_unchanged(self):
"""String primitives are returned unchanged."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert DataSanitizer.sanitize("hello") == "hello"
def test_returns_number_unchanged(self):
"""Number primitives are returned unchanged."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert DataSanitizer.sanitize(42) == 42
assert DataSanitizer.sanitize(3.14) == 3.14
def test_returns_boolean_unchanged(self):
"""Boolean primitives are returned unchanged."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert DataSanitizer.sanitize(True) is True
assert DataSanitizer.sanitize(False) is False
def test_returns_none_unchanged(self):
"""None is returned unchanged."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert DataSanitizer.sanitize(None) is None
class TestSanitizeCustomKeys:
"""Tests for custom sensitive key sets."""
def test_custom_keys_are_removed(self):
"""Custom sensitive keys are removed."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"custom_secret": "value", "name": "test"}
result = DataSanitizer.sanitize(data, sensitive_keys={"custom_secret"})
assert "custom_secret" not in result
assert result["name"] == "test"
def test_default_keys_not_removed_with_custom(self):
"""Default keys are not removed when custom set is provided."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"api_key": "value", "custom_key": "secret"}
result = DataSanitizer.sanitize(data, sensitive_keys={"custom_key"})
# With custom keys, default keys are not removed
assert "api_key" in result
assert "custom_key" not in result
def test_empty_custom_keys_removes_nothing(self):
"""Empty custom key set removes nothing."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"api_key": "value", "password": "secret"}
result = DataSanitizer.sanitize(data, sensitive_keys=set())
assert "api_key" in result
assert "password" in result
class TestSanitizeEmptyInputs:
"""Tests for empty inputs."""
def test_empty_dict_returns_empty(self):
"""Empty dictionary returns empty dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert DataSanitizer.sanitize({}) == {}
def test_empty_list_returns_empty(self):
"""Empty list returns empty list."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert DataSanitizer.sanitize([]) == []
class TestSanitizeOriginalUnmodified:
"""Tests that original data is not modified."""
def test_original_dict_unchanged(self):
"""Original dictionary is not modified."""
from local_deep_research.security.data_sanitizer import DataSanitizer
original = {"name": "test", "api_key": "secret"}
DataSanitizer.sanitize(original)
assert "api_key" in original
def test_original_nested_dict_unchanged(self):
"""Original nested dictionary is not modified."""
from local_deep_research.security.data_sanitizer import DataSanitizer
original = {"user": {"name": "test", "password": "secret"}}
DataSanitizer.sanitize(original)
assert "password" in original["user"]
class TestRedactBasicDictionary:
"""Tests for redacting basic dictionaries."""
def test_redacts_api_key(self):
"""api_key value is redacted."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"username": "user", "api_key": "secret123"}
result = DataSanitizer.redact(data)
assert result["api_key"] == "[REDACTED]"
assert result["username"] == "user"
def test_redacts_password(self):
"""password value is redacted."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"username": "user", "password": "secret123"}
result = DataSanitizer.redact(data)
assert result["password"] == "[REDACTED]"
assert result["username"] == "user"
def test_redacts_multiple_keys(self):
"""Multiple sensitive keys are redacted."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {
"api_key": "k1",
"password": "p1",
"secret": "s1",
"name": "test",
}
result = DataSanitizer.redact(data)
assert result["api_key"] == "[REDACTED]"
assert result["password"] == "[REDACTED]"
assert result["secret"] == "[REDACTED]"
assert result["name"] == "test"
class TestRedactCustomText:
"""Tests for custom redaction text."""
def test_custom_redaction_text(self):
"""Custom redaction text is used."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"api_key": "secret"}
result = DataSanitizer.redact(data, redaction_text="***HIDDEN***")
assert result["api_key"] == "***HIDDEN***"
def test_empty_redaction_text(self):
"""Empty redaction text is used."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"api_key": "secret"}
result = DataSanitizer.redact(data, redaction_text="")
assert result["api_key"] == ""
class TestRedactNestedStructures:
"""Tests for redacting nested structures."""
def test_redacts_nested_dict(self):
"""Nested dictionary values are redacted."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"config": {"api_key": "secret", "url": "http://example.com"}}
result = DataSanitizer.redact(data)
assert result["config"]["api_key"] == "[REDACTED]"
assert result["config"]["url"] == "http://example.com"
def test_redacts_list_of_dicts(self):
"""List of dictionaries values are redacted."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = [
{"name": "a", "password": "p1"},
{"name": "b", "password": "p2"},
]
result = DataSanitizer.redact(data)
assert result[0]["password"] == "[REDACTED]"
assert result[1]["password"] == "[REDACTED]"
assert result[0]["name"] == "a"
class TestRedactPreservesStructure:
"""Tests that redact preserves data structure."""
def test_preserves_key_in_result(self):
"""Redacted key is still present in result."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"api_key": "secret"}
result = DataSanitizer.redact(data)
assert "api_key" in result
def test_preserves_nested_structure(self):
"""Nested structure is preserved."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"a": {"b": {"password": "secret"}}}
result = DataSanitizer.redact(data)
assert "a" in result
assert "b" in result["a"]
assert "password" in result["a"]["b"]
class TestConvenienceFunctions:
"""Tests for convenience functions."""
def test_sanitize_data_function(self):
"""sanitize_data convenience function works."""
from local_deep_research.security.data_sanitizer import sanitize_data
data = {"api_key": "secret", "name": "test"}
result = sanitize_data(data)
assert "api_key" not in result
assert result["name"] == "test"
def test_redact_data_function(self):
"""redact_data convenience function works."""
from local_deep_research.security.data_sanitizer import redact_data
data = {"api_key": "secret", "name": "test"}
result = redact_data(data)
assert result["api_key"] == "[REDACTED]"
assert result["name"] == "test"
def test_sanitize_data_with_custom_keys(self):
"""sanitize_data works with custom keys."""
from local_deep_research.security.data_sanitizer import sanitize_data
data = {"custom": "value", "other": "data"}
result = sanitize_data(data, sensitive_keys={"custom"})
assert "custom" not in result
assert result["other"] == "data"
def test_redact_data_with_custom_text(self):
"""redact_data works with custom redaction text."""
from local_deep_research.security.data_sanitizer import redact_data
data = {"password": "secret"}
result = redact_data(data, redaction_text="<removed>")
assert result["password"] == "<removed>"
class TestDefaultSensitiveKeys:
"""Tests for the default sensitive keys constant."""
def test_default_keys_include_api_key(self):
"""Default keys include api_key."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert "api_key" in DataSanitizer.DEFAULT_SENSITIVE_KEYS
def test_default_keys_include_password(self):
"""Default keys include password."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert "password" in DataSanitizer.DEFAULT_SENSITIVE_KEYS
def test_default_keys_include_secret(self):
"""Default keys include secret."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert "secret" in DataSanitizer.DEFAULT_SENSITIVE_KEYS
def test_default_keys_is_set(self):
"""Default keys is a set for O(1) lookup."""
from local_deep_research.security.data_sanitizer import DataSanitizer
assert isinstance(DataSanitizer.DEFAULT_SENSITIVE_KEYS, set)
class TestEdgeCases:
"""Tests for edge cases."""
def test_handles_none_values_in_dict(self):
"""Handles None values in dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"name": None, "api_key": "secret"}
result = DataSanitizer.sanitize(data)
assert result["name"] is None
assert "api_key" not in result
def test_handles_numeric_values(self):
"""Handles numeric values in dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"count": 42, "api_key": "secret"}
result = DataSanitizer.sanitize(data)
assert result["count"] == 42
assert "api_key" not in result
def test_handles_boolean_values(self):
"""Handles boolean values in dictionary."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = {"enabled": True, "password": "secret"}
result = DataSanitizer.sanitize(data)
assert result["enabled"] is True
assert "password" not in result
def test_handles_mixed_types_in_list(self):
"""Handles mixed types in list."""
from local_deep_research.security.data_sanitizer import DataSanitizer
data = [1, "string", {"api_key": "secret"}, None, True]
result = DataSanitizer.sanitize(data)
assert result[0] == 1
assert result[1] == "string"
assert "api_key" not in result[2]
assert result[3] is None
assert result[4] is True