diff --git a/changelog.d/9499.misc b/changelog.d/9499.misc
new file mode 100644
index 0000000000000000000000000000000000000000..1513017a10f0f7e47cad7f75020783fb9a3b2f78
--- /dev/null
+++ b/changelog.d/9499.misc
@@ -0,0 +1 @@
+Introduce bugbear to the test suite and fix some of it's lint violations.
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index 5e301c2cd7d385a54a5c63010631a64b982bf613..920868df203e434cdaf4f356f49c576ffe30e896 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -18,7 +18,8 @@ ignore =
 #  E203: whitespace before ':' (which is contrary to pep8?)
 #  E731: do not assign a lambda expression, use a def
 #  E501: Line too long (black enforces this for us)
-ignore=W503,W504,E203,E731,E501
+#   B00: Subsection of the bugbear suite (TODO: add in remaining fixes)
+ignore=W503,W504,E203,E731,E501,B00
 
 [isort]
 line_length = 88
diff --git a/setup.py b/setup.py
index bbd9e7862a01217bee64969dd12f5ca5a842a2c4..b834e4e55bd271aeb266b39655d606cad601686a 100755
--- a/setup.py
+++ b/setup.py
@@ -99,6 +99,7 @@ CONDITIONAL_REQUIREMENTS["lint"] = [
     "isort==5.7.0",
     "black==20.8b1",
     "flake8-comprehensions",
+    "flake8-bugbear",
     "flake8",
 ]
 
diff --git a/synapse/app/__init__.py b/synapse/app/__init__.py
index 4a9b0129c328519dbb8f1176c0c215d403f70b6e..d1a2cd5e192b3d352d9632b15a5bd472bf9fab86 100644
--- a/synapse/app/__init__.py
+++ b/synapse/app/__init__.py
@@ -22,7 +22,9 @@ logger = logging.getLogger(__name__)
 try:
     python_dependencies.check_requirements()
 except python_dependencies.DependencyException as e:
-    sys.stderr.writelines(e.message)
+    sys.stderr.writelines(
+        e.message  # noqa: B306, DependencyException.message is a property
+    )
     sys.exit(1)
 
 
diff --git a/synapse/config/key.py b/synapse/config/key.py
index de964dff134075f7d0b1c215919f5f1da164c7b7..350ff1d6654c8cb73e6dd62afe968b5308c571ec 100644
--- a/synapse/config/key.py
+++ b/synapse/config/key.py
@@ -404,7 +404,11 @@ def _parse_key_servers(key_servers, federation_verify_certificates):
     try:
         jsonschema.validate(key_servers, TRUSTED_KEY_SERVERS_SCHEMA)
     except jsonschema.ValidationError as e:
-        raise ConfigError("Unable to parse 'trusted_key_servers': " + e.message)
+        raise ConfigError(
+            "Unable to parse 'trusted_key_servers': {}".format(
+                e.message  # noqa: B306, jsonschema.ValidationError.message is a valid attribute
+            )
+        )
 
     for server in key_servers:
         server_name = server["server_name"]
diff --git a/synapse/config/metrics.py b/synapse/config/metrics.py
index dfd27e152365816a8d468d2d912396579c9f8638..2b289f4208d0ea63b843b5f6353e47d2a6e17c2e 100644
--- a/synapse/config/metrics.py
+++ b/synapse/config/metrics.py
@@ -56,7 +56,9 @@ class MetricsConfig(Config):
             try:
                 check_requirements("sentry")
             except DependencyException as e:
-                raise ConfigError(e.message)
+                raise ConfigError(
+                    e.message  # noqa: B306, DependencyException.message is a property
+                )
 
             self.sentry_dsn = config["sentry"].get("dsn")
             if not self.sentry_dsn:
