mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-07-07 12:56:24 +02:00
Compare commits
No commits in common. "2e0bb01595be5a7921fe799526bb5f6445715305" and "2ccbd7d60b12c9c9d65bde027f4c974665022b28" have entirely different histories.
2e0bb01595
...
2ccbd7d60b
5 changed files with 1 additions and 175 deletions
63
SECURITY.md
63
SECURITY.md
|
@ -1,63 +0,0 @@
|
||||||
# Security Policy for Continuwuity
|
|
||||||
|
|
||||||
This document outlines the security policy for Continuwuity. Our goal is to maintain a secure platform for all users, and we take security matters seriously.
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
We provide security updates for the following versions of Continuwuity:
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| -------------- |:----------------:|
|
|
||||||
| Latest release | ✅ |
|
|
||||||
| Main branch | ✅ |
|
|
||||||
| Older releases | ❌ |
|
|
||||||
|
|
||||||
We may backport fixes to the previous release at our discretion, but we don't guarantee this.
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
### Responsible Disclosure
|
|
||||||
|
|
||||||
We appreciate the efforts of security researchers and the community in identifying and reporting vulnerabilities. To ensure that potential vulnerabilities are addressed properly, please follow these guidelines:
|
|
||||||
|
|
||||||
1. Contact members of the team over E2EE private message.
|
|
||||||
- [@jade:ellis.link](https://matrix.to/#/@jade:ellis.link)
|
|
||||||
- [@nex:nexy7574.co.uk](https://matrix.to/#/@nex:nexy7574.co.uk) <!-- ? -->
|
|
||||||
2. **Email the security team** directly at [security@continuwuity.org](mailto:security@continuwuity.org). This is not E2EE, so don't include sensitive details.
|
|
||||||
3. **Do not disclose the vulnerability publicly** until it has been addressed
|
|
||||||
4. **Provide detailed information** about the vulnerability, including:
|
|
||||||
- A clear description of the issue
|
|
||||||
- Steps to reproduce
|
|
||||||
- Potential impact
|
|
||||||
- Any possible mitigations
|
|
||||||
- Version(s) affected, including specific commits if possible
|
|
||||||
|
|
||||||
If you have any doubts about a potential security vulnerability, contact us via private channels first! We'd prefer that you bother us, instead of having a vulnerability disclosed without a fix.
|
|
||||||
|
|
||||||
### What to Expect
|
|
||||||
|
|
||||||
When you report a security vulnerability:
|
|
||||||
|
|
||||||
1. **Acknowledgment**: We will acknowledge receipt of your report.
|
|
||||||
2. **Assessment**: We will assess the vulnerability and determine its impact on our users
|
|
||||||
3. **Updates**: We will provide updates on our progress in addressing the vulnerability, and may request you help test mitigations
|
|
||||||
4. **Resolution**: Once resolved, we will notify you and discuss coordinated disclosure
|
|
||||||
5. **Credit**: We will recognize your contribution (unless you prefer to remain anonymous)
|
|
||||||
|
|
||||||
## Security Update Process
|
|
||||||
|
|
||||||
When security vulnerabilities are identified:
|
|
||||||
|
|
||||||
1. We will develop and test fixes in a private branch
|
|
||||||
2. Security updates will be released as soon as possible
|
|
||||||
3. Release notes will include information about the vulnerabilities, avoiding details that could facilitate exploitation where possible
|
|
||||||
4. Critical security updates may be backported to the previous stable release
|
|
||||||
|
|
||||||
## Additional Resources
|
|
||||||
|
|
||||||
- [Matrix Security Disclosure Policy](https://matrix.org/security-disclosure-policy/)
|
|
||||||
- [Continuwuity Documentation](https://continuwuity.org/introduction)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
This security policy was last updated on May 25, 2025.
|
|
|
@ -20,4 +20,3 @@
|
||||||
- [Testing](development/testing.md)
|
- [Testing](development/testing.md)
|
||||||
- [Hot Reloading ("Live" Development)](development/hot_reload.md)
|
- [Hot Reloading ("Live" Development)](development/hot_reload.md)
|
||||||
- [Community (and Guidelines)](community.md)
|
- [Community (and Guidelines)](community.md)
|
||||||
- [Security](security.md)
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
{{#include ../SECURITY.md}}
|
|
|
@ -2162,109 +2162,6 @@ async fn knock_room_by_id_helper(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For knock_restricted rooms, check if the user meets the restricted conditions
|
|
||||||
// If they do, attempt to join instead of knock
|
|
||||||
// This is not mentioned in the spec, but should be allowable (we're allowed to
|
|
||||||
// auto-join invites to knocked rooms)
|
|
||||||
let join_rule = services.rooms.state_accessor.get_join_rules(room_id).await;
|
|
||||||
if let JoinRule::KnockRestricted(restricted) = &join_rule {
|
|
||||||
let restriction_rooms: Vec<_> = restricted
|
|
||||||
.allow
|
|
||||||
.iter()
|
|
||||||
.filter_map(|a| match a {
|
|
||||||
| AllowRule::RoomMembership(r) => Some(&r.room_id),
|
|
||||||
| _ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Check if the user is in any of the allowed rooms
|
|
||||||
let mut user_meets_restrictions = false;
|
|
||||||
for restriction_room_id in &restriction_rooms {
|
|
||||||
if services
|
|
||||||
.rooms
|
|
||||||
.state_cache
|
|
||||||
.is_joined(sender_user, restriction_room_id)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
user_meets_restrictions = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user meets the restrictions, try joining instead
|
|
||||||
if user_meets_restrictions {
|
|
||||||
debug_info!(
|
|
||||||
"{sender_user} meets the restricted criteria in knock_restricted room \
|
|
||||||
{room_id}, attempting to join instead of knock"
|
|
||||||
);
|
|
||||||
// For this case, we need to drop the state lock and get a new one in
|
|
||||||
// join_room_by_id_helper We need to release the lock here and let
|
|
||||||
// join_room_by_id_helper acquire it again
|
|
||||||
drop(state_lock);
|
|
||||||
match join_room_by_id_helper(
|
|
||||||
services,
|
|
||||||
sender_user,
|
|
||||||
room_id,
|
|
||||||
reason.clone(),
|
|
||||||
servers,
|
|
||||||
None,
|
|
||||||
&None,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
| Ok(_) => return Ok(knock_room::v3::Response::new(room_id.to_owned())),
|
|
||||||
| Err(e) => {
|
|
||||||
debug_warn!(
|
|
||||||
"Failed to convert knock to join for {sender_user} in {room_id}: {e:?}"
|
|
||||||
);
|
|
||||||
// Get a new state lock for the remaining knock logic
|
|
||||||
let new_state_lock = services.rooms.state.mutex.lock(room_id).await;
|
|
||||||
|
|
||||||
let server_in_room = services
|
|
||||||
.rooms
|
|
||||||
.state_cache
|
|
||||||
.server_in_room(services.globals.server_name(), room_id)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let local_knock = server_in_room
|
|
||||||
|| servers.is_empty()
|
|
||||||
|| (servers.len() == 1 && services.globals.server_is_ours(&servers[0]));
|
|
||||||
|
|
||||||
if local_knock {
|
|
||||||
knock_room_helper_local(
|
|
||||||
services,
|
|
||||||
sender_user,
|
|
||||||
room_id,
|
|
||||||
reason,
|
|
||||||
servers,
|
|
||||||
new_state_lock,
|
|
||||||
)
|
|
||||||
.boxed()
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
knock_room_helper_remote(
|
|
||||||
services,
|
|
||||||
sender_user,
|
|
||||||
room_id,
|
|
||||||
reason,
|
|
||||||
servers,
|
|
||||||
new_state_lock,
|
|
||||||
)
|
|
||||||
.boxed()
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(knock_room::v3::Response::new(room_id.to_owned()));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if !matches!(join_rule, JoinRule::Knock | JoinRule::KnockRestricted(_)) {
|
|
||||||
debug_warn!(
|
|
||||||
"{sender_user} attempted to knock on room {room_id} but its join rule is \
|
|
||||||
{join_rule:?}, not knock or knock_restricted"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let server_in_room = services
|
let server_in_room = services
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
|
@ -2312,12 +2209,6 @@ async fn knock_room_helper_local(
|
||||||
return Err!(Request(Forbidden("This room does not support knocking.")));
|
return Err!(Request(Forbidden("This room does not support knocking.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that this room has a valid knock or knock_restricted join rule
|
|
||||||
let join_rule = services.rooms.state_accessor.get_join_rules(room_id).await;
|
|
||||||
if !matches!(join_rule, JoinRule::Knock | JoinRule::KnockRestricted(_)) {
|
|
||||||
return Err!(Request(Forbidden("This room's join rule does not allow knocking.")));
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = RoomMemberEventContent {
|
let content = RoomMemberEventContent {
|
||||||
displayname: services.users.displayname(sender_user).await.ok(),
|
displayname: services.users.displayname(sender_user).await.ok(),
|
||||||
avatar_url: services.users.avatar_url(sender_user).await.ok(),
|
avatar_url: services.users.avatar_url(sender_user).await.ok(),
|
||||||
|
|
|
@ -638,7 +638,7 @@ fn valid_membership_change(
|
||||||
warn!(?target_user_membership_event_id, "Banned user can't join");
|
warn!(?target_user_membership_event_id, "Banned user can't join");
|
||||||
false
|
false
|
||||||
} else if (join_rules == JoinRule::Invite
|
} else if (join_rules == JoinRule::Invite
|
||||||
|| room_version.allow_knocking && (join_rules == JoinRule::Knock || matches!(join_rules, JoinRule::KnockRestricted(_))))
|
|| room_version.allow_knocking && join_rules == JoinRule::Knock)
|
||||||
// If the join_rule is invite then allow if membership state is invite or join
|
// If the join_rule is invite then allow if membership state is invite or join
|
||||||
&& (target_user_current_membership == MembershipState::Join
|
&& (target_user_current_membership == MembershipState::Join
|
||||||
|| target_user_current_membership == MembershipState::Invite)
|
|| target_user_current_membership == MembershipState::Invite)
|
||||||
|
|
Loading…
Add table
Reference in a new issue