以下的要求不是强制性的, 未按模板评论时对issue无任何影响
issue处理注意事项:
1. 当前issue受影响的分支提交pr时, 须在pr描述中填写当前issue编号进行关联, 否则无法关闭当前issue;
2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容,未引入的分支不需要填写, 否则无法关闭当前issue;
3. 以下为模板中需要填写完整的内容, 请复制到评论区回复, 注: 内容的标题名称(影响性分析说明, 缺陷严重等级, 受影响版本排查(受影响/不受影响), 修复是否涉及abi变化(是/否))不能省略,省略后defect-manager将无法正常解析填写内容.
评论区可能使用到的指令说明:
| 指令 | 指令说明 | 使用权限 |
|---|---|---|
| /check-issue | 触发defect-manager校验 | 不限 |
| /reason xxx | /reason +挂起或取消条件 | 不限 |
影响性分析说明:
缺陷严重等级:(Critical/High/Moderate/Low)
缺陷根因说明:
受影响版本排查(受影响/不受影响):
- openEuler-20.03-LTS-SP4:
- openEuler-22.03-LTS-SP4:
- openEuler-24.03-LTS-SP1:
- openEuler-24.03-LTS-SP3:
- openEuler-24.03-LTS-SP4:
abi变化(是/否):
- openEuler-20.03-LTS-SP4:
- openEuler-22.03-LTS-SP4:
- openEuler-24.03-LTS-SP1:
- openEuler-24.03-LTS-SP3:
- openEuler-24.03-LTS-SP4:
缺陷issue处理具体操作请参考:
https://atomgit.com/openeuler/cve-manager/blob/master/cve-vulner-manager/doc/md/defect-manager-manual.md
pr关联issue具体操作请参考:
https://docs.atomgit.com/docs/help/home/org_project/pullrequests/pr-related-issue


Welcome To openEuler Community
Hey @yangna1310 , thanks for your contribution to the community.
Bot Usage Manual
I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands. You can self-configure the PR merge rules for this repository. For more details, please refer to Here.
Contact Guide
If you have any questions, please contact the SIG: sig-golang ,
and any of the maintainers: @genedna, @jing-rui ,
and any of the committers: @fuowang, @wd-gitcode .