diff --git a/synapse/config/oidc_config.py b/synapse/config/oidc_config.py
index eab042a085f472054bbd4ad148e382a85a4c1f90..747ab9a7fe4eb87b882d41b97f6e2fd9772a9806 100644
--- a/synapse/config/oidc_config.py
+++ b/synapse/config/oidc_config.py
@@ -42,7 +42,9 @@ class OIDCConfig(Config):
         try:
             check_requirements("oidc")
         except DependencyException as e:
-            raise ConfigError(e.message) from e
+            raise ConfigError(
+                e.message  # noqa: B306, DependencyException.message is a property
+            ) from e
 
         # check we don't have any duplicate idp_ids now. (The SSO handler will also
         # check for duplicates when the REST listeners get registered, but that happens
diff --git a/synapse/config/repository.py b/synapse/config/repository.py
index 69d9de5a43154cc8b2c48cf80a8caa97535a2f15..061c4ec83fc72617fab9fff90453c2f4ccb0e30e 100644
--- a/synapse/config/repository.py
+++ b/synapse/config/repository.py
@@ -176,7 +176,9 @@ class ContentRepositoryConfig(Config):
                 check_requirements("url_preview")
 
             except DependencyException as e:
-                raise ConfigError(e.message)
+                raise ConfigError(
+                    e.message  # noqa: B306, DependencyException.message is a property
+                )
 
             if "url_preview_ip_range_blacklist" not in config:
                 raise ConfigError(
diff --git a/synapse/config/saml2_config.py b/synapse/config/saml2_config.py
index 4b494f217f647b5838bfba3893694a393a8a408f..6db9cb5ced3cf8280b1f3a5044432cb791384881 100644
--- a/synapse/config/saml2_config.py
+++ b/synapse/config/saml2_config.py
@@ -76,7 +76,9 @@ class SAML2Config(Config):
         try:
             check_requirements("saml2")
         except DependencyException as e:
-            raise ConfigError(e.message)
+            raise ConfigError(
+                e.message  # noqa: B306, DependencyException.message is a property
+            )
 
         self.saml2_enabled = True
 
diff --git a/synapse/config/tracer.py b/synapse/config/tracer.py
index 0c1a854f096bee632fc1b6b65ca5a78c88913605..727a1e700838e8df8a3c2365980a806faf3b2791 100644
--- a/synapse/config/tracer.py
+++ b/synapse/config/tracer.py
@@ -39,7 +39,9 @@ class TracerConfig(Config):
         try:
             check_requirements("opentracing")
         except DependencyException as e:
-            raise ConfigError(e.message)
+            raise ConfigError(
+                e.message  # noqa: B306, DependencyException.message is a property
+            )
 
         # The tracer is enabled so sanitize the config
 
diff --git a/synapse/crypto/context_factory.py b/synapse/crypto/context_factory.py
index 14b21796d9abd55bf56099d5ef10c0580f4bb7e5..4ca13011e54b1aa611c175c0797c70d621e1cb33 100644
--- a/synapse/crypto/context_factory.py
+++ b/synapse/crypto/context_factory.py
@@ -219,7 +219,7 @@ class SSLClientConnectionCreator:
         # ... and we also gut-wrench a '_synapse_tls_verifier' attribute into the
         # tls_protocol so that the SSL context's info callback has something to
         # call to do the cert verification.
-        setattr(tls_protocol, "_synapse_tls_verifier", self._verifier)
+        tls_protocol._synapse_tls_verifier = self._verifier
         return connection
 
 
diff --git a/tests/unittest.py b/tests/unittest.py
index ca7031c724b3821fbe50e39e91ab9b7e8e624af8..224f037ce170b1efca2be2708492404e2b7bb0c4 100644
--- a/tests/unittest.py
+++ b/tests/unittest.py
@@ -140,7 +140,7 @@ class TestCase(unittest.TestCase):
             try:
                 self.assertEquals(attrs[key], getattr(obj, key))
             except AssertionError as e:
-                raise (type(e))(e.message + " for '.%s'" % key)
+                raise (type(e))("Assert error for '.{}':".format(key)) from e
 
     def assert_dict(self, required, actual):
         """Does a partial assert of a dict.