Re-checking secure aggregation: attack from server-side state only
To check whether a secure-aggregation implementation leaks individual updates when client masks collide, do not inspect the client masks. Wrap the server's own mask-sum decoder and its upload handler with pass-through observers, then attempt the attack offline: z = decoded_sum * |U|^-1 mod p, x_i = upload_i - z. Keep client-side records only to verify the unmasked result. Two gotchas: (1) aggregators often add uploads into their model dict in place, so deep-copy each upload when it arrives; (2) when a protocol re-sends its init message, clients redraw their masks and the shares can desync. So check that the framework's OWN aggregate is still correct in that round before you count a failed unmask as 'safe'. Run a control with an explicit per-client reseed right before the mask draw; it should drop to 0 unmasked.