Skip to content

fix: notify() generates iv_nonce and a fresh session_id per call#522

Open
cconstab wants to merge 1 commit into
trunkfrom
fix/notify-iv-nonce-and-session-id
Open

fix: notify() generates iv_nonce and a fresh session_id per call#522
cconstab wants to merge 1 commit into
trunkfrom
fix/notify-iv-nonce-and-session-id

Conversation

@cconstab

@cconstab cconstab commented Jul 2, 2026

Copy link
Copy Markdown
Member

notify() had two defects, both in at_client/atclient.py:

  1. Crashes without a nonce. It read at_key.metadata.iv_nonce and passed it
    straight to aes_encrypt_from_base64; if the caller hadn't set it, AES-CTR raised
    nonce must be bytes-like. Callers had to set metadata.iv_nonce manually.
  2. Shared session_id. The signature default session_id=str(uuid.uuid4()) is
    evaluated once at import, so every notify() without an explicit id reused the same
    id for the process lifetime. The atServer dedups by notification id, so duplicate /
    rapid notifications were silently dropped.

Fix: generate the nonce inside notify() when unset (and store it on the key's
metadata so it travels with the notification for the receiver to decrypt), and default
session_id to None, minting a fresh UUID per call.

Tests: test/notify_test.py — network-free:

  • session_id default is None (regression against the import-time UUID)
  • notify() sets iv_nonce when the key has none (mocked network)

Found while building a production integration on atsdk; both were reproducible in
isolation.

notify() crashed when the AtKey had no iv_nonce ('nonce must be bytes-like'),
forcing callers to set metadata.iv_nonce manually. It also used a signature
default session_id=str(uuid.uuid4()), which is evaluated once at import, so every
notify() without an explicit id reused the same one and the server deduped the
duplicates.

Generate the AES nonce inside notify() when unset (and store it on the key's
metadata so it travels with the notification), and default session_id to None,
generating a fresh UUID per call.

Adds network-free unit tests for both behaviours.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes two long-standing correctness issues in AtClient.notify() by ensuring encrypted notifications always have the required AES-CTR nonce and by preventing reuse of a single import-time session_id. It also adds network-free regression tests covering both behaviors.

Changes:

  • Change notify() to default session_id to None and mint a fresh UUID per call when not provided.
  • Ensure notify() generates and sets metadata.iv_nonce when it is missing, preventing AES-CTR crashes.
  • Add test/notify_test.py to validate the session_id default and nonce generation without requiring network connections.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
at_client/atclient.py Fix notify() session ID default behavior and generate/store an AES-CTR nonce when missing.
test/notify_test.py Add regression tests ensuring session_id is not an import-time UUID and iv_nonce is generated.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread at_client/atclient.py
Comment on lines 433 to +436
iv = at_key.metadata.iv_nonce
if iv is None:
iv = EncryptionUtil.generate_iv_nonce()
at_key.metadata.iv_nonce = iv
Comment thread test/notify_test.py
from at_client import AtClient
from at_client.common import AtSign
from at_client.common.keys import SharedKey
from at_client.util.encryptionutil import EncryptionUtil
@cconstab cconstab requested a review from cpswan July 3, 2026 02:55
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.

2 participants