Skip to content
ISSUE 001·LIVE·12:59 IL
← Journal/2026-11-04·8 min·semantic kernel

Semantic Kernel Python 1.46.0: Tool Authorization Docs, Template Trust and Pinned DNS in HttpPlugin

Semantic Kernel Python 1.46.0 mixes security fixes with documentation that says out loud what its function filters do not do. I read the release notes, the pull requests and the README at the tag to see what changed and what still falls on your application.

By Harel Asaf·AI Builder·Tel Aviv

Semantic Kernel Python 1.46.0 is mostly a hardening release. The most useful part may be a README section that says something many tool-calling guides skip: a function allowlist chooses which tools the model can pick, and it does not authorize anything. The release also pins HttpPlugin requests to validated DNS addresses, rejects dot segments in session upload paths, and stops logging function argument values.

I read the python-1.46.0 release notes (published October 28, 2026), seven pull requests they list, and the Python README at that tag. I did not install the package or run any of the code. Everything below is what those documents say.

The README section on tool authorization

Pull request 14647 adds a "Tool invocation and authorization" section to the Python README. It is documentation only. The PR says existing filtered dispatch already rejects non-member functions before invocation and that no new mechanism is introduced. The README text at the tag makes these points:

  • Model-generated function calls and arguments are untrusted input. Prompts, function descriptions and the model's decision to call a tool are not authorization controls.
  • FunctionChoiceBehavior.Auto() without filters makes all functions registered in the kernel available for automatic invocation. Register only what the task needs, or use an explicit nonempty allowlist with included_functions, using the PluginName-function_name format.
  • An empty inclusion list is not deny-all. Empty lists do not restrict function selection.
  • With filters set, the automatic invocation path checks the requested function against the filtered kernel metadata. The README says this is not a snapshot of the tools sent to the model, so keep registered functions and filters unchanged during a request.
  • Filters restrict selection. They do not check data access or whether an operation is allowed for a given user. Those checks belong in the function or in a function invocation filter.
  • An automatic function invocation filter can decline a call by not calling next(context). Setting context.terminate after await next(context) stops later processing but does not undo the call.
  • For approval before execution, use Auto(auto_invoke=False, filters=...), then inspect and authorize each returned call. If you call Kernel.invoke_function_call yourself, pass the same behavior as function_behavior. Omitting it skips name filtering, and passing execution_settings alone does not enable it.

The empty-list point is the one I would test first in my own code. A config that builds the list from user roles could end up with an empty list and quietly allow everything. That is my reading of the README, not something I ran.

The prompt template trust boundary

Pull request 14648 is also documentation, with one regression test. Its description says template source can invoke functions registered in the Kernel during rendering, and that this was not explicit before. The change documents that:

  • Template source must be trusted, because function expressions run before the model request.
  • Untrusted text should be passed as template arguments, not spliced into template source.
  • Content-escaping settings do not disable template function execution.

The new test shows template-like syntax passed as an argument is rendered literally and does not call a registered plugin function. The PR says no runtime behavior or defaults change.

HttpPlugin and DNS pinning

Pull request 14649 (merged October 23) describes a gap in HttpPlugin. It validated the DNS addresses of allow-listed hosts before sending a request, then discarded them. The HTTP transport could resolve the hostname again at connection time. The fix keeps the validated IPv4 and IPv6 addresses and gives aiohttp a host-scoped resolver that returns only those. The original URL is kept, so Host headers, TLS SNI and certificate checks still use the hostname. It applies to GET, POST, PUT and DELETE. Literal IP URLs and the explicit allow_all_domains and allow_private_network_access opt-ins behave as before.

The PR says tests cover every method and include a real connection test showing a later hostname lookup is not used. I did not read the tests.

Session upload paths

Pull request 14563 (merged October 16) fixes SessionsPythonTool.upload_file in Python. Download already rejected . and .. path segments in the remote name, but upload only added a /mnt/data/ prefix. A model-supplied remote_file_path such as one with parent-directory segments would be sent to the sessions service as given. The fix reuses the same guard in the shared helper, with the same exception type.

The PR notes that the existing local-side check on upload directories does not cover this, because the remote name is a string chosen by the model. Pull request 14646 applies a similar rule to the .NET plugin, and also handles backslashes, rooted names, drive prefixes and UNC paths.

Logging without argument values

Pull request 14574 (merged October 12) says function invocation diagnostics used to include full argument, result or exception values at INFO, DEBUG or ERROR level. Now automatic invocation logs the function identity at INFO without argument values, and logs argument counts, result presence and error type in place of the values. Raw exception details stay in function spans only when sensitive diagnostics are explicitly enabled.

If your tool arguments hold user data, this is a real change in what your logs contain. If you relied on those logs to debug, you will need sensitive diagnostics turned on.

A .NET change in the same notes

Pull request 14504 bounds element nesting depth in the .NET XML prompt parser at 64. The PR says parse work grew with nesting depth times prompt size. Over-limit prompts take the existing invalid-XML path and are sent as one user text message. It is in this release's notes even though it is a .NET change, which is a reminder that the notes cover more than the Python package.

What I would check

These are my untested suggestions.

  • Search for FunctionChoiceBehavior.Auto() calls with no filters, and for any filter list built at runtime that could be empty.
  • Check whether any template source is built from user, file or network text. Move that text into arguments.
  • If you use HttpPlugin with allow-listed hosts, keep your allow list explicit and avoid the unrestricted opt-ins.
  • If you parse logs from function calls, look for argument values you depended on.
  • If you use the sessions plugin, keep the remote path under your control and do not accept model-chosen path strings without checks of your own.

What I would not conclude

  • That filters make tool calling safe. The README says they do not authorize access.
  • That these fixes cover every plugin. I read the changes to HttpPlugin and the sessions plugin only.
  • That the release notes are only about Python. They include .NET and CI changes.

Frequently asked questions

What does included_functions do in Semantic Kernel?

It limits which functions function choice can select, using the PluginName-function_name format. The README says it is not an authorization control.

Does an empty included_functions list block everything?

No. The README says empty lists do not restrict function selection.

Can prompt template text call my plugins?

Per pull request 14648, template source can invoke functions registered in the kernel during rendering. Pass untrusted text as arguments.

Does escaping stop template functions from running?

The documentation added in that PR says content-escaping settings do not disable template function execution.

What changed in HttpPlugin?

Validated DNS addresses are now pinned for the connection, so the transport does not resolve the hostname again. The hostname is kept for Host headers and TLS checks.

Are function arguments still logged?

Per pull request 14574, automatic invocation logs function identity without argument values at INFO, and counts and error types in place of values. Raw exception details go in spans only when sensitive diagnostics are enabled.

Did you run it?

No. I read the release notes, pull requests and README. I did not install or run Semantic Kernel.

Sources

All read on November 4, 2026.

Not read: the code and tests behind these pull requests, the remaining fixes in the release notes, and the .NET release.

Related reading

The build log

Follow the work.

New essays and prototypes, in your feed reader. Email subscriptions are paused while I connect a working delivery service. No email is collected here.

Follow via RSS