
GitHub 产品安全工程团队通过开发 CodeQL 等工具来大规模检测和修复漏洞,从而确保 GitHub 代码的安全。他们分享了自己的方法,以便其他组织可以学习如何使用 CodeQL 来更好地保护自己的代码库。
CodeQL 让用户可以用与查询数据库类似的方式查询代码,从而实现自动化安全分析。与简单的文本搜索相比,这种方法更有效,因为它可以跟踪数据在代码中的移动,定位不安全的模式,并检测出仅通过文本无法发现的漏洞。这样就能更深入地了解代码模式,发现潜在的安全问题。
该团队以各种方式使用 CodeQL 来确保 GitHub 存储库的安全。标准配置使用了默认及安全扩展查询套件,这足以满足企业大多数存储库的需要。这种设置使 CodeQL 可以自动审查 pull 请求是否存在安全问题。
对于某些存储库,比如 GitHub 的大型 Ruby 单体库,就需要额外采取一些措施。在这种情况下,团队会使用为特定安全需求量身定制的查询包。此外,还可以使用多存储库变体分析 (MRVA)进行安全审计,识别需要进一步调查的代码模式。还可以编写自定义查询用于检测 GitHub 代码库特有的潜在漏洞。
最初,自定义 CodeQL 查询是直接发布在存储库中的。然而,这种方法带来了一些挑战,包括每次更新都需要经过生产部署流程、CI 分析速度比较慢以及 CodeQL CLI 更新导致的问题。为了应对这些挑战,团队转为在 GitHub 容器注册表(GCR)中发布查询包。这一变化简化了流程,提高了可维护性,并减少了更新查询的阻力。
在开发自定义查询包时,要考虑到依赖关系,如 ruby-all 包。通过扩展默认查询包中的类,团队可以避免不必要的重复,同时保持查询简洁有效。不过,CodeQL 库 API 在更新时可能会带来破坏性的变化,有可能会影响查询性能。为了降低这种风险,团队会针对最新版本的 ruby-all 来开发查询,但在发布前会锁定特定的版本。这样就能确保已经部署的查询可以可靠地运行,而不会因意外更新而产生意想不到的问题。
为了保持查询的稳定性,每个新查询都要编写单元测试。这些测试被集成到查询包存储库的 CI 管道中,以便可以在部署前尽早发现潜在的问题。发布过程涉及多个步骤,包括打开 pull 请求、编写单元测试、合并更改、增大查询包版本号、解决依赖性问题以及将更新后的查询包发布到 GCR。这种结构化方法兼顾了开发灵活性和稳定性需求。
采用何种方法将查询包集成到存储库取决于组织的部署策略。GitHub 安全团队没有在 CodeQL 配置文件中锁定查询包的特定版本,而是选择通过 GCR 管理版本。这种方法使存储库可以自动使用最新发布的版本,同时在必要时提供快速回滚更改的能力。
在 GCR 中发布查询包时,他们遇到的一个挑战是如何确保组织内多个存储库的可访问性。他们考虑了几种解决方案,包括手动授予访问权限、使用个人访问令牌以及将存储库链接到软件包以获得继承访问权限。最终,团队采用了链接存储库的方法,无需人工干预即可有效管理多个存储库的权限。
为加强安全分析,GitHub 安全团队编写了各种自定义查询。这些查询的重点是识别高风险 API、执行安全编码实践,以及检测 API 端点中缺失的授权控制。有些查询是告警工具,而不是严格的执行机制,它们只会使用较低的严重性级别来提醒工程师,而不会阻止部署。这种方法允许开发人员评估安全问题,同时又能确保及时处理最关键的漏洞。
声明:本文为 InfoQ 翻译,未经许可禁止转载。
原文链接:https://www.infoq.com/news/2025/03/how-github-uses-codeql-security/
评论