Do not accept pattern_type from user input in push rules. (#15088)

Internally the push rules module uses a `pattern_type` property for `event_match`
conditions (and `related_event_match`) to mark the condition as matching the
current user's Matrix ID or localpart.

This is leaky to the Client-Server API where a user can successfully set a condition
which provides `pattern_type` instead of `pattern` (note that there's no benefit to
doing this -- the user can just use their own Matrix ID or localpart instead). When
serializing back to the client the `pattern_type` property is converted into a proper
`pattern`.

The following changes are made to avoid this:

* Separate the `KnownCondition::EventMatch` enum value into `EventMatch`
  and `EventMatchType`, each with their own expected properties. (Note that a
  similar change is made for `RelatedEventMatch`.)
* Make it such that the `pattern_type` variants serialize to the same condition kind,
  but cannot be deserialized (since they're only provided by base rules).
* As a final tweak, convert `user_id` vs. `user_localpart` values into an enum.
This commit is contained in:
Patrick Cloke 2023-02-28 10:11:20 -05:00 committed by GitHub
parent 521026897c
commit e746f80b4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 244 additions and 186 deletions

View file

@ -401,6 +401,33 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
"pattern should not match before a newline",
)
def test_event_match_pattern(self) -> None:
"""Check that event_match conditions do not use a "pattern_type" from user data."""
# The pattern_type should not be deserialized into anything valid.
condition = {
"kind": "event_match",
"key": "content.value",
"pattern_type": "user_id",
}
self._assert_not_matches(
condition,
{"value": "@user:test"},
"should not be possible to pass a pattern_type in",
)
# This is an internal-only condition which shouldn't get deserialized.
condition = {
"kind": "event_match_type",
"key": "content.value",
"pattern_type": "user_id",
}
self._assert_not_matches(
condition,
{"value": "@user:test"},
"should not be possible to pass a pattern_type in",
)
def test_exact_event_match_string(self) -> None:
"""Check that exact_event_match conditions work as expected for strings."""