Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Python: NAMED_ARG_REGEX character-class bug [${1}] lets non-$-prefixed values ({, 1, }) be silently parsed as variable references

オープン 初心者向け
#14,491 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
85/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
backend

調査の方向性

python/semantic_kernel/template_engine/blocks/named_arg_block.py の21行目から始め、列挙されている NamedArgBlock のケースを再現して正規表現の動作を確認してください。変数形式のマッチングを更新し、リテラルの $ プレフィックスだけが受け入れられるようにしてから、$var は引き続きパースされ、1var、{var、}var は NamedArgBlockSyntaxError を発生させることを確認してください。

索引モデルが issue の本文から書いたものです。

説明

python triage

What happens

NamedArgBlock's parsing regex, NAMED_ARG_REGEX, is supposed to require a named argument's variable form to start with a literal $ (per the grammar: [parameter] ::= [variable] | [value] and [variable] ::= "$" [valid-name]). Because of a regex mistake, it instead accepts a variable reference whose first character is $, {, 1, or } and always treats the rest as the variable name, silently dropping that first character. This means unquoted, non-$-prefixed argument text that starts with 1, {, or } is silently reinterpreted as a variable substitution instead of raising a syntax error, and the value actually used at render time comes from an unrelated kernel argument instead of the text the template author wrote.

Where

python/semantic_kernel/template_engine/blocks/named_arg_block.py, line 21:

NAMED_ARG_REGEX = r"^(?P<name>[0-9A-Za-z_]+)[=]{1}(?P<value>[${1}](?P<var_name>[0-9A-Za-z_]+)|(?P<quote>[\"'])(?P<val>.[^\"^']*)(?P=quote))$"

The variable-form alternative is [${1}](?P<var_name>...). Inside a character class, {1} is not a quantifier, it is three literal characters {, 1, }. So [${1}] is a 4-character class matching any one of $, {, 1, } — not "a literal $, exactly once" as the {1} clearly was intended to express (that would need to be written outside the brackets, e.g. \$ or [$]).

Why

Confirmed directly against the regex and the real class, on semantic-kernel==1.44.1 (byte-identical to current main for this file):

from semantic_kernel.template_engine.blocks.named_arg_block import NamedArgBlock

for content in ["arg1=$var", "arg1={var", "arg1=1var", "arg1=}var"]:
    b = NamedArgBlock(content=content)
    print(content, "-> name=", b.name, "variable=", b.variable)

Output:

arg1=$var -> name= arg1 variable= content='$var' name='var'
arg1={var -> name= arg1 variable= content='{var' name='var'
arg1=1var -> name= arg1 variable= content='1var' name='var'
arg1=}var -> name= arg1 variable= content='}var' name='var'

All four are accepted and all four produce a VarBlock pointing at the variable named var, even though only the first one actually starts with $. The {, 1, and } prefixes are silently swallowed instead of causing a NamedArgBlockSyntaxError (which is what happens for any other non-$/non-quote prefix, e.g. arg1=Xvar is correctly rejected).

Full end-to-end repro (real rendering, not just the regex)

import asyncio
from semantic_kernel import Kernel
from semantic_kernel.functions.kernel_arguments import KernelArguments
from semantic_kernel.functions.kernel_function_decorator import kernel_function
from semantic_kernel.prompt_template.kernel_prompt_template import KernelPromptTemplate
from semantic_kernel.prompt_template.prompt_template_config import PromptTemplateConfig

class MyPlugin:
    @kernel_function(name="echo")
    def echo(self, arg1: str) -> str:
        return f"GOT[{arg1}]"

kernel = Kernel()
kernel.add_plugin(MyPlugin(), plugin_name="my")

async def main():
    args = KernelArguments(var="SECRET_VALUE")
    template_str = "{{ my.echo arg1=1var }}"   # arg1 is meant to be the literal text "1var"
    tpl = KernelPromptTemplate(prompt_template_config=PromptTemplateConfig(template=template_str))
    print(await tpl.render(kernel, args))

asyncio.run(main())

Output:

GOT[SECRET_VALUE]

Expected vs actual

  • Expected: arg1=1var does not match the [variable] grammar rule ("$" [valid-name]), so it should either be rejected with NamedArgBlockSyntaxError (consistent with arg1=Xvar, which is correctly rejected) or, if unquoted plain-text arguments were meant to be legal, treated as the literal text 1var. Either way arg1 should never end up holding the value of an unrelated kernel argument called var.
  • Actual: the call silently succeeds and arg1 is substituted with args["var"] ("SECRET_VALUE"), not the text the template author wrote. The same happens for any unquoted, non-quoted value that happens to start with { or }.

Suggested fix

Move the quantifier out of the character class so only a literal $ starts the variable form, e.g.:

NAMED_ARG_REGEX = r"^(?P<name>[0-9A-Za-z_]+)=(?P<value>\$(?P<var_name>[0-9A-Za-z_]+)|(?P<quote>[\"'])(?P<val>.[^\"^']*)(?P=quote))$"

Environment

  • semantic-kernel 1.44.1 (PyPI), verified byte-for-byte identical against python/semantic_kernel/template_engine/blocks/named_arg_block.py on the current main branch.
  • Python 3.13, Windows.
主要言語
C#
スター
28.6k
フォーク
4.8k
平均マージ
12時間 20分
マージ済み PR(30日)
12

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

microsoft/semantic-kernel のほかの issue

microsoft/semantic-kernel の issue をすべて見る

似ている issue

C# の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。