From 1c106acf1034bdc08e9ec68cbf11aa0a3b92ad03 Mon Sep 17 00:00:00 2001 From: LilDojd Date: Tue, 19 Nov 2024 15:40:16 +0400 Subject: [PATCH] Forbid NULL byte in secret --- alchemiscale/security/auth.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/alchemiscale/security/auth.py b/alchemiscale/security/auth.py index 67a16e07..78c4ac0e 100644 --- a/alchemiscale/security/auth.py +++ b/alchemiscale/security/auth.py @@ -25,6 +25,10 @@ # this is deliberately higher than any reasonable key length # this is the same max size that `passlib` defaults to MAX_SECRET_SIZE = 4096 +# Bcrypt truncates the secret at first NULL it encounters. For this reason, +# passlib forbids NULL bytes in the secret. This is not necessary for backwards +# compatibility, but we follow passlib's lead. +_BNULL = b"\x00" class BcryptPasswordHandler(object): @@ -52,14 +56,16 @@ def verify(self, key: str, hashed_salted: str) -> bool: pwd_context = BcryptPasswordHandler() -def validate_secret(secret): +def validate_secret(secret: str): """ensure secret has correct type & size""" - if not isinstance(secret, (str, bytes)): - raise TypeError("secret must be a string or bytes") + if not isinstance(secret, str): + raise TypeError("secret must be a string") if len(secret) > MAX_SECRET_SIZE: raise ValueError( f"secret is too long, maximum length is {MAX_SECRET_SIZE} characters" ) + if _BNULL in secret.encode("utf-8"): + raise ValueError("secret contains NULL byte") def generate_secret_key():