【缺陷描述】:请补充详细的缺陷问题现象描述
go代码安全扫描问题
一、缺陷信息
发现 7 个问题(🔴 致命 0 · 🟡 重要 0 · 🟢 建议 5 · ⚠️ 疑似 2)
该 BUILD 树为纯净上游 Go 1.24.2 标准库,经 Go 团队与社区长期审计,未发现可被远程/未认证利用的致命或重要漏洞。本次审计所立问题均为:遗留弱加密算法(向后兼容所需)、用户可选关闭证书校验的特性、网络响应体无界读取的潜在 DoS、以及一处用户配置异常导致的 panic(健壮性)。所有发现均附带真实
file:line、调用栈与修复建议。Go 工具链在命令执行方面采用 argv 数组(无 shell)、配合 git--end-of-options与module.CheckPath校验,命令注入面已被有效收敛。🟢 [建议] F1 — 遗留 PEM 加密使用 MD5 KDF + DES/3DES 弱加密算法
CWE: CWE-327(使用已被破解或有缺陷的加密算法)、CWE-916(口令派生函数迭代次数不足)
规则: R03-weak-crypto / R03-weak-kdf
描述:
crypto/x509/pem_decrypt.go实现 RFC 1423 遗留 PEM 加密。rfc1423Algos将PEMCipherDES(DES-CBC,56 位密钥)与PEMCipher3DES列为可选算法;deriveKey使用md5.New()单轮迭代从口令派生密钥(无 PBKDF2/盐迭代)。DES 56 位密钥可被暴力破解,MD5 已被攻破(碰撞攻击),单轮无迭代 KDF 对字典攻击几乎无防护。该文件本身在 line 100-103 的IsEncryptedPEMBlock文档注释中已明确标注「Legacy PEM encryption as specified in RFC 1423 is insecure by design」。影响: 当用户显式选择
PEMCipherDES/PEMCipher3DES加密 PEM 私钥时,加密强度远低于 AES;MD5 单轮 KDF 使口令字典攻击成本极低。攻击者获得 PEM 文件后可离线恢复私钥。CVSS: 3.5(Low)— 需攻击者已持有加密 PEM 文件,且默认/推荐算法为 AES。
数据来源: 遗留 PEM 文件(OpenSSL 历史格式)
风险传播路径: 用户调用
x509.EncryptPEMBlock(rand, blockType, data, password, PEMCipherDES)→ 选中rfc1423Algos[PEMCipherDES]→deriveKey(password, salt)用 MD5 派生 8 字节密钥 →des.NewCipher加密。调用栈
问题代码
// 文件: crypto/x509/pem_decrypt.go:46-57 DES/3DES 列为可选算法 var rfc1423Algos = []rfc1423Algo{{ cipher: PEMCipherDES, name: "DES-CBC", cipherFunc: des.NewCipher, keySize: 8, blockSize: des.BlockSize, }, { cipher: PEMCipher3DES, name: "DES-EDE3-CBC", cipherFunc: des.NewTripleDESCipher, keySize: 24, blockSize: des.BlockSize, }, /* ... AES128/192/256 ... */} // 文件: crypto/x509/pem_decrypt.go:82-96 MD5 单轮口令派生 func (c rfc1423Algo) deriveKey(password, salt []byte) []byte { hash := md5.New() // 弱哈希 out := make([]byte, c.keySize) var digest []byte for i := 0; i < len(out); i += len(digest) { hash.Reset() hash.Write(digest) hash.Write(password) hash.Write(salt) digest = hash.Sum(digest[:0]) // 单轮,无迭代计数 copy(out[i:], digest) } return out }调用链分析
修复建议
// 1) 不建议修改上游 API;应用层应避免使用 PEMCipherDES/PEMCipher3DES, // 新加密一律使用 PEMCipherAES256。 // 2) 若需保护遗留已加密 PEM,应迁移至 PKCS#8 (crypto/x509.MarshalPKCS8PrivateKey) // 配合 AES-256-CBC + PBKDF2/scrypt 高迭代 KDF。 // 3) 文档/编译期告警:可在应用层 lint 规则中标记 PEMCipherDES/PEMCipher3DES 为禁用。 encBlock, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", pemData, password, x509.PEMCipherAES256)🟢 [建议] F2 — TLS 1.0/1.1 PRF 与握手使用 MD5(协议遗留)
CWE: CWE-327(使用已被破解或有缺陷的加密算法)
规则: R03-weak-crypto
描述:
crypto/tls/prf.go的prf10实现 TLS 1.0 PRF,按 RFC 2246 使用 MD5+SHA1 双哈希;finishedHash在 TLS 1.0/1.1 下额外维护clientMD5/serverMD5并在 Finished 消息中拼接 MD5 摘要;crypto/tls/key_agreement.go的md5SHA1Hash实现 TLS 1.0 混合哈希。MD5 已被攻破,但 TLS 1.0/1.1 协议规范强制使用 MD5。影响: 仅当协商使用 TLS 1.0/1.1 时受影响。Go 1.24 默认最小版本为 TLS 1.2(
crypto/tls/common.go:758),服务端 TLS 1.0 仅在GODEBUG=tls10server=1时启用。默认配置不受影响。CVSS: 2.0(Low)— 仅影响显式启用 TLS 1.0/1.1 的遗留连接。
数据来源: TLS 协议版本协商
风险传播路径:
tls.Client握手 →prfAndHashForVersion(VersionTLS10/11)返回prf10→pHash(..., hashMD5)→ MD5 参与密钥派生与 Finished 校验。调用栈
问题代码
// 文件: crypto/tls/prf.go:50-70 TLS 1.0 PRF 使用 MD5 func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { result := make([]byte, keyLen) hashSHA1 := sha1.New hashMD5 := md5.New // ... s1, s2 := splitPreMasterSecret(secret) pHash(result, s1, labelAndSeed, hashMD5) // MD5 参与密钥派生 // ... } // 文件: crypto/tls/prf.go:90-93 TLS 1.0/1.1 路由到 prf10 func prfAndHashForVersion(version uint16, suite *cipherSuite) (prfFunc, crypto.Hash) { switch version { case VersionTLS10, VersionTLS11: return prf10, crypto.Hash(0) // ... } // 文件: crypto/tls/key_agreement.go:115-125 TLS 1.0 混合哈希 func md5SHA1Hash(slices [][]byte) []byte { md5sha1 := make([]byte, md5.Size+sha1.Size) hmd5 := md5.New() for _, slice := range slices { hmd5.Write(slice) } copy(md5sha1, hmd5.Sum(nil)) copy(md5sha1[md5.Size:], sha1Hash(slices)) return md5sha1 }调用链分析
修复建议
// 应用层应在 tls.Config 中强制最小版本为 TLS 1.2,彻底规避 MD5 路径: config := &tls.Config{ MinVersion: tls.VersionTLS12, // 拒绝 TLS 1.0/1.1 } // 服务端不要设置 GODEBUG=tls10server=1(默认即禁用 TLS 1.0)。 // 上游 stdlib 此处为协议强制,无法移除 MD5;正确缓解在配置层。🟢 [建议] F3 — pprof 工具在
https+insecure协议下跳过 TLS 证书校验CWE: CWE-295(证书校验不当)
规则: R03-cert-validation
描述:
cmd/pprof/pprof.go的getProfile在 URL scheme 为https+insecure时构造tls.Config{InsecureSkipVerify: true},跳过服务器证书链与主机名校验,随后用该配置发起 HTTPS GET 拉取 profile 数据。影响: 当用户以
https+insecure://host/...形式拉取 profile 时,连接可被中间人(MITM)劫持/窃听/篡改 profile 数据。该 scheme 为用户显式输入的特殊协议,属 opt-in 行为;但一旦误用(如把生产 profile 端点写成https+insecure),即丧失传输安全。CVSS: 2.7(Low)— 需用户显式使用
https+insecurescheme,且攻击者处于网络路径中间人位置。数据来源: 用户在 pprof 命令行传入的 URL
风险传播路径:
pprof fetcher→getProfile("https+insecure://...")→tls.Config{InsecureSkipVerify:true}→http.Client.Get→ MITM 可篡改 profile 响应。调用栈
问题代码
// 文件: cmd/pprof/pprof.go:84-91 var tlsConfig *tls.Config if url.Scheme == "https+insecure" { tlsConfig = &tls.Config{ InsecureSkipVerify: true, // 跳过证书校验 } url.Scheme = "https" source = url.String() }调用链分析
修复建议
// 1) 文档/告警:在启用 https+insecure 时向 stderr 打印明显安全警告, // 提示该连接不受 MITM 保护,仅限受控调试环境。 // 2) 优先使用显式 CA 指定而非整体跳过校验:支持 -cacert 指定自签 CA。 // 3) 用户侧:不要对非本机/不可信网络使用 https+insecure,仅限本地 loopback 调试。🟢 [建议] F4 —
go命令在 GOINSECURE 模式下跳过 HTTPS 模块拉取的证书校验CWE: CWE-295(证书校验不当)
规则: R03-cert-validation
描述:
cmd/go/internal/web/http.go定义impatientInsecureHTTPClient,其TLSClientConfig.InsecureSkipVerify = true。该 client 在get()中当security == Insecure && url.Scheme == "https"时被选用(line 134-135),即用户设置GOINSECURE环境变量后,go get对 HTTPS 模块源/代理的请求跳过证书校验。影响: 设置
GOINSECURE后,模块拉取可被 MITM 篡改/窃听,攻击者可注入恶意模块代码或篡改 go.sum 校验和前的元数据。该行为是 GOINSECURE 的设计语义(用于自签证书的内网代理),但用户若将 GOINSECURE 设得过宽(如GOINSECURE=*),将整体丧失模块拉取的传输安全。CVSS: 2.7(Low)— 需用户显式设置 GOINSECURE 且攻击者处于网络路径。
数据来源:
GOINSECURE环境变量(用户配置)风险传播路径:
go get→web.get(Insecure)→fetch(url)→security==Insecure && https→impatientInsecureHTTPClient.Do(req)→ MITM。调用栈
问题代码
// 文件: cmd/go/internal/web/http.go:37-46 var impatientInsecureHTTPClient = &http.Client{ CheckRedirect: checkRedirect, Timeout: 5 * time.Second, Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, // GOINSECURE 时跳过证书校验 }, }, } // 文件: cmd/go/internal/web/http.go:133-135 选用条件 var client *http.Client if security == Insecure && url.Scheme == "https" { client = impatientInsecureHTTPClient }调用链分析
修复建议
// 1) 用户侧:将 GOINSECURE 限定到明确的内网主机前缀,避免 GOINSECURE=*。 // 例如:GOINSECURE=git.internal.corp.com,*.corp.local // 2) 内网自签证书场景优先用 GOAUTH 或自定义 CA 而非 GOINSECURE。 // 3) 可在 -x 输出中当 insecure client 被启用时打印安全告警,提醒用户。🟢 [建议] F5 — 模块拉取网络响应体无界
io.ReadAll(潜在内存耗尽 DoS)CWE: CWE-400(不受控的资源消耗)、CWE-770(资源分配无限制)
规则: R05-resource-limit / R01-input-validation
描述:
cmd/go/internal/modfetch/proxy.go的getBytes与cmd/go/internal/web/api.go的GetBytes均对 HTTP 响应体直接调用io.ReadAll(body)而无显式字节数上限。这些响应来自 GOPROXY 代理或go-importmeta 服务器。安全保留的默认 client(securityPreservingDefaultClient,基于http.DefaultClient)未设置Client.Timeout,因此既无大小上限也无整体读超时。影响: 恶意或被入侵的 GOPROXY / 模块服务器可流式返回超大响应体,导致
go命令进程内存耗尽(OOM)而崩溃,构成对构建/CI 环境的拒绝服务。net/http/request.go:1278-1293的表单解析有 10MB 上限作为正面对照,而此处网络拉取无对应防护。CVSS: 4.3(Medium)— 需攻击者控制或能影响用户配置的 GOPROXY/模块服务器;用户侧影响为构建 DoS。
数据来源: GOPROXY 服务器 / go-import meta 服务器的 HTTP 响应体
风险传播路径:
go get/go mod download→proxyRepo.getBytes→io.ReadAll(body)→ 无上限分配 → OOM。调用栈
问题代码
// 文件: cmd/go/internal/modfetch/proxy.go:259-273 func (p *proxyRepo) getBytes(ctx context.Context, path string) ([]byte, error) { body, redactedURL, err := p.getBody(ctx, path) if err != nil { return nil, err } defer body.Close() b, err := io.ReadAll(body) // 无 LimitReader,无字节数上限 if err != nil { return b, &url.Error{Op: "read", URL: redactedURL, Err: err} } return b, nil } // 文件: cmd/go/internal/web/api.go:84-96 func GetBytes(u *url.URL) ([]byte, error) { resp, err := Get(DefaultSecurity, u) // ... b, err := io.ReadAll(resp.Body) // 无上限 // ... }调用链分析
修复建议
// 为模块元数据拉取设置合理的字节数上限(如 32MB,模块 .mod/.info/.zip 元数据远小于此), // 并为默认安全 client 设置整体超时。 const maxModuleMetadataBytes = 32 << 20 // 32 MB b, err := io.ReadAll(io.LimitReader(body, maxModuleMetadataBytes+1)) if err != nil { /* ... */ } if int64(len(b)) > maxModuleMetadataBytes { return nil, fmt.Errorf("module metadata at %s too large (max %d bytes)", redactedURL, maxModuleMetadataBytes) } // 同时为 securityPreservingDefaultClient 设置 Timeout: var securityPreservingDefaultClient = securityPreservingHTTPClient(&http.Client{ Timeout: 60 * time.Second, })⚠️ 疑似[建议] F6 —
buildCommand对空白字符 GOAUTH 值发生 panic(健壮性/空索引)CWE: CWE-476(空指针/空切片解引用)、CWE-754(异常条件检查不当)
规则: R05-error-handling / R01-input-validation
置信度: 85%
描述:
cmd/go/internal/auth/userauth.go的buildCommand调用quoted.Split(command)后直接exec.Command(words[0], words[1:]...)。quoted.Split(cmd/internal/quoted/quoted.go:25-59)对空白字符-only 输入(如" ")会返回(nil, nil)——即切片为空且无错误:循环中先trim掉全部空白,len(s)==0即break,f保持nil。此时words[0]对 nil 切片取下标 0 触发index out of rangepanic。调用方runAuthCommand在 line 24 仅有if command == ""判空,无法捕获空白字符-only 的 GOAUTH 值(" " != ""),故 panic 不会被前置检查拦截。影响: 用户设置
GOAUTH=" "(或因配置脚本拼接错误产生纯空白值)时,go命令在发起认证时崩溃(panic),而非返回清晰错误。属本地可用性/健壮性问题,非安全漏洞(GOAUTH 由用户自设,攻击者需已能修改用户环境)。CVSS: 2.0(Low)— 本地 DoS,需用户自设异常 GOAUTH。
数据来源:
GOAUTH环境变量(用户配置)风险传播路径:
cfg.GOAUTH解析 →runAuthCommand(" ", url, res)→command == ""为 false(通过) →buildCommand(" ")→quoted.Split(" ")→(nil, nil)→exec.Command(words[0]...)→ panic: runtime error: index out of range。调用栈
问题代码
// 文件: cmd/go/internal/auth/userauth.go:108-115 func buildCommand(command string) (*exec.Cmd, error) { words, err := quoted.Split(command) if err != nil { return nil, fmt.Errorf("cannot parse GOAUTH command %s: %v", command, err) } cmd := exec.Command(words[0], words[1:]...) // words 为 nil 时 panic return cmd, nil } // 文件: cmd/go/internal/auth/userauth.go:23-30 调用方仅判 == "" func runAuthCommand(command string, url string, res *http.Response) (map[string,http.Header, error) { if command == "" { // 无法捕获 " " panic("GOAUTH invoked an empty authenticator command:" + command) } cmd, err := buildCommand(command) // ... } // 文件: cmd/internal/quoted/quoted.go:25-58 空白输入返回 (nil, nil) func Split(s string) ([]string, error) { var f []string for len(s) > 0 { for len(s) > 0 && isSpaceByte(s[0]) { s = s[1:] } // " " 全被 trim if len(s) == 0 { break } // 退出,f 仍为 nil // ... } return f, nil // (nil, nil) }调用链分析
==""修复建议
// 在 buildCommand 中显式校验 words 非空,返回清晰错误而非 panic: func buildCommand(command string) (*exec.Cmd, error) { words, err := quoted.Split(command) if err != nil { return nil, fmt.Errorf("cannot parse GOAUTH command %s: %v", command, err) } if len(words) == 0 { return nil, fmt.Errorf("GOAUTH command %q contains no executable", command) } cmd := exec.Command(words[0], words[1:]...) return cmd, nil } // 同时建议 runAuthCommand 将 =="" 收紧为 strings.TrimSpace(command) == ""。⚠️ 疑似[建议] F7 — VCS 命令执行面:模块路径派生的参数注入风险(已缓解,残留风险)
CWE: CWE-78(操作系统命令注入)、CWE-88(参数注入)
规则: R02-command-injection
置信度: 70%(已缓解,残留风险)
描述:
cmd/go/internal/vcs/vcs.go的run1通过exec.Command(v.Cmd, args...)执行 VCS 二进制(git/hg/svn 等)。args由cmdline模板经strings.Fields拆分并expand(m, arg)替换占位符得到,占位符的值(scheme、repo等)源自模块 import 路径。Shell 注入不可能(argv 数组,不经 shell)。参数注入风险(如--upload-pack=恶意命令)由上游module.CheckPath/module.EscapePath路径校验 + git 命令中的--end-of-options守卫(git.go 中 8 处)缓解。但 VCS 子进程参数解析行为各异,且此处是历史高危面(旧版go getCVE-2018-6574 即在此类路径),未来若路径校验或 VCS 模板出现回归,可能重新引入参数注入。影响: 在当前 Go 1.24 实现下,路径校验与
--end-of-options已有效收敛参数注入;本条记录该攻击面与现有缓解,提示后续维护关注。CVSS: 3.1(Low)— 需路径校验/VCS 模板出现回归方可利用。
数据来源: 模块 import 路径 / VCS URL(
go get输入)风险传播路径:
go get <module>→vcsCmd.run/Ping→run1(dir, cmdline, keyval)→expand(m, arg)(m 含 repo/scheme) →exec.Command(v.Cmd, args...)→ VCS 二进制解析参数。调用栈
问题代码
// 文件: cmd/go/internal/vcs/vcs.go:451-500 func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) { m := make(map[string]string) for i := 0; i < len(keyval); i += 2 { m[keyval[i]] = keyval[i+1] // repo/scheme 等源自 import 路径 } args := strings.Fields(cmdline) for i, arg := range args { args[i] = expand(m, arg) // 占位符替换为路径派生值 } // ... --go-internal-mkdir / --go-internal-cd 处理 ... cmd := exec.Command(v.Cmd, args...) // 执行 VCS 二进制 cmd.Dir = dir // ... out, err := cmd.Output() return out, err } // 文件: cmd/go/internal/vcs/vcs.go:515-533 Ping 注入 repo func (v *Cmd) Ping(scheme, repo string) error { // ... return v.runVerboseOnly(dir, v.PingCmd, "scheme", scheme, "repo", repo) }调用链分析
修复建议
// 1) 维持并强化 module.CheckPath / module.EscapePath 对 repo/scheme 的前置校验 // (拒绝含 "--"、控制字符、空格的路径段),确保进入 expand 的值不可能以 "-" 开头。 // 2) 在 run1 中对展开后的 args 做防御性校验:任何以 "-" 开头且非已知 VCS 选项的 token // 一律拒绝,或对 git 类命令统一在 rev 前插入 --end-of-options。 // 3) 持续回归测试:覆盖 import 路径含 "--upload-pack=..."、"-"、空格等畸形用例。 // 4) 应用层:在不可信 import 路径场景限制 GOPROXY=off / GOFLAGS=-mod=readonly 降低动态拉取面。【缺陷所属的os版本】
24.03-LTS-next
【内核版本】
kernel6.6
【缺陷所属软件及版本号】
go
【环境信息】
【问题复现步骤】
【实际结果】
【期望结果】
【其他相关附件信息】
【缺陷详情及分析指导参考链接】
二、缺陷分析结构反馈
影响性分析说明:
缺陷严重等级:(Critical/High/Moderate/Low)
缺陷根因说明:
受影响版本排查(受影响/不受影响):
openEuler-20.03-LTS-SP4
openEuler-22.03-LTS-SP4
openEuler-24.03-LTS-SP1
openEuler-24.03-LTS-SP3
openEuler-24.03-LTS-SP4
修复是否涉及abi变化(是/否):
openEuler-20.03-LTS-SP4
openEuler-22.03-LTS-SP4
openEuler-24.03-LTS-SP1
openEuler-24.03-LTS-SP3
openEuler-24.03-LTS-SP4