Skip to content

v0.2.3 — security + correctness fixes

Latest

Choose a tag to compare

@BAder82t BAder82t released this 01 May 22:58
· 1 commit to main since this release

Highlights

Bug-fix release rolling up the security + correctness remediation from a code/security re-review of v0.2.2.

Security

  • Secret-key isolationmake_evaluator_context now serialises the inner TenSEAL Context without the secret key and rebuilds the wrapper from explicit fields. The keyholder's context is never mutated and shares no mutable state with the evaluator copy.
  • Sub-128-bit CKKS refusedbuild_context validates (poly_modulus_degree, coeff_mod_bit_sizes) against the HE-standard 128-bit table. Sub-128-bit configurations require explicit insecure_allow_low_security=True and emit InsecureCKKSParametersWarning.
  • Signature downgrade closed — Signed envelopes write the canonical signature_b64 field. validate_envelope rejects legacy value-only blocks (closes the relay-strip downgrade vector). verify_envelope_signature still reads value for back-compat verification of v0.2.2 envelopes.
  • min_security_bits floorvalidate_envelope defaults to 128. Pass 0 to opt out.
  • CLI --require-signature enforces verification — Single error per failure mode (no key, key read failure, missing signature block, bad signature). No more silent satisfaction when only a signature block is present.
  • ANSI / Unicode sanitisation_safe_str (used by inspect) strips full CSI/OSC sequences and Unicode bidi / zero-width characters.

Correctness

  • Per-thread op_session() — New context manager with threading.local stack. True isolation under concurrent audits — the previous reset_op_counters + snapshot pattern interleaved across threads.
  • Encrypted-mask MSE depth fix_per_group_mse_terms re-folds mask · sw into a single ct×pt before the ct×ct against ŷ², landing at depth 2 (was 3).
  • MAE opt-inmean_absolute_error_group_max(..., approximate=True) (default) acknowledges the sqrt(MSE) approximation; approximate=False raises NotImplementedError.
  • _safe_div consolidated — Single canonical implementation in _circuits used by base, scoring, and regression metrics.
  • EncryptedVector.encrypt bounds-checks — Rejects vectors larger than ctx.n_slots instead of silently truncating.
  • Scoring closures_group_min/_group_max/_group_difference/_group_ratio capture reduction as an explicit closure variable. Plaintext fallback when fairlearn lacks the helper.
  • audit_metric records n_groups=0 when no sensitive features.
  • Misc — Fixed double-indented _build_encrypted body, lifted functools import out of hot loop, vectorised group_masks for single-column sensitive features.

Tests

Test fixture upgraded to N=16384 with an 8-prime chain (depth 6, 128-bit security). Two new regression suites — tests/test_review_v0_2_3_fixes.py and tests/test_review_v0_2_4_fixes.py — totalling 44 tests. 385 tests passing.

Migration

  • Envelopes signed by v0.2.2 still verify cryptographically via verify_envelope_signature. To pass validate_envelope they must be re-signed with v0.2.3 (the canonical signature_b64 field is now required).
  • Callers building contexts with custom coeff_mod_bit_sizes may need to pick parameters from the HE-standard 128-bit table or pass insecure_allow_low_security=True.

Full diff: v0.2.2...v0.2.3