我有一个yaml文件,我通过模板语言生成(在本例中为jinja2。)这是一个简单的片段:
services_to_install:
{% for service in services if service.install -%}
- {{ service.name }}
{% endfor -%}
user_data: |
#! /bin/bash
set -o errexit
/usr/local/bin/ansible-playbook -i 127.0.0.1, -c local /tmp/ansible/playbook.yml --extra-vars 'app={{ app }}'
我知道,例如,如果我让service.name
包含换行符,它可能会逃脱它应该包含的列表,并且可以编写任意yaml语法。所以我限制换行。
然而,我并不知道"代码注入"所有其他可能的滥用行为。 (即编写任意yaml语法)可能存在。抛开可能在运行时创建对象的语言特定标签,我还需要注意哪些其他事项?
换句话说,如何清理模板化yaml文件的输入,就像清理模板化html文件的输入一样?
P.S。我没有和一个模板引擎结婚,我对yaml语法更感兴趣。
编辑在我的示例中添加了一个块元素,因为我也使用了这些元素。
答案 0 :(得分:2)
最安全的做法是编写一个过滤字符串并将其放在双引号中的过滤器。 Here是YAML双引号标量样式中转义序列的完整列表。
话虽如此,如果你想把它写成普通的(即没有引用的)标量,让我们看一下被禁止的内容:
某些字符可能无法启动普通标量,因此不得在开头出现。这些被称为indicator characters,包括:
,
,[
,]
,{
,}
)'
,"
)!
,&
,*
)#
)%
)@
,`
)|
,>
,?
,:
,-
)。但是,?
,:
和-
如果没有空格,则允许。启动普通标量后,大多数字符都被允许。但是,某些字符将标记普通标量的结尾:
,
,[
,]
,{
,}
),但仅限于流式 :
)如果后跟空格。#
)如果前面有空格。请注意,尽管可以在标量中包含换行符(如果缩进处理正确),但这些换行符合line folding,因此,在使用此值之前,您需要将转换应用于原始值如果您希望将其解析为相同的值,请使用样式。
在文档中,字符序列---
和...
可能永远不会出现在行的开头(它们在其他地方都很好)因为它们表示结束当前的文件,也可能是新文件的开头。
普通标量没有转义机制,因此它们可以代表什么字符串受到限制。双引号标量是唯一能够表示所有可能字符串的表示形式,因此也是您想要的结果。
选择是将字符串表示为普通字符串还是引用标量通常是YAML实现的任务,因为决策制定很复杂且有许多警告。如果使用模板引擎生成YAML,则可能无法访问所有信息来做出决定 - 例如,当前缩进,状态(流式和块式)等。因此,为了安全起见,请使用过滤器转义特殊字符并使用双引号样式。