Skip to content

Improve test coverage and document possible vulnerabilities (unexploitable under different inter-query keys)#9

Open
p0mvn wants to merge 1 commit intomenonsamir:artifactfrom
valargroup:security/selective-failure-side-channel
Open

Improve test coverage and document possible vulnerabilities (unexploitable under different inter-query keys)#9
p0mvn wants to merge 1 commit intomenonsamir:artifactfrom
valargroup:security/selective-failure-side-channel

Conversation

@p0mvn
Copy link
Copy Markdown

@p0mvn p0mvn commented Mar 27, 2026

Feedback from Zellic audit.

Summary

This PR adds test suites that document two security vulnerabilities in the YPIR client response-decoding path, along with comprehensive boundary/edge-case tests for malformed server responses.

Note: the vulnerabilities are unexploitable under different inter-query keys.

Vulnerability 1 — Selective-failure side channel (decode_response_normal_yclient)

Location: src/client.rs, lines 718-723 and 731-736

The assert!(val < lwe_q_prime) range checks in the RLWE→LWE decoding pipeline panic when a deserialized coefficient exceeds lwe_q_prime. Because the coefficients are derived by subtracting the client's secret key from the ciphertext, whether the assertion fires depends on the secret key.

A malicious server can exploit this by crafting a response where:

  • Client A (with key k₁) passes the assertion and returns a result
  • Client B (with key k₂) hits the assertion and panics

This leaks 1 bit of secret-key-dependent information per query. The server observes whether the client proceeds normally or crashes/disconnects, distinguishing keys without ever seeing them.

Concrete demonstration: The test decode_normal_crafted_near_boundary_same_outcome feeds a 0x7F-filled response to 5 different keys and observes outcomes [false, false, true, false, false] — confirming the side channel. A second test (decode_normal_max_value_bytes_same_outcome_different_keys) shows the same divergence on 0xFF-filled responses.

Suggested fix: Replace the assert! calls with saturating/wrapping arithmetic or return a Result, ensuring the code path is identical regardless of the secret key.

Vulnerability 2 — Unchecked accumulator overflow (YClient::decode_response)

Location: src/client.rs, decode_response method

The inner-product accumulator uses u128, but the function does not validate that inputs are < params.modulus. When given u64::MAX values, poly_len × (u64::MAX)² overflows u128::MAX, causing a panic in debug mode or silent wraparound in release mode.

While not directly exploitable as a side channel (the overflow is key-independent), it means a malicious server can cause a guaranteed client crash with crafted responses, and the silent wraparound in release mode produces garbage plaintext.

Suggested fix: Validate input coefficients are < params.modulus before accumulation, or document the precondition and enforce it at the deserialization boundary.


What this PR adds

File Tests added Purpose
src/client.rs 22 tests in malformed_response_tests Boundary, overflow, determinism, and side-channel tests for all three decode paths (decode_response, decode_response_normal_yclient, decode_response_simplepir_yclient)
src/modulus_switch.rs 9 tests in mod test Length validation, boundary values, round-trip, and adversarial-bytes tests for recover and switch

The two side-channel demonstration tests are marked #[ignore] since they are expected to fail (they document the vulnerability rather than assert correct behavior).

How to reproduce

# Run the full test suite (side-channel tests are skipped by default)
cargo test

# Run the ignored side-channel demonstration tests
cargo test -- --ignored decode_normal_crafted_near_boundary_same_outcome
cargo test -- --ignored decode_normal_max_value_bytes_same_outcome_different_keys

…ding

The `assert!(val < lwe_q_prime)` range checks in `decode_response_normal_yclient`
(lines 718-723, 731-736) panic on malicious server responses in a way that depends
on the client's secret key. A malicious server can craft responses that cause some
keys to panic and others to succeed, leaking 1 bit of key-dependent information per
query.

This commit adds:
- Comprehensive malformed-response test suites for all three decode paths
  (YClient::decode_response, decode_response_normal_yclient,
  decode_response_simplepir_yclient)
- Two #[ignore]'d tests that demonstrate the selective-failure side channel
  with concrete observed outcomes
- Boundary, overflow, and determinism tests for modulus_switch::recover

Made-with: Cursor
@p0mvn p0mvn changed the title Security: document selective-failure side channel in response decoding Improve test coverage and document possible vulnerabilities (unexploitable under different inter-query keys) Mar 27, 2026
@p0mvn p0mvn closed this Mar 27, 2026
@p0mvn p0mvn reopened this Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant