diff --git a/packages/overlays/matrix-synapse/patches/0008-Add-option-to-allow-registrations-that-begin-with-_-.patch b/packages/overlays/matrix-synapse/patches/0008-Add-option-to-allow-registrations-that-begin-with-_-.patch
new file mode 100644
index 0000000..fa37022
--- /dev/null
+++ b/packages/overlays/matrix-synapse/patches/0008-Add-option-to-allow-registrations-that-begin-with-_-.patch
@@ -0,0 +1,116 @@
+From 44ae5362fd952dbb209f4b52ee9c96641163f032 Mon Sep 17 00:00:00 2001
+From: _ <x5f@fastmail.com>
+Date: Thu, 15 May 2025 04:31:52 -0700
+Subject: [PATCH 08/34] Add option to allow registrations that begin with '_'
+ (#18262)
+
+Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
+---
+ changelog.d/18262.feature | 1 +
+ .../configuration/config_documentation.md | 14 +++++++++++
+ synapse/config/registration.py | 4 ++++
+ synapse/handlers/register.py | 5 +++-
+ tests/handlers/test_register.py | 23 +++++++++++++++++++
+ 5 files changed, 46 insertions(+), 1 deletion(-)
+ create mode 100644 changelog.d/18262.feature
+
+diff --git a/changelog.d/18262.feature b/changelog.d/18262.feature
+new file mode 100644
+index 0000000000..c8249faa76
+--- /dev/null
++++ b/changelog.d/18262.feature
+@@ -0,0 +1 @@
++Add option to allow registrations that begin with `_`. Contributed by `_` (@hex5f).
+diff --git a/docs/usage/configuration/config_documentation.md b/docs/usage/configuration/config_documentation.md
+index 2228c18a6c..e688bc5cd8 100644
+--- a/docs/usage/configuration/config_documentation.md
++++ b/docs/usage/configuration/config_documentation.md
+@@ -2887,6 +2887,20 @@ Example configuration:
+ inhibit_user_in_use_error: true
+ ```
+ ---
++### `allow_underscore_prefixed_registration`
++
++Whether users are allowed to register with a underscore-prefixed localpart.
++By default, AppServices use prefixes like `_example` to namespace their
++associated ghost users. If turned on, this may result in clashes or confusion.
++Useful when provisioning users from an external identity provider.
++
++Defaults to false.
++
++Example configuration:
++```yaml
++allow_underscore_prefixed_registration: false
++```
++---
+ ## User session management
+ ---
+ ### `session_lifetime`
+diff --git a/synapse/config/registration.py b/synapse/config/registration.py
+index 3cf7031656..8adf21079e 100644
+--- a/synapse/config/registration.py
++++ b/synapse/config/registration.py
+@@ -162,6 +162,10 @@ class RegistrationConfig(Config):
+ "disable_msisdn_registration", False
+ )
+
++ self.allow_underscore_prefixed_localpart = config.get(
++ "allow_underscore_prefixed_localpart", False
++ )
++
+ session_lifetime = config.get("session_lifetime")
+ if session_lifetime is not None:
+ session_lifetime = self.parse_duration(session_lifetime)
+diff --git a/synapse/handlers/register.py b/synapse/handlers/register.py
+index ecfea175c7..3e86349981 100644
+--- a/synapse/handlers/register.py
++++ b/synapse/handlers/register.py
+@@ -159,7 +159,10 @@ class RegistrationHandler:
+ if not localpart:
+ raise SynapseError(400, "User ID cannot be empty", Codes.INVALID_USERNAME)
+
+- if localpart[0] == "_":
++ if (
++ localpart[0] == "_"
++ and not self.hs.config.registration.allow_underscore_prefixed_localpart
++ ):
+ raise SynapseError(
+ 400, "User ID may not begin with _", Codes.INVALID_USERNAME
+ )
+diff --git a/tests/handlers/test_register.py b/tests/handlers/test_register.py
+index 92487692db..dda389c08b 100644
+--- a/tests/handlers/test_register.py
++++ b/tests/handlers/test_register.py
+@@ -588,6 +588,29 @@ class RegistrationTestCase(unittest.HomeserverTestCase):
+ d = self.store.is_support_user(user_id)
+ self.assertFalse(self.get_success(d))
+
++ def test_underscore_localpart_rejected_by_default(self) -> None:
++ for invalid_user_id in ("_", "_prefixed"):
++ with self.subTest(invalid_user_id=invalid_user_id):
++ self.get_failure(
++ self.handler.register_user(localpart=invalid_user_id),
++ SynapseError,
++ )
++
++ @override_config(
++ {
++ "allow_underscore_prefixed_localpart": True,
++ }
++ )
++ def test_underscore_localpart_allowed_if_configured(self) -> None:
++ for valid_user_id in ("_", "_prefixed"):
++ with self.subTest(valid_user_id=valid_user_id):
++ user_id = self.get_success(
++ self.handler.register_user(
++ localpart=valid_user_id,
++ ),
++ )
++ self.assertEqual(user_id, f"@{valid_user_id}:test")
++
+ def test_invalid_user_id(self) -> None:
+ invalid_user_id = "^abcd"
+ self.get_failure(
+--
+2.49.0
+
|