Dmytro Struk explains recent encoding changes in Semantic Kernel, showing developers how to securely handle template arguments in .NET and Python. The article includes practical guidance and code examples.

Stricter Encoding Rules for Template Arguments in Semantic Kernel

Semantic Kernel’s latest release changes how template argument encoding works. Previously, if a template argument was a simple string, encoding was performed automatically. However, for complex or custom types (objects, collections, anonymous types), encoding was skipped, which could potentially introduce security vulnerabilities.

What Changed?

  • Automatic encoding is now stricter: Passing complex types with automatic encoding enabled (the default) throws an exception.
  • This enforces secure template usage—developers must manually encode complex type properties and explicitly allow ‘dangerous’ content when they have sufficiently sanitized input.
  • The update applies to both the .NET and Python SDKs for Semantic Kernel, impacting scenarios where templating engines like Handlebars and Liquid are used.

Why This Matters

  • Security: Automatic encoding for strings helps prevent template injection. For complex types, automatic processing could have missed nested properties, leading to risks. Now, the SDK strictly requires the developer to handle encoding manually for these cases.

Upgrading Your Code

.NET Example (Before)

var arguments = new KernelArguments()
{
    { "customer", new { firstName = userInput.FirstName, lastName = userInput.LastName } }
};

var templateFactory = new LiquidPromptTemplateFactory();
var promptTemplateConfig = new PromptTemplateConfig() { TemplateFormat = "liquid" };
var promptTemplate = templateFactory.Create(promptTemplateConfig);
var renderedPrompt = await promptTemplate.RenderAsync(kernel, arguments); // Now throws exception

.NET Example (After)

var arguments = new KernelArguments()
{
    { "customer", new {
        firstName = HttpUtility.HtmlEncode(userInput.FirstName),
        lastName = HttpUtility.HtmlEncode(userInput.LastName),
    } }
};

var promptTemplateConfig = new PromptTemplateConfig()
{
    TemplateFormat = "liquid",
    InputVariables = new() {
        new() { Name = "customer", AllowDangerouslySetContent = true },
    }
};
var templateFactory = new LiquidPromptTemplateFactory();
var promptTemplate = templateFactory.Create(promptTemplateConfig);
var renderedPrompt = await promptTemplate.RenderAsync(kernel, arguments); // No exception

Python Example (Before)

arguments = {
    "customer": {
        "first_name": user_input.first_name,
        "last_name": user_input.last_name,
    }
}
prompt_template_config = PromptTemplateConfig(template_format="handlebars")
prompt_template = HandlebarsPromptTemplate(prompt_template_config=prompt_template_config)
rendered_prompt = await prompt_template.render(kernel, arguments) # Now throws exception

Python Example (After)

arguments = {
    "customer": {
        "first_name": escape(user_input.first_name),
        "last_name": escape(user_input.last_name),
    }
}
prompt_template_config = PromptTemplateConfig(
    template=template,
    template_format="handlebars",
    input_variables=[InputVariable(name="customer", allow_dangerously_set_content=True)],
)
prompt_template = HandlebarsPromptTemplate(prompt_template_config=prompt_template_config)
rendered_prompt = await prompt_template.render(kernel, arguments) # No exception

Key steps:

  1. Manually encode user input or property values before passing them as arguments.
  2. Set AllowDangerouslySetContent = true (or equivalent) for any variable where you handle encoding yourself.
  3. Test template outputs to confirm correct encoding and behavior with your data.

Summary

The Semantic Kernel SDK now enforces manual encoding for complex template arguments, raising runtime exceptions when unsafe patterns are detected. Developers must explicitly sanitize input and configure template variables to permit this, greatly improving the security posture of applications leveraging Semantic Kernel.

Find more guidance in the official documentation or join the GitHub discussions for community support and feedback.

This post appeared first on “Microsoft Semantic Kernel Blog”. Read the entire article here