Commit Graph

8 Commits

Author SHA1 Message Date
LearningCircuit
d0a438cc77 fix: SQLCipher mlock() warnings — default cipher_memory_security to OFF (#2355)
cipher_memory_security=ON calls mlock() which fails in Docker without
IPC_LOCK, spamming logs. Defaulting to OFF because the password already
sits unprotected in Flask session, db_manager.connections, and
thread-local storage — mlock on SQLCipher's internal buffers alone
doesn't meaningfully help when the same secret is exposed elsewhere.

Users can opt back in with LDR_DB_CONFIG_CIPHER_MEMORY_SECURITY=ON
(requires IPC_LOCK capability in Docker).

Also moves the pragma outside the creation_mode guard so the env var
override works for existing databases too.
2026-02-22 16:56:22 +00:00
LearningCircuit
65b2383eb7 Revert "Revert "fix: add SQLCipher 4.x compatibility for cipher pragma ordering"" (#1867)
* Revert "Revert "fix: add SQLCipher 4.x compatibility for cipher pragma orderi…"

This reverts commit d72b7ae668.

* ci: add backwards compatibility workflow for SQLCipher encryption

Add a CI workflow that verifies database encryption backwards compatibility:

- Runs encryption constants tests on PRs touching database files
- Runs full PyPI version compatibility test on main/releases
- Triggers on schedule (weekly) to catch dependency drift
- Path-filtered to only run when relevant files change

This prevents regressions like salt or KDF parameter changes that would
break existing encrypted databases.

* ci: add backwards compatibility to security release gate

- Add workflow_call trigger to backwards-compatibility.yml
- Include backwards-compatibility check in security-release-gate.yml
- Run full PyPI compatibility test on releases (not just encryption constants)

This ensures database encryption changes can't break existing user databases
in a release.

* test: increase timeouts for PyPI backwards compatibility test

- Add pytest.mark.timeout(600) for the test function
- Increase pip install timeout from 300s to 600s

The package has many dependencies (numpy, torch, etc.) which take
significant time to install in a fresh venv.

* ci: fix shellcheck SC2129 in backwards-compatibility workflow

Group consecutive GITHUB_OUTPUT redirects into a single block
to satisfy actionlint/shellcheck SC2129 style check.

* fix: comprehensive SQLCipher security and correctness improvements

- Fix critical PRAGMA ordering: cipher_default_* before key for new DBs,
  cipher_* after key for existing DBs (per Zetetic SQLCipher 4.x docs)
- Replace unbounded @cache with @lru_cache(maxsize=8) to prevent memory leaks
- Add thread safety: RLock for connections dict, Lock for cipher_default globals
- Pre-derive hex keys before closures to avoid capturing plaintext passwords
- Add connection cleanup on failure (close conn, remove partial DB files)
- Add engine.dispose() on failed open_user_database()
- Whitespace password validation (reject " " as password)
- Remove cipher_memory_security=OFF (SQLCipher >=4.5 defaults to OFF)
- CI-aware KDF minimum: 100k production, relaxed in test environments
- Add set_sqlcipher_key_from_hex(), get_sqlcipher_version() utilities
- Replace direct db_manager.connections dict access with is_user_connected()
- Update harden-runner to v2.14.1, improve CI error handling
- Fix all except Exception: pass patterns to re-raise AssertionError in tests
- Update all test files for renamed functions and correct PRAGMA ordering

* fix: address race condition in get_session() and exception swallowing in test

Move sessionmaker + session creation inside _connections_lock to prevent
race with close_user_database() disposing the engine. Also fix exception
handler in test_sqlcipher_integration.py to re-raise AssertionError.

* fix: address review issues in SQLCipher 4.x compatibility PR

- Update 3 broken web test files (test_queue_manager, test_decorators,
  test_session_cleanup) to mock is_user_connected()/get_session() instead
  of the removed connections.get() API
- Wire backwards-compatibility.yml into security-release-gate.yml so
  encryption compat checks actually run during releases
- Add missing apply_sqlcipher_pragmas() call in _check_encryption_available()
  to properly set kdf_iter after key on the test connection
- Replace generic CI/TESTING env var checks with PYTEST_CURRENT_TEST and
  LDR_TEST_MODE to prevent accidental KDF weakening in production
- Add timeout-minutes to both backwards-compatibility CI jobs
2026-02-11 02:26:58 +00:00
LearningCircuit
507d0d35ea fix: use env_registry for cipher_memory_security instead of raw os.environ
Addresses djpetti's review comment to use the project's environment
variable setting infrastructure (EnumSetting + get_env_setting) instead
of plain os.environ.get() for cipher_memory_security.
2026-02-10 18:41:32 +01:00
LearningCircuit
f18883b840 fix: SQLCipher key derivation & crypto security fixes
- CRITICAL: Fix set_sqlcipher_rekey to use PBKDF2-derived key via
  _get_key_from_password instead of raw UTF-8 hex encoding, which
  would make databases unopenable after password change
- Replace unbounded functools.cache with TTL-bounded cachetools.TTLCache
  (5min TTL, thread-safe) to prevent memory growth from cached keys
- Make cipher_memory_security configurable via LDR_DB_CIPHER_MEMORY_SECURITY
  env var (default ON) instead of hardcoded OFF
- Remove password length logging in scheduler (log presence only)
- Expand documentation on static PBKDF2 salt trade-off
- Add tests for rekey fix, cipher_memory_security, and TTL cache
2026-02-04 19:39:51 +01:00
LearningCircuit
d72b7ae668 Revert "fix: add SQLCipher 4.x compatibility for cipher pragma ordering" (#1866) 2026-02-01 00:09:56 +00:00
LearningCircuit
861b78d63e Merge test/sqlcipher-integration-tests with SQLCipher 4.x fixes
Integrates 67 SQLCipher integration tests with the SQLCipher 4.x
compatibility branch. Updates unit tests to reflect the new architecture:

- apply_cipher_settings_before_key(): cipher_page_size, cipher_hmac_algorithm,
  cipher_kdf_algorithm (must be set BEFORE key in SQLCipher 4.x)
- apply_sqlcipher_pragmas(): only kdf_iter (set AFTER key)

Test changes:
- Update test_applies_core_pragmas to only check kdf_iter
- Rename test_key_before_cipher_pragmas to test_sqlcipher_4x_pragma_order
- Update test_all_cipher_pragmas_present to verify both functions
- Add TestApplyCipherSettingsBeforeKey test class for new function
2026-01-21 20:12:43 +01:00
LearningCircuit
e8a7121dd6 test: add SQLCipher integration tests and pragma order verification
Add real SQLCipher integration tests that verify the registration → login
flow which was previously failing in UI tests. Also add pragma order
verification tests to ensure key is set before cipher pragmas.

New tests:
- test_sqlcipher_integration.py: 8 real SQLCipher tests (not mocked)
- TestPragmaOrder class: 5 pragma order verification tests
2026-01-20 22:54:26 +01:00
LearningCircuit
f8011588a8 test: add unit tests for untested modules
Add 14 new test files covering 4 major areas:

**Web Utilities (5 files, 65 tests)**
- test_formatters.py: output formatting helpers
- test_rate_limiter.py: rate limiting logic with Flask contexts
- test_theme_helper.py: theme detection and persistence
- test_templates.py: template rendering utilities
- test_vite_helper.py: Vite asset path resolution

**Database Modules (4 files, 64 tests)**
- test_session_context.py: session context management
- test_thread_local_session.py: thread-local session handling
- test_sqlcipher_utils.py: SQLCipher encryption utilities
- test_thread_metrics.py: per-thread metrics writer

**Security File Integrity (2 files, 33 tests)**
- test_base_verifier.py: base verifier class and checksum
- test_integrity_manager.py: file integrity verification

**Library Download Management (3 files, 64 tests)**
- test_failure_classifier.py: failure categorization
- test_retry_manager.py: retry logic and filter summaries
- test_status_tracker.py: download status tracking

Total: 226 new tests, all passing.
2026-01-18 11:52:06 +01:00