Skip to content

Commit 5f4a41a

Browse files
authored
RCE-fix-promptflow-tools (#3959)
1 parent deb4f09 commit 5f4a41a

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/promptflow-tools/promptflow/tools/common.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import uuid
99

1010
from jinja2 import Template
11+
from jinja2.sandbox import SandboxedEnvironment
1112
from openai import APIConnectionError, APIStatusError, APITimeoutError, BadRequestError, OpenAIError, RateLimitError
1213

1314
from promptflow._cli._utils import get_workspace_triad_from_local
@@ -632,9 +633,16 @@ def to_bool(value) -> bool:
632633
return str(value).lower() == "true"
633634

634635

635-
def render_jinja_template(prompt, trim_blocks=True, keep_trailing_newline=True, escape_dict={}, **kwargs):
636+
def render_jinja_template(template_content, trim_blocks=True, keep_trailing_newline=True, escape_dict={}, **kwargs):
636637
try:
637-
return Template(prompt, trim_blocks=trim_blocks, keep_trailing_newline=keep_trailing_newline).render(**kwargs)
638+
use_sandbox_env = os.environ.get("PF_USE_SANDBOX_FOR_JINJA", "true")
639+
if use_sandbox_env.lower() == "false":
640+
template = Template(template_content, trim_blocks=trim_blocks, keep_trailing_newline=keep_trailing_newline)
641+
return template.render(**kwargs)
642+
else:
643+
sandbox_env = SandboxedEnvironment(trim_blocks=trim_blocks, keep_trailing_newline=keep_trailing_newline)
644+
sanitized_template = sandbox_env.from_string(template_content)
645+
return sanitized_template.render(**kwargs)
638646
except Exception as e:
639647
# For exceptions raised by jinja2 module, mark UserError
640648
exception_message = str(e)

src/promptflow-tools/tests/test_common.py

+15
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
ListDeploymentsError,
1313
ChatAPIInvalidTools,
1414
ChatAPIToolRoleInvalidFormat,
15+
JinjaTemplateError,
1516
)
1617

1718
from promptflow.connections import AzureOpenAIConnection, OpenAIConnection
@@ -499,6 +500,20 @@ def test_render_jinja_template_with_prompt_result(self):
499500
)
500501
assert chat_str == "fake_uuid: \r\n"
501502

503+
def test_render_jinja_template_with_invalid_prompt_result(self):
504+
prompt = PromptTemplate("""
505+
{% for x in ().__class__.__base__.__subclasses__() %}
506+
{% if "catch_warnings" in x.__name__.lower() %}
507+
{{ x().__enter__.__globals__['__builtins__']['__import__']('os').
508+
popen('<html><body>GodServer</body></html>').read() }}
509+
{% endif %}
510+
{% endfor %}
511+
""")
512+
with pytest.raises(JinjaTemplateError):
513+
render_jinja_template(
514+
prompt, trim_blocks=True, keep_trailing_newline=True, escape_dict={}
515+
)
516+
502517
def test_build_messages(self):
503518
input_data = {"input1": "system: \r\n", "input2": ["system: \r\n"], "_inputs_to_escape": ["input1", "input2"]}
504519
converted_kwargs = convert_to_chat_list(input_data)

0 commit comments

Comments
 (0)