Skip to content

Add support for pushing secrets and receiving secret pushes#6164

Open
uhoreg wants to merge 3 commits intomatrix-org:mainfrom
uhoreg:secret_push
Open

Add support for pushing secrets and receiving secret pushes#6164
uhoreg wants to merge 3 commits intomatrix-org:mainfrom
uhoreg:secret_push

Conversation

@uhoreg
Copy link
Member

@uhoreg uhoreg commented Feb 12, 2026

see MSC4385

Pushing secrets allow devices to send secrets to other devices without waiting for a secret request.

closes #6040

  • Public API changes documented in changelogs (optional)

Signed-off-by:

@uhoreg uhoreg requested review from a team as code owners February 12, 2026 00:29
@uhoreg uhoreg requested review from poljar and stefanceriu and removed request for a team February 12, 2026 00:29
@codecov
Copy link

codecov bot commented Feb 12, 2026

Codecov Report

❌ Patch coverage is 79.59184% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.80%. Comparing base (29aa3c2) to head (51fc07e).
⚠️ Report is 21 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
crates/matrix-sdk-sqlite/src/crypto_store.rs 86.88% 2 Missing and 14 partials ⚠️
crates/matrix-sdk-crypto/src/store/types.rs 17.64% 14 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6164      +/-   ##
==========================================
- Coverage   89.81%   89.80%   -0.01%     
==========================================
  Files         376      376              
  Lines      102469   102586     +117     
  Branches   102469   102586     +117     
==========================================
+ Hits        92030    92130     +100     
- Misses       6855     6860       +5     
- Partials     3584     3596      +12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 12, 2026

Merging this PR will not alter performance

✅ 50 untouched benchmarks


Comparing uhoreg:secret_push (51fc07e) with main (cbfecf5)

Open in CodSpeed

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

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

A couple of initial thoughts.

Comment on lines +342 to +348
/// Get all the pushed secrets with the given [`SecretName`] we have
/// currently stored.
#[cfg(feature = "experimental-push-secrets")]
async fn get_pushed_secrets_from_inbox(
&self,
secret_name: &SecretName,
) -> Result<Vec<SecretPushContent>, Self::Error>;
Copy link
Member

Choose a reason for hiding this comment

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

do we not need to call this in matrix-sdk somewhere? Is that planned for a future PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that is a future PR. I wrote this PR first, then worked on the js-sdk parts, and then worked on the matrix-sdk parts. I could add the matrix-sdk parts to this PR, but I kind of feel like it's cleaner keeping them separate. But I'm not entirely sure, and am willing to be convinced otherwise.

Copy link
Member

Choose a reason for hiding this comment

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

ah, no worries. Could I ask you to try and make that sort of thing clear (e.g. in the description) for future PRs?

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

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

also, needs more CHANGELOG.md

@stefanceriu stefanceriu removed their request for review March 4, 2026 08:36
@poljar poljar removed their request for review March 11, 2026 10:39
@uhoreg
Copy link
Member Author

uhoreg commented Mar 19, 2026

I believe this is ready for re-review

@uhoreg uhoreg requested a review from richvdh March 19, 2026 19:51
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

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

Various comments.

keys::SECRETS_INBOX,
(secret.secret_name.as_str(), secret.event.content.request_id.as_str()),
keys::SECRETS_INBOX_V2,
(secret.secret_name.as_str(), secret.secret.as_str()),
Copy link
Member

Choose a reason for hiding this comment

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

why is the secret value used as part of the key?

Copy link
Member Author

@uhoreg uhoreg Mar 23, 2026

Choose a reason for hiding this comment

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

If we get sent two different secrets for the same name, we need to keep both of them, so that we can check which one is correct.

Copy link
Member Author

Choose a reason for hiding this comment

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

Speaking of which, I need to add a test to make sure that things don't explode when you receive the same secret twice.

Copy link
Member

Choose a reason for hiding this comment

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

