From 5a3263d606c7e22e966a709659ded4bc00d8c95e Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Tue, 27 Oct 2026 16:37:05 +0100 Subject: [PATCH] Python: Reject bytes in prompt template argument encoding --- .../prompt_template/prompt_template_base.py | 2 +- .../test_prompt_template_e2e.py | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/python/semantic_kernel/prompt_template/prompt_template_base.py b/python/semantic_kernel/prompt_template/prompt_template_base.py index 4492a367fe1b..3fd020dcaad7 100644 --- a/python/semantic_kernel/prompt_template/prompt_template_base.py +++ b/python/semantic_kernel/prompt_template/prompt_template_base.py @@ -107,7 +107,7 @@ def _is_safe_type(self, value: Any) -> bool: from uuid import UUID # Check for primitive types - if isinstance(value, (int, float, bool, bytes)): + if isinstance(value, (int, float, bool)): return True # Check for date/time types diff --git a/python/tests/unit/prompt_template/test_prompt_template_e2e.py b/python/tests/unit/prompt_template/test_prompt_template_e2e.py index fc3a34917597..1c97fd861651 100644 --- a/python/tests/unit/prompt_template/test_prompt_template_e2e.py +++ b/python/tests/unit/prompt_template/test_prompt_template_e2e.py @@ -10,7 +10,9 @@ from semantic_kernel.exceptions import TemplateSyntaxError from semantic_kernel.functions import kernel_function from semantic_kernel.functions.kernel_arguments import KernelArguments +from semantic_kernel.prompt_template.handlebars_prompt_template import HandlebarsPromptTemplate from semantic_kernel.prompt_template.input_variable import InputVariable +from semantic_kernel.prompt_template.jinja2_prompt_template import Jinja2PromptTemplate from semantic_kernel.prompt_template.kernel_prompt_template import KernelPromptTemplate from semantic_kernel.prompt_template.prompt_template_config import PromptTemplateConfig @@ -239,6 +241,44 @@ async def test_renders_and_disallows_message_injection(kernel: Kernel): assert expected == result +@mark.parametrize( + ("prompt_template_type", "template", "template_format"), + [ + (KernelPromptTemplate, '{{$input}}', "semantic-kernel"), + (Jinja2PromptTemplate, '{{ input }}', "jinja2"), + (HandlebarsPromptTemplate, '{{input}}', "handlebars"), + ], +) +async def test_default_encoding_rejects_bytes_for_all_template_engines( + kernel: Kernel, prompt_template_type, template: str, template_format: str +): + target = prompt_template_type( + prompt_template_config=PromptTemplateConfig( + name="test", + template=template, + template_format=template_format, + ) + ) + unsafe_input = b'This is an injected system message' + + with raises(NotImplementedError, match="Argument 'input'"): + await target.render(kernel, KernelArguments(input=unsafe_input)) + + rendered = await target.render(kernel, KernelArguments(input=unsafe_input.decode())) + messages = ChatHistory.from_rendered_prompt(rendered).messages + + assert len(messages) == 1 + assert messages[0].role == AuthorRole.USER + assert messages[0].content == unsafe_input.decode() + + rendered = await target.render(kernel, KernelArguments(input=42)) + messages = ChatHistory.from_rendered_prompt(rendered).messages + + assert len(messages) == 1 + assert messages[0].role == AuthorRole.USER + assert messages[0].content == "42" + + async def test_renders_and_disallows_message_injection_from_specific_input(kernel: Kernel): system_message = "This is the system message" unsafe_input = "This is the newer system message"