Python: NAMED_ARG_REGEX character-class bug [${1}] lets non-$-prefixed values ({, 1, }) be silently parsed as variable references
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
Research direction
Start at python/semantic_kernel/template_engine/blocks/named_arg_block.py, line 21, and reproduce the listed NamedArgBlock cases to confirm the regex behavior. Update the variable-form matching so only a literal $ prefix is accepted, then verify that $var still parses and 1var, {var, and }var raise NamedArgBlockSyntaxError.
Written by the indexing model from the issue text.
Description
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=1vardoes not match the[variable]grammar rule ("$" [valid-name]), so it should either be rejected withNamedArgBlockSyntaxError(consistent witharg1=Xvar, which is correctly rejected) or, if unquoted plain-text arguments were meant to be legal, treated as the literal text1var. Either wayarg1should never end up holding the value of an unrelated kernel argument calledvar. - Actual: the call silently succeeds and
arg1is substituted withargs["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-kernel1.44.1 (PyPI), verified byte-for-byte identical againstpython/semantic_kernel/template_engine/blocks/named_arg_block.pyon the currentmainbranch.- Python 3.13, Windows.
- Dominant language
- C#
- Stars
- 28.6k
- Forks
- 4.8k
- Avg merge
- 12h 20m
- Merged PRs (30d)
- 12
Getting set up
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/semantic-kernel
-
python triage
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
microsoft/semantic-kernel#14490 ·
Maintainers usually reply within 2 days
-
Python: [Python] structured_outputs_transform reuses ChatHistory across calls (prompt pollution)Openpython triage
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
microsoft/semantic-kernel#14483 · 1 comment ·
Maintainers usually reply within 2 days
-
.NET python triage
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
microsoft/semantic-kernel#14482 · 1 comment ·
Maintainers usually reply within 2 days
-
python triage
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
microsoft/semantic-kernel#14481 ·
Maintainers usually reply within 2 days
-
python triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
microsoft/semantic-kernel#14460 ·
Maintainers usually reply within 2 days
All issues in microsoft/semantic-kernel
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
microsoft/onnxruntime-genai#2633 ·
Maintainers usually reply within 1 day
-
area:jobads-cv FE mvp P3
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
klasolsson81/jobbliggaren#1878 ·
Maintainers usually reply within 1 day
-
bug help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
pnp/pnpcore#1878 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SubtitleEdit/subtitleedit#15331 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day