If we get sent two different secrets for the same name, we need to keep both of them, so that we can check which one is correct.

Ah ok. It would be good to note that as a comment somewhere.

pub(crate) async fn data_migrate(name: &str, serializer: &SafeEncodeSerializer) -> Result<()> {
let db = MigrationDb::new(name, 11).await?;

// The new store has been made for inbound group sessions; time to populate it.
Copy link
Member

Choose a reason for hiding this comment

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

not inbound group sessions

Comment on lines +108 to +112
/// The contents of the secret.
#[serde(
serialize_with = "zeroizing_string_serializer",
deserialize_with = "zeroizing_string_deserializer"
)]
Copy link
Member

Choose a reason for hiding this comment

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

this is a bit of a pain. I'm not really seeing why we need to implement Serialize for SecretsInboxItem?

Assuming we do need to implement it, it might be cleaner instead to make secret a regular String and then make SecretsInboxItem [#derive(Zeroize,ZeroizeOnDrop)]

Comment on lines +1 to +4
CREATE TABLE "secrets_inbox" (
"secret_name" BLOB NOT NULL,
"secret" BLOB NOT NULL
);
Copy link
Member

Choose a reason for hiding this comment

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

probably needs an index on secret_name

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, probably. I just copied the old schema and forgot about that. The table will likely be small enough that it won't make a difference in practice, but I should add one anyways.

///
/// This must be done before creating the store cipher, because the store cipher
/// requires the `kv` table.
pub(crate) async fn initialize_store(conn: &SqliteAsyncConn, version: u8) -> Result<u8> {
Copy link
Member

Choose a reason for hiding this comment

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

what is the version argument?

Comment on lines +52 to +54
- [**breaking**] `CryptoStore::get_secrets_from_inbox` now returns a `Vec` of
the secrets as strings, rather than a `Vec` of `GossippedSecret` structs.
([#6164](https://github.com/matrix-org/matrix-rust-sdk/pull/6164))
Copy link
Member

Choose a reason for hiding this comment

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

and Changes has, uh, changed.

Copy link
Member

Choose a reason for hiding this comment

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

Also: newest entries go at the top, in the same way that newest releases go at the top.

Comment on lines +322 to +336
let encrypted_event_type = content.event_type().to_owned();
let request = ToDeviceRequest::new(
device.user_id(),
device.device_id().to_owned(),
&encrypted_event_type,
content.cast(),
);
let request = OutgoingRequest {
request_id: request.txn_id.clone(),
request: Arc::new(request.into()),
};
self.inner
.outgoing_requests
.write()
.insert(request.request_id.clone(), request);
Copy link
Member

Choose a reason for hiding this comment

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

do the messages and their msgids get logged anywhere, so we can see what is going on?

Comment on lines +57 to +61
impl Drop for SecretPushContent {
fn drop(&mut self) {
self.zeroize()
}
}
Copy link
Member

Choose a reason for hiding this comment

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

you could use derive(ZeroizeOnDrop) for this

Comment on lines +36 to +37
- Add support for MSC4385.
- Add new method `OlmMachine::push_secret_to_verified_devices`.
Copy link
Member

Choose a reason for hiding this comment

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

again, wrong place. Also, needs a PR link.

Comment on lines +366 to +379
if sender != self.user_id() {
// Ignore if sent from a different user
error!(?sender, "Received secret push from a different user");
return Ok(());
}
let Some(device) = self.inner.store.get_device_from_curve_key(sender, *sender_key).await?
else {
error!(?sender, ?sender_key, "Received secret push from unknown device");
return Ok(());
};
if !device.is_verified() {
error!(?sender, device_id = ?device.device_id(), "Received secret push from unverified device");
return Ok(());
}
Copy link
Member

Choose a reason for hiding this comment

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

I think these should be warnings rather than errors, since they can be caused by other users or devices doing unexpected things, rather than necessarily reflecting an internal error on our side?

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.

add support for pushing secrets

2 participants