diff --git a/src/hookrelay/config.py b/src/hookrelay/config.py index 978fa8c..a82f464 100644 --- a/src/hookrelay/config.py +++ b/src/hookrelay/config.py @@ -1,5 +1,6 @@ from __future__ import annotations +import hashlib import json from dataclasses import dataclass, field from pathlib import Path @@ -73,10 +74,15 @@ def _parse_signature(data: object, route_name: str) -> Signature | None: raise ConfigError(f"route {route_name!r}: signature must be an object") if not data.get("secret"): raise ConfigError(f"route {route_name!r}: signature.secret is required") + algorithm = str(data.get("algorithm", "sha256")) + if algorithm not in hashlib.algorithms_available: + raise ConfigError( + f"route {route_name!r}: unsupported signature.algorithm {algorithm!r}" + ) return Signature( secret=str(data["secret"]), header=str(data.get("header", "X-Hub-Signature-256")), - algorithm=str(data.get("algorithm", "sha256")), + algorithm=algorithm, prefix=str(data.get("prefix", "")), ) diff --git a/tests/test_config.py b/tests/test_config.py index 920a5bf..1576ed5 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -77,6 +77,20 @@ def test_signature_requires_secret(): parse_config(bad) +def test_signature_rejects_unsupported_algorithm(): + bad = { + "routes": [ + { + "name": "r", + "signature": {"secret": "shh", "algorithm": "sha265"}, + "sinks": [{"type": "slack", "url": "http://s"}], + } + ] + } + with pytest.raises(ConfigError): + parse_config(bad) + + def test_signature_parsed(): data = { "routes": [