From e8522049ecf8fbd35fe1cc79c29526a5e560ea14 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 23 Mar 2026 16:17:32 +0100 Subject: [PATCH] Add security warning on loading untrusted data --- fints/client.py | 12 +++++++++++- fints/dialog.py | 3 +++ fints/utils.py | 3 +++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/fints/client.py b/fints/client.py index 7e0898a..213972a 100644 --- a/fints/client.py +++ b/fints/client.py @@ -102,6 +102,7 @@ class NeedRetryResponse(SubclassesMixin, metaclass=ABCMeta): @classmethod def from_data(cls, blob): """Restore an object instance from a compressed datablob. + `blob` **MUST NOT** be from an untrusted source. Returns an instance of a concrete subclass.""" version, data = decompress_datablob(DATA_BLOB_MAGIC_RETRY, blob) @@ -334,6 +335,7 @@ class FinTS3Client: def set_data(self, blob: bytes): """Restore a datablob created with deconstruct(). + `blob` **MUST NOT** be from an untrusted source. You should only call this method once, and only immediately after constructing the object and before calling any other method or functionality (e.g. __enter__()). @@ -1080,6 +1082,9 @@ class FinTS3Client: client.send_tan(...) # Exiting the context here ends the dialog, unless frozen with pause_dialog() again. + + **Warning:** `dialog_data` **MUST NOT** be stored in a place where an untrusted user could + modify it or you will have a major security issue. """ if not self._standing_dialog: raise Exception("Cannot pause dialog, no standing dialog exists") @@ -1087,7 +1092,12 @@ class FinTS3Client: @contextmanager def resume_dialog(self, dialog_data): - # FIXME document, test, NOTE NO UNTRUSTED SOURCES + """ + Create a dialog based on the data of a previous dialog. + + **Warning:** `dialog_data` **MUST NOT** be from an untrusted source such as user-controlled + or client-side state or you will have a major security issue. + """ if self._standing_dialog: raise Exception("Cannot resume dialog, existing standing dialog") self._standing_dialog = FinTSDialog.create_resume(self, dialog_data) diff --git a/fints/dialog.py b/fints/dialog.py index e1f66aa..7fda0c8 100644 --- a/fints/dialog.py +++ b/fints/dialog.py @@ -227,6 +227,9 @@ class FinTSDialog: @classmethod def create_resume(cls, client, blob): + """ + `blob` **MUST NOT** be from an untrusted source. + """ retval = cls(client=client) decompress_datablob(DATA_BLOB_MAGIC, blob, retval) return retval diff --git a/fints/utils.py b/fints/utils.py index a3e101d..f02edb6 100644 --- a/fints/utils.py +++ b/fints/utils.py @@ -43,6 +43,9 @@ def compress_datablob(magic: bytes, version: int, data: dict): def decompress_datablob(magic: bytes, blob: bytes, obj: object = None): + """ + `blob` **MUST NOT** be from an untrusted source. + """ if not blob.startswith(magic): raise ValueError("Incorrect data blob") s = blob.split(b';', 3) -- 2.47.3