如何在GitHub Actions中安全转义文本以填充Shell变量?
安全处理GitHub Action脚本中的变量,避免特殊字符报错
问题场景
我写了一个GitHub Action脚本,当PR的分支名称带有hotfix/前缀时,会给PR标题加上hotfix:前缀。但如果PR标题包含反引号、$、同类型引号等特殊字符,脚本会报错或出现异常行为(比如执行标题里的命令、替换环境变量)。请问在无法控制PR标题内容的情况下,如何安全地将GitHub Action变量插入到bash脚本中?
原脚本:
title="${{ github.event.pull_request.title }}" if [[ ${{ github.head_ref }} = hotfix/* ]] && [[ $title != hotfix:* ]]; then echo "Marking as hotfix." gh pr edit ${{ env.PR_NUMBER }} --title "hotfix: ${title}" fi
核心问题分析
原脚本的问题在于直接将GitHub模板变量插入bash代码,且未对特殊字符做安全处理:
- 条件判断中直接使用
${{ github.head_ref }},如果分支名称含空格、*等特殊字符,会触发shell语法错误。 --title "hotfix: ${title}"中的title如果包含反引号、$等,会被shell当作命令或环境变量解析,导致标题被篡改或脚本报错。
安全解决方案
方法1:bash变量+双引号包裹参数
将GitHub模板变量先赋值给bash变量,所有参数用双引号包裹,避免shell解析特殊字符:
# 安全赋值:用双引号包裹模板变量,避免分词和特殊字符提前解析 pr_title="${{ github.event.pull_request.title }}" head_ref="${{ github.head_ref }}" pr_number="${{ env.PR_NUMBER }}" # 用bash变量做条件判断,不要直接插入模板变量 if [[ "$head_ref" == hotfix/* && "$pr_title" != hotfix:* ]]; then echo "标记为hotfix类型PR" new_title="hotfix: $pr_title" # 双引号包裹所有参数,确保特殊字符被当作参数内容 gh pr edit "$pr_number" --title "$new_title" fi
方法2:数组传递命令参数(更可靠)
对于含复杂特殊字符的场景,用bash数组存储命令参数,确保每个参数被独立解析:
pr_title="${{ github.event.pull_request.title }}" head_ref="${{ github.head_ref }}" pr_number="${{ env.PR_NUMBER }}" if [[ "$head_ref" == hotfix/* && "$pr_title" != hotfix:* ]]; then echo "标记为hotfix类型PR" new_title="hotfix: $pr_title" # 将所有命令参数存入数组,每个元素作为独立参数 gh_command=(pr edit "$pr_number" --title "$new_title") # 执行命令,数组展开时自动处理特殊字符 "${gh_command[@]}" fi
方法3:GitHub toJSON函数转义(终极方案)
如果PR标题包含双引号、换行等极端特殊字符,用GitHub的toJSON函数将变量转成JSON字符串,再用jq解析回原始内容:
# 用toJSON将标题转成JSON格式,自动转义特殊字符 pr_title_json="${{ toJSON(github.event.pull_request.title) }}" # 用jq解析JSON,还原原始标题内容 pr_title=$(echo "$pr_title_json" | jq -r .) head_ref="${{ github.head_ref }}" pr_number="${{ env.PR_NUMBER }}" if [[ "$head_ref" == hotfix/* && "$pr_title" != hotfix:* ]]; then echo "标记为hotfix类型PR" new_title="hotfix: $pr_title" gh pr edit "$pr_number" --title "$new_title" fi
注意:使用此方法需要在Action中安装
jq工具(比如通过apt-get install jq或actions/setup-node附带安装)。
安全原则总结
- 所有GitHub模板变量赋值给bash变量时,必须用双引号包裹,避免分词和特殊字符被提前解析。
- 条件判断、命令参数中使用bash变量,而非直接插入模板变量,防止shell语法错误。
- 执行外部命令时,优先用数组传递参数或双引号包裹每个参数,确保特殊字符被当作参数内容而非shell命令的一部分。
内容的提问来源于stack exchange,提问作者bler
相关产品推荐
相关产品推荐

