- 测试
- 操作系统
- 网络安全
【免费下载链接】syzkaller
syzkaller is an unsupervised coverage-guided kernel fuzzer
本文以 syzkaller 仓库 vendor 目录下随附的 gosec(Go Security Checker) 官方文档为主体,结合仓库内 gosec v2.19.0 的完整源码,系统讲解 gosec 的工作原理、规则体系、配置方式与 CI 落地实践。读完本文,你将掌握 gosec 的安装接入、规则筛选、#nosec抑制注解、SARIF 报告集成等全套实操技能,并能从源码层面理解其 AST + SSA 双通道扫描机制。
gosec 是什么:基于 AST 与 SSA 的 Go 安全扫描器
gosec 通过扫描 Go 源码的AST(抽象语法树)与SSA(静态单赋值)代码表示来检查安全缺陷,属于静态分析(SAST)工具,无需运行被测代码即可发现硬编码凭据、弱加密算法、SQL 注入、不安全的 TLS 配置等典型问题。
从仓库内的源码可以看到其核心机制:
- 规则接口:
vendor/github.com/securego/gosec/v2/rule.go定义了Rule接口(ID()与Match(ast.Node, *Context)),以及RuleBuilder、RuleSet注册表。规则按 AST 节点类型注册,扫描器在遍历 AST 时只对当前节点类型调用已注册的规则。 - 扫描器主体:
vendor/github.com/securego/gosec/v2/analyzer.go中的Analyzer通过ast.Walk遍历语法树驱动规则匹配,同时调用golang.org/x/tools/go/analysis/passes/buildssa构建 SSA 表示,由CheckAnalyzers运行基于数据流的分析器(如切片越界G602即由此实现,见vendor/github.com/securego/gosec/v2/analyzers/slice_bounds.go)。 - 上下文对象:
Context结构体携带文件集、注释映射、类型信息、导入追踪器等数据,在规则匹配时透传给每个规则,使规则不仅能看语法,还能结合类型信息与注释(如#nosec)做判断。
安装 gosec:CI、本地与 Docker 三种方式
CI / 脚本安装
利用 gosec 官方发布脚本可直接将二进制安装到指定目录(脚本会随版本号下载对应平台的预编译产物):
# 二进制将安装到 $(go env GOPATH)/bin/gosec curl -sfL <gosec_install_script_url> | sh -s -- -b $(go env GOPATH)/bin vX.Y.Z # 或安装到当前目录的 ./bin/ curl -sfL <gosec_install_script_url> | sh -s vX.Y.Z # Alpine Linux 默认不带 curl,可用 wget wget -O - -q <gosec_install_script_url> | sh -s vX.Y.Z如需校验发布包完整性,可下载对应操作系统的gosec_vX.Y.Z_OS.tar.gz压缩包,用 Release 页面提供的校验和文件核对:
echo "<check sum from the check sum file> gosec_vX.Y.Z_OS.tar.gz" | sha256sum -c - gosec --help本地安装(go install)
在已配置 Go 工具链的环境下,最简单的方式是直接安装:
go install github.com/securego/gosec/v2/cmd/gosec@latest作为 GitHub Action 运行
securego/gosec@master提供了现成的 Action,最小示例:
name: Run Gosec on: push: branches: - master pull_request: branches: - master jobs: tests: runs-on: ubuntu-latest env: GO111MODULE: on steps: - name: Checkout Source uses: actions/checkout@v3 - name: Run Gosec Security Scanner uses: securego/gosec@master with: args: ./...与 GitHub code scanning 集成(SARIF 上传)
gosec 支持输出 SARIF 格式报告,可借助 GitHub code scanning 展示扫描结果。将 gosec 作为 workflow 中的一步,输出results.sarif后由upload-sarifAction 上传:
name: "Security Scan" # 每次代码推送时运行,并额外在每周日 00:00 UTC 定时运行 on: push: schedule: - cron: '0 0 * * 0' jobs: tests: runs-on: ubuntu-latest env: GO111MODULE: on steps: - name: Checkout Source uses: actions/checkout@v3 - name: Run Gosec Security Scanner uses: securego/gosec@master with: # 不因扫描结果直接导致任务失败,交由 GitHub Security 特性触发告警 args: '-no-fail -fmt sarif -out results.sarif ./...' - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v2 with: # SARIF 文件路径相对于仓库根目录 sarif_file: results.sarifDocker 方式
也可构建本地镜像后以容器方式运行(make image构建镜像,细节见 vendor 内 Makefile):
docker run --rm -it -w /<PROJECT>/ -v <YOUR PROJECT PATH>/<PROJECT>:/<PROJECT> securego/gosec /<PROJECT>/...注意:必须用
-w指定容器内工作目录,否则无法正确解析 go module 依赖。
规则体系全景:从 G101 到 G602
gosec 默认会对输入文件运行全部规则。要递归扫描当前目录,以./...作为输入参数即可。完整规则清单如下:
| 规则 ID | 检查内容 |
|---|---|
| G101 | 查找硬编码凭据 |
| G102 | 绑定到所有网络接口 |
| G103 | 审计 unsafe 代码块的使用 |
| G104 | 审计未检查的错误 |
| G106 | 审计 ssh.InsecureIgnoreHostKey 的使用 |
| G107 | 作为 taint 输入提供给 HTTP 请求的 URL |
| G108 | 自动暴露在 /debug/pprof 的性能分析端点 |
| G109 | strconv.Atoi 结果转换为 int16/32 时潜在的整数溢出 |
| G110 | 解压炸弹导致的潜在 DoS 漏洞 |
| G111 | 潜在的目录穿越 |
| G112 | 潜在的 slowloris 攻击 |
| G113 | math/big 中 Rat.SetString 的溢出使用(CVE-2022-23772) |
| G114 | 使用不支持设置超时时间的 net/http serve 函数 |
| G201 | 使用格式化字符串构造 SQL 查询 |
| G202 | 使用字符串拼接构造 SQL 查询 |
| G203 | 在 HTML 模板中使用未转义数据 |
| G204 | 审计命令执行的使用 |
| G301 | 创建目录时使用不当的文件权限 |
| G302 | 使用 chmod 时设置不当的文件权限 |
| G303 | 使用可预测路径创建临时文件 |
| G304 | 作为 taint 输入提供的文件路径 |
| G305 | 解压 zip/tar 归档时的文件遍历 |
| G306 | 写入新文件时使用不当的文件权限 |
| G307 | 使用 os.Create 创建文件时使用不当的文件权限 |
| G401 | 检测 DES、RC4、MD5 或 SHA1 的使用 |
| G402 | 查找糟糕的 TLS 连接设置 |
| G403 | 确保 RSA 密钥长度至少为 2048 位 |
| G404 | 不安全的随机数来源(rand) |
| G501 | 导入黑名单:crypto/md5 |
| G502 | 导入黑名单:crypto/des |
| G503 | 导入黑名单:crypto/rc4 |
| G504 | 导入黑名单:net/http/cgi |
| G505 | 导入黑名单:crypto/sha1 |
| G601 | range 语句中元素的隐式内存别名 |
| G602 | 切片访问越界 |
已退休规则(Retired rules)
以下规则已从默认检查中移除:
- G105:审计 math/big.Int.Exp 的使用——对应 CVE 已修复;
- G307:defer 调用返回错误的方法——该检查带来的困扰大于其发现的安全价值,故被移除(历史上该编号曾被重新分配用于文件权限检查,注意不同版本语义差异)。
CWE 映射
gosec 发现的每个问题都会映射到对应的CWE(Common Weakness Enumeration)编号,便于与通用漏洞标准对齐。完整映射表定义在仓库源码 vendor/github.com/securego/gosec/v2/issue/issue.go#L55-L91 的ruleToCWE变量中,例如G101 → CWE-798、G201/G202 → CWE-89、G402 → CWE-295、G404 → CWE-338、G601/G602 → CWE-118。扫描结果中的Cwe字段即由此映射生成。
按需选择规则:-include 与 -exclude
默认情况下 gosec 对输入路径运行全部规则,但可通过两个标志精确控制规则集合:
# 只运行指定的规则子集 $ gosec -include=G101,G203,G401 ./... # 运行除 G303 以外的所有规则 $ gosec -exclude=G303 ./...-include用于从全量规则中挑出关心的子集;-exclude用于剔除误报率较高或与团队规范冲突的规则。从源码看,这一机制对应 analyzer.go 中的RuleSet注册与IsRuleSuppressed查询,被排除的规则在RuleSuppressedMap中标记为 suppressed,命中时不再计入有效 issue。
配置:全局设置与规则级参数
全局配置
通过-conf指定 JSON 配置文件,可设置影响所有规则的全局开关:
{ "global": { "nosec": "enabled", "audit": "enabled" } }# 使用全局配置文件运行 $ gosec -conf config.json .两个全局选项的含义:
nosec:启用后将覆盖代码库中所有#nosec指令,即不再忽略任何被注解的行;audit:以审计模式运行,启用那些对常规代码分析而言可能过于"多管闲事"的附加检查。
从源码 vendor/github.com/securego/gosec/v2/config.go 可以看到,全局选项还包括show-ignored(被#nosec忽略的 issue 是否仍计入发现)、#nosec(自定义抑制注解替代标签)等,配置值通过IsGlobalEnabled判定("true"或"enabled"视为开启)。
规则级配置:以 G104 为例
某些规则接受专属配置。例如 G104(未检查错误)可指定"包 + 函数"列表,审计时跳过这些函数:
{ "G104": { "ioutil": ["WriteFile"] } }规则级配置:G101 硬编码凭据
G101 支持自定义匹配模式或调整熵阈值:
{ "G101": { "pattern": "(?i)passwd|pass|password|pwd|secret|private_key|token", "ignore_entropy": false, "entropy_threshold": "80.0", "per_char_threshold": "3.0", "truncate": "32" } }各参数的作用(结合 rules/hardcoded_credentials.go 源码可确认默认值与判定逻辑):
pattern:用于匹配变量名的正则。源码默认值为(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred;ignore_entropy:默认false。为true时跳过熵检测,只要变量名匹配即报警;为false时需同时满足高熵条件;entropy_threshold:默认80.0。字符串整体熵达到该值即判定为高熵(使用zxcvbn口令强度算法计算);per_char_threshold:默认3.0。当总熵超过阈值一半且"每字符熵"达到该值时也判定为高熵;truncate:默认16。参与熵计算的字符串截断长度,避免超长字符串稀释熵值。
除熵检测外,G101 还内置了大量已知凭据格式的正则(secretsPatterns列表),覆盖 RSA/SSH/PGP 私钥块、Slack Token、AWS API Key、GitHub personal access token、Google API Key、Stripe 密钥、Twilio API Key、Telegram Bot Token、URL 内嵌密码等数十种模式。实际命中任一模式即直接报警,无需依赖熵阈值,这也是 G101 误报率相对可控的原因。
扫描实践:依赖、测试文件与生成文件
依赖处理
当启用 go module(如GO111MODULE=on)时,gosec 会自动拉取被分析代码的依赖;否则需要先手动执行go get -d下载依赖后再扫描。
排除测试文件与目录
gosec 默认会忽略所有包中的测试文件以及 vendor 目录中的依赖。若需要扫描测试文件,使用-tests:
gosec -tests ./...需要排除额外目录时使用-exclude-dir(可重复指定):
gosec -exclude-dir=rules -exclude-dir=cmd ./...排除生成文件
gosec 可跳过带标准生成注释的 Go 文件。生成注释的标准格式为:
// Code generated by some generator DO NOT EDIT.配合-exclude-generated标志使用:
gosec -exclude-generated ./...从源码 analyzer.go 的generatedCodePattern(^// Code generated .* DO NOT EDIT\.$)可以看到其精确匹配规则,CheckRules与CheckAnalyzers两个通道都会跳过此类文件。
#nosec 注解:处理误报的正确姿势
与所有自动化检测工具一样,gosec 也会产生误报。对于已人工确认为安全的告警,可在对应行添加以#nosec开头的注释:
格式为#nosec [RuleList] [-- Justification],注释必须放在告警报告的同一行:
func main() { tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, // #nosec G402 }, } client := &http.Client{Transport: tr} _, err := client.Get("https://golang.org/") if err != nil { fmt.Println(err) } }进阶用法:
- 只抑制指定规则:
/* #nosec G401 */或//#nosec G201 G202 G203,让该区域只跳过列出的规则,其余规则继续扫描; - 附加说明文字:在规则列表后以两个及以上连字符开头书写理由,例如
//#nosec G101 G102 -- This is a false positive; - 整体忽略所有注解:
gosec -nosec=true ./...会忽略所有#nosec,用于复查历史注解是否仍必要。
源码层面,#nosec的解析逻辑在 analyzer.go 的ignore方法中:它按-{2,}切分指令与理由,用G\d{3}正则提取要抑制的规则 ID,若未列出具体规则则抑制该处全部规则(*通配),并记录Kind: "inSource"的抑制信息。
追踪抑制(Track Suppressions)
外部抑制(-include/-exclude)与内联抑制(#nosec)信息可用于审计用途,通过-track-suppressions记录:
gosec -track-suppressions -exclude=G101 -fmt=sarif -out=results.sarif ./...抑制信息的两种来源:
- 外部抑制:
kind为external,justification固定为 "Globally suppressed."(源码常量externalSuppressionJustification); - 内联抑制:
kind为inSource,justification为#nosec注释中两个及以上连字符之后的文字。
注意:仅SARIF 和 JSON两种格式支持记录抑制信息。
构建标签与输出格式
构建标签
gosec 可将 Go 构建标签透传给分析器,以逗号分隔列表传入:
gosec -tags debug,ignore ./...输出格式
gosec 支持text、json、yaml、csv、sonarqube、JUnit XML、html和golint八种输出格式。默认结果输出到 stdout,可用-fmt指定格式、-out指定输出文件:
# 以 json 格式写入 results.json $ gosec -fmt=json -out=results.json *.go-stdout可在写文件的同时把结果打到标准输出;-verbose则覆盖 stdout 的输出格式:
# 以 json 写入 results.json,同时输出到 stdout $ gosec -fmt=json -out=results.json -stdout *.go # stdout 用 text 格式展示,文件仍写为 json $ gosec -fmt=json -out=results.json -stdout -verbose=text *.goSonarQube 集成时,gosec 生成通用问题导入格式(generic issue import format),需要将报告通过sonar.externalIssuesReportPaths=path/to/gosec-report.json导入 SonarQube。
从报告结构看(issue/issue.go),每个 Issue 包含severity、confidence、cwe、rule_id、details、file、code、line、column等字段;严重度与置信度均为 LOW/MEDIUM/HIGH 三档(Score枚举),JSON 序列化时输出为对应字符串。
在 syzkaller 仓库中的集成现状
gosec 在本仓库中的角色是静态安全扫描第三方依赖:它以v2.19.0版本作为间接依赖被 vendored(见 go.mod#L187 与 vendor/modules.txt),源码完整保留在 vendor/github.com/securego/gosec/v2 目录下。
在 lint 集成层面,syzkaller 使用 golangci-lint 统一管理静态检查,其配置文件 .golangci.yml#L54 的disable列表中显式禁用了gosec,同时启用了vet、staticcheck、revive、errcheck(注释中说明 errcheck 待修复既有告警后再启用)以及项目自研的syz-linter(自定义插件,路径bin/syz-linter.so)。这表明在大型基础设施类项目(如内核模糊测试框架)中,团队往往会根据自身告警容忍度与既有 lint 体系,选择性地关闭通用安全扫描器,转而依赖更贴合项目语境的规则集——这是 gosec 这类通用工具在实际工程中的常见落地形态。
如果你希望在本仓库启用 gosec 做专项安全审计,可在.golangci.yml的enable列表中加入gosec并按上述-exclude/#nosec机制逐步收敛误报。
开发者视角:构建、测试与发布
构建与测试
# 构建二进制 make # 运行全部单元测试 make test版本发布与签名校验
发布通过打 tag 触发:
git tag v1.0.0 -m "Release version v1.0.0" git push origin v1.0.0tag 推送后,发布工作流会调用 goreleaser 产出各平台二进制并发布 Docker 镜像。所有发布产物使用 cosign 签名(公钥见 cosign.pub):
# 校验 Docker 镜像签名 cosign verify --key cosign.pub securego/gosec:<TAG> # 校验二进制包签名 cosign verify-blob --key cosign.pub --signature gosec_<VERSION>_darwin_amd64.tar.gz.sig gosec_<VERSION>_darwin_amd64.tar.gzTLS 规则自动生成
TLS 规则(G402)的密码套件配置可从 Mozilla 的 TLS 服务端配置推荐自动生成:
# 安装生成工具 go get github.com/securego/gosec/v2/cmd/tlsconfig/... # 在项目根目录执行 go generate ./...该命令会生成rules/tls_config.go,包含 Mozilla 当前推荐的密码套件清单(仓库中已存在 rules/tls_config.go 生成产物),使 TLS 规则始终与业界推荐基线保持同步。
小结
gosec 通过"AST 规则匹配 + SSA 数据流分析"双通道实现对 Go 代码的安全缺陷检测,提供了从单条命令到 CI/CD 全链路(GitHub Action、SARIF、SonarQube)的集成能力。实践中的关键决策点包括:用-include/-exclude裁剪规则集、用-conf调整全局与规则级参数、用#nosec规范地处理误报、用-track-suppressions沉淀审计证据。无论是为中小型 Go 服务引入第一道安全防线,还是像 syzkaller 这样在既有 lint 体系中权衡取舍,理解 gosec 的规则语义与配置细节都至关重要。
- 测试
- 操作系统
- 网络安全
【免费下载链接】syzkaller
syzkaller is an unsupervised coverage-guided kernel fuzzer
相关推荐
gosec Go 安全扫描器实战指南:AST/SSA/Taint 三层分析、规则配置与 CI 集成
gosec Go 安全扫描器实战指南:AST/SSA/Taint 三层分析、规则配置与 CI 集成 gosec(Go Security Checker)是一款专
SAST应用安全静态分析代码质量漏洞扫描jQuery.scrollTo完全指南:10分钟掌握轻量级滚动动画插件
jQuery.scrollTo完全指南:10分钟掌握轻量级滚动动画插件 jQuery.scrollTo是一款轻量级、跨浏览器且高度可定制的jQuery滚动动画插
前端ECC Go 安全规则详解:密钥管理、gosec 静态扫描与 context 超时治理
ECC Go 安全规则详解:密钥管理、gosec 静态扫描与 context 超时治理 本篇指南聚焦 ECC 仓库中的 Go 安全规则文件 .cursor/ru
人工智能AI 技能AI 插件AI 评测Agent 评测MCP Clients开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考