Detail Bug Report
https://app.detail.dev/org_89d327b3-b883-4365-b6a3-46b6701342a9/bugs/bug_d22aba2e-b5b1-4f13-819b-392d704f8c9b
Introduced in #37 by @infiniteregrets on Apr 22, 2026
Summary
- Context: The
validate_encryption_key function validates encryption keys passed when accessing encrypted streams in the S2 SDK.
- Bug: The validator only checks that the key is valid base64, but does not verify that the decoded key is 32 bytes as required by the encryption algorithms (AEGIS-256 and AES-256-GCM).
- Actual vs. expected: Currently accepts any valid base64 string of any decoded length; should reject keys that don't decode to exactly 32 bytes.
- Impact: Users get an uninformative
422 invalid error from the server instead of a precise client-side error message.
Code with Bug
# src/s2_sdk/_validators.py
def validate_encryption_key(key: str) -> None:
try:
base64.b64decode(key, validate=True) # <-- BUG 🔴 only validates base64; does not enforce 32-byte decoded length
except Exception:
raise S2ClientError("encryption_key must be a base64 encoded str")
# src/s2_sdk/_ops.py
elif isinstance(encryption_key, bytes):
encryption_key = base64.b64encode(encryption_key).decode() # <-- BUG 🔴 bytes key length not validated; non-32B keys get encoded and sent
Explanation
Both supported ciphers require a 32-byte key, but the SDK accepts any base64 string (and any bytes length) and only fails later when the server rejects it with 422 invalid. This prevents the SDK from providing an immediate, actionable client-side error (e.g., reporting the decoded length).
Codebase Inconsistency
Other validators (e.g. validate_basin, validate_append_input) enforce documented constraints client-side even when the server also validates, to provide clearer errors. validate_encryption_key only enforces one of the documented requirements (base64 format) and omits the 32-byte requirement.
Recommended Fix
# src/s2_sdk/_validators.py
def validate_encryption_key(key: str) -> None:
try:
decoded = base64.b64decode(key, validate=True)
except Exception:
raise S2ClientError("encryption_key must be a base64 encoded str")
if len(decoded) != 32:
raise S2ClientError(
f"encryption_key must decode to 32 bytes, got {len(decoded)} bytes"
)
# src/s2_sdk/_ops.py
elif isinstance(encryption_key, bytes):
if len(encryption_key) != 32:
raise S2ClientError(
f"encryption_key must be 32 bytes, got {len(encryption_key)} bytes"
)
encryption_key = base64.b64encode(encryption_key).decode()
History
This bug was introduced in commit b7df199. The original EncryptionKey class validated only that the base64-encoded string length was <= 44 characters, missing that the decoded key must be exactly 32 bytes for AEGIS-256 and AES-256-GCM ciphers. The incomplete validation (checking upper bound but not exact length) persisted through subsequent refactoring: commit 1958253 moved the class to _types.py, and commit 2106eda replaced it with the simpler validate_encryption_key function that only checks base64 format.
Detail Bug Report
https://app.detail.dev/org_89d327b3-b883-4365-b6a3-46b6701342a9/bugs/bug_d22aba2e-b5b1-4f13-819b-392d704f8c9b
Introduced in #37 by @infiniteregrets on Apr 22, 2026
Summary
validate_encryption_keyfunction validates encryption keys passed when accessing encrypted streams in the S2 SDK.422 invaliderror from the server instead of a precise client-side error message.Code with Bug
Explanation
Both supported ciphers require a 32-byte key, but the SDK accepts any base64 string (and any bytes length) and only fails later when the server rejects it with
422 invalid. This prevents the SDK from providing an immediate, actionable client-side error (e.g., reporting the decoded length).Codebase Inconsistency
Other validators (e.g.
validate_basin,validate_append_input) enforce documented constraints client-side even when the server also validates, to provide clearer errors.validate_encryption_keyonly enforces one of the documented requirements (base64 format) and omits the 32-byte requirement.Recommended Fix
History
This bug was introduced in commit b7df199. The original
EncryptionKeyclass validated only that the base64-encoded string length was <= 44 characters, missing that the decoded key must be exactly 32 bytes for AEGIS-256 and AES-256-GCM ciphers. The incomplete validation (checking upper bound but not exact length) persisted through subsequent refactoring: commit 1958253 moved the class to_types.py, and commit 2106eda replaced it with the simplervalidate_encryption_keyfunction that only checks base64 format.