All Posts

Go 版本不一致?别慌,这是特性!

故事的开端:一场“奇葩”的争论 最近,我和一位可爱的同事,因为一个项目的 go.mod 文件,产生了一点小小的“学术分歧”。文件长这样: // go.mod go 1.21.1 toolchain go1.22.9 同事认为这种配置“非常奇葩”,并抛出了一个灵魂拷问:“你本地用 go1.22.9 的工具链编译,线上服务器(CI/CD 环境)用的却是 go1.21 的基础镜像来构建,这能不出问题吗?这不就是经典的‘我电脑上好好的’吗?” 说实话,我一开始还没 get 到他说的“线上版本”是啥,后来才明白他指的是我们项目构建镜像所基于的 golang:1.21。他的核心论点是:开发环境和生产环境的 Go 版本不一致,是危险的。 为了说服我,他甚至搬出了“AI 军师”,进行了一场“人机对话”。 AI 的“第一次接触”:危言耸听 同事提问: go.mod 中 Go 版本与 Toolchain 版本不一致会带来什么问题? AI 回答(摘要版): 哇,这可不得了!当 go 版本和 toolchain 版本不一致时,会引发一系列灾难性后果: 语言语义和编译行为不一致:编译器优化策略不同,二进制文件体积和性能会有差异。 API 可用性错配:旧工具链编译不了新代码,新工具链用了新 API 在旧环境也跑不起来。 依赖解析差异:go mod tidy 的结果可能不一样,go.sum 文件会在不同开发者之间反复横跳。 构建标志和行为变化:CI/CD 和本地产物的可复现性降低。 安全与合规隐患:你可能会错过新工具链里的重要安全修复。 团队协作噩梦:开发者 A 和 B 构建出的二进制文件性能、大小、告警都不同,定位问题难于上青天。 AI 总结: 为了天下太平,请务必保持版本统一!CI 用什么,你就用什么! 好家伙,这说得头头是道,一套组合拳下来,差点就把我打懵了。如果真如 AI 所说,toolchain 这玩意儿不就成了“潘多拉魔盒”? 我冷静下来,心中升起一个巨大的问号:如果版本不一致是原罪,那 Go 团队费那么大劲引入 toolchain 指令,难道是为了好玩吗?

AI 审代码,靠谱吗?

背景:一道出乎意料的笔试题 最近在校招面试中,我发现一道关于 GORM SQL 注入的笔试题,所有人的答案都错了。题目代码大致如下: func UsersHandler(c *gin.Context) { groupId := c.Query("group_id") var group GroupModel // 注意这里的用法 err := DB.First(&group, groupId).Error if err != nil { c.Status(404) return } c.JSON(http.StatusOK, gin.H{ "group": group, }) } 问题是:这段代码是否存在 SQL 注入漏洞? 正确答案是:会。 说实话,这个答案起初也让我感到意外。在日常业务开发中,我们很少会这样直接将变量传给 First 函数。First 通常用于获取按主键排序的第一条记录,更常见的做法是通过 Where 方法来构建查询条件。这不禁让我怀疑:这道题本身是不是有问题? 初探源码:First 函数的内部实现 简单看了一下 First 函数的实现: // First finds the first record ordered by primary key, matching given conditions conds func (db *DB) First(dest interface{}, conds ...interface{}) (tx *DB) { tx = db.Limit(1).Order(clause.OrderByColumn{ Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey}, }) if len(conds) > 0 { if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 { tx.Statement.AddClause(clause.Where{Exprs: exprs}) } } tx.Statement.RaiseErrorOnNotFound = true tx.Statement.Dest = dest return tx.callbacks.Query().Execute(tx) } 从源码看,当 conds 参数不为空时,GORM 会调用 tx.Statement.BuildCondition来处理查询条件。

CVE-2025-55188:7-Zip 任意文件写入漏洞

安全研究员 Landon 发现了一个新披露的 7-Zip 漏洞,编号为 CVE-2025-55188。该漏洞的 CVSS 评分为 2.7,影响 25.01 之前的版本,可能允许攻击者在提取存档文件时执行任意文件写入操作——在某些情况下可能升级为任意代码执行。 根据报告,“在 25.01 之前的 7-Zip 中提取恶意制作的存档文件允许任意文件写入,可能导致任意代码执行。” 该问题源于在提取过程中对符号链接的处理不当。7-Zip 在解压存档文件时会跟随符号链接,这意味着恶意存档文件可以将提取的文件指向预期目录之外的位置——覆盖系统上的关键文件。 漏洞利用需要特定条件: Linux – 任何在 25.01 之前版本的 7-Zip 上运行的用户,提取支持符号链接格式的存档(如 .zip、.tar、.7z、.rar)都会受到影响。 Windows – 漏洞利用是可能的,但较为困难。提取过程必须具有创建符号链接的权限,可能在以下情况下发生: 7-Zip 以管理员权限运行。 Windows 处于开发者模式。 启用了其他特殊权限。 一旦触发,攻击者可能会覆盖敏感文件,如 SSH 密钥或 .bashrc,从而留下持久后门或执行命令。 虽然 CVSS 2.7 的评分可能表明严重性较低,但如果攻击者可以控制存档文件的内容和目标的提取环境,其影响可能很严重。Landon 警告称,“在一次提取过程中,攻击者可能多次尝试利用此漏洞写入敏感文件。” 此类攻击可能: 破坏安全外壳 SSH 认证。 修改启动脚本以实现持久化。 篡改配置文件以绕过安全控制。 修复已包含在 7-Zip 版本 25.01 中。用户应: 立即从官方 7-Zip 网站更新至 25.01 或更高版本。 避免从不信任来源提取存档文件。 处理未知文件时使用沙盒或隔离环境。 相关文章: CVE-2025-0411: 7-Zip 安全漏洞可导致代码执行 – 立即更新 7-Zip 中的两个漏洞可能触发拒绝服务攻击 7-Zip CVE-2025-0411 的 PoC 允许攻击者绕过 MotW 并运行恶意代码 CVE-2025-0411: 针对乌克兰的攻击中利用了 7-Zip 漏洞 CVE-2022-29072: 7-Zip 权限提升漏洞

mac mini,真香?

距离上次换 iMac 2020 已经有4年多的时间。最近 mac 国补的价格,感觉不买就在亏钱一样。本来是在 iMac 和 mac mini 之间犹豫,但是现在新版本的 iMac 只有 24 寸,并且只有 4.5 k。另外还有一个重要的问题是京东没有 vesa 版本的 iMac,但是我只想买 vesa 支架友好的显示器。后来,又听同事说 m4pro 芯片是 m4 芯片性能的将近2倍。果断拿下了 mac mini m4pro 丐版配置,m4 pro (24 G 内存 + 512 G 存储)。对于来说基本足够了,苹果的内存是黄金做的,实在是加不起。 更换 mac mini 之后,最大的问题就是显示器了。之前是 iMac + studio display 的配置,但是市面上 5k 显示器的选择屈指可数。如果降级选择 4k 选择器感觉反而越来越次了,而且太次的 4k 显示器我也看不上。参考了市面上的几款主流的 5k 显示器作对比: 5K显示器横向对比(5120×2880分辨率) 优缺点 未来视野 RV100 优派 VP32UQ 酷优客 Pro5K 三星 UR55 优点 价格便宜,性价比高 品牌有保证,综合素质可以 外观最好看,vesa支架友好,性价比较高 品质有保证 缺点 品质不稳定,容易踩坑 外形老土,外接电源,雾面屏 新品牌 性价比低,外接电源,不如加钱上 studio display 其实对比几款显示器,其实优缺点都挺明显的。优派的显示器我是拿到手体验了,然后的确是有两个大的方面我是接受不了,一个就是雾面屏,另外就是那么大的外接电源。显示器最恶心的缺点就是外接电源,和板砖一样难受,所以外接电源一律是不考虑。

通过 Cookie Tossing 劫持 OAUTH 流程

原文:Hijacking OAUTH flows via Cookie Tossing 译者:madneal welcome to star my articles-translator, providing you advanced articles translation. Any suggestion, please issue or contact me LICENSE: MIT 我们最近在瑞士苏黎世的Area41会议上展示了我们的 GitHub Action 研究。在会议的第一天,Thomas Houhou 进行了一个有趣的演讲,介绍了如何利用 Cookie Tossing 攻击来增强 Self-XSS 问题的影响,使其变得值得报告。这次演讲非常精彩,展示了一些新颖的 Cookie Tossing 在劫持多步骤流程中的应用。作为一种技术,Cookie Tossing 常常被忽视或不为人知,关于这一主题的发表内容也很少。 我们希望扩展目前有限的研究,看看 Cookie Tossing 攻击还可能导致哪些额外的影响。我们发现,Cookie Tossing 可以用来劫持 OAUTH 流程,并导致身份提供者(IdP)的账户接管。 什么是 Cookie Tossing? Cookie Tossing 是一种技术允许一个子域名(例如 securitylabs.snyk.io)在其父域名(例如 snyk.io)上设置 cookie。在我们查看一些问题场景之前,先来了解一下 HTTP cookie 是什么。 什么是 HTTP cookies? 根据 RFC 6265 的定义,Cookie 是服务器与用户的网页浏览器之间交换的一小段数据。这些 Cookie 对于网络应用至关重要,因为它们能够存储有限的数据并帮助维护状态信息,从而解决 HTTP 协议固有的无状态特性。通过 Cookie,用户会话可以持续,偏好设置可以被保存,并且可以提供个性化的体验。

NilAway:实用的 Go Nil Panic 检测方式

原文:NilAway: Practical Nil Panic Detection for Go 译者:madneal welcome to star my articles-translator, providing you advanced articles translation. Any suggestion, please issue or contact me LICENSE: MIT Uber 由于 Go 语言的高性能,广泛采用其作为实现后端服务和库的主要编程语言。Uber 的 Go monorepo 是 Uber 最大的代码库,包含 9000 万行代码(并且还在增长)。这使得编写可靠 Go 代码的工具成为我们开发基础设施的重要组成部分。 指针(保存其他变量的内存地址而不是其实际值的变量)是 Go 编程语言的一个重要组成部分,有助于高效的内存管理和有效的数据操作。因此,程序员在编写 Go 程序时广泛使用指针,出于多种目的,如原地数据修改、并发编程、数据共享优化、内存使用优化以及支持接口和多态性。虽然指针功能强大且被广泛使用,但必须谨慎和明智地使用它们,以避免诸如空指针解引用导致的 nil panic 等常见陷阱。 nil panic 问题 nil panic 是指程序尝试解引用一个 nil 指针时发生的运行时 panic。当一个指针为 nil 时,意味着它不指向任何有效的内存地址,尝试访问它指向的值将导致 panic(即运行时错误),错误信息如图 1 所示。 图 2 显示了在实现 Go 标准库(特别是 net 包)中发现并解决的最近一次 nil panic 问题 的示例。由于在第 1859 行直接调用了方法 RemoteAddr() 的返回值上的 String() 方法,假设它总是非 nil 的,如图2所示,从而引发了 panic。当接口类型 net.Conn 的字段 c.rwc 被分配给结构 net.conn 时导致了这个问题,因为如果发现连接 c 异常的话,它的 RemoteAddr() 的具体实现可以返回 nil 值(如图 3 所示)。具体来说,RemoteAddr() 可以在 L225 返回一个 nil 接口值,当被调用方法(.String())时,由于 nil 值不包含任何指向可以调用的具体方法的指针,从而导致 nil panic。

Home Assistant 小米门铃视频本地存储

小米的门铃,免费的云存储时间只有 72 小时,希望保存更多时间的视频,只能去充钱。后来网上搜了一下,通过 Home Assistant 的小米插件可以实现这样的功能。刚好家里有一台闲置的 Macbook 用来发挥余热不是刚好。其实我之前已经安装好了,只不过手残把镜像文件删掉了,这样刚好出个教程从头来一次。 Home Assistant 安装 Home Assistant 支持多种安装方案,不过他们主推的是他们自己的一款软硬件一体的方案。其实家里是有一台软路由的,不过软路由担心把网络搞出问题,还是选择使用那台闲置的 Mac。官网里面也包含了 MacOS 的安装方案。因为 Home Assistant 用的是比较低版本的 Linux 系统,所以基本都还是需要使用虚拟机。首先需要安装 VirtualBox。另外就是需要下载 Home Assistant 的镜像文件。对于虚机,有一个推荐的配置,下面都以贴图的形式展现。 这个步骤里面的虚拟硬盘,记得需要使用前面下载下来的 vdi 文件。 接着需要把虚机的网络里面去配置桥接,官方文档里面说必须要使用有线连接网络,但是我的笔记本使用 WIFI 也没有什么问题。 系统全都配置好了之后,就直接启动系统,等待系统初始化好后即可。系统初始化好后,即可进入页面 http://homeassistant.local:8123/ 。一般进入页面的时候可能还需要等待一段时间初始化。 初始化完成后,创建账户。 选择家庭地址 进入主页 以上就是 Home Assistant 的安装,主要就是一个虚机的配置,其它基本只要下一步就可以。不过这个还是只是第一步,还需要安装 HACS,它是一个插件商店,通过这个商店才可以去安装小米的插件。 HACS 安装 HACS 需要尝试通过终端去安装,我尝试过直接在虚机里面去直接执行命令,但是是不可以的。需要安装终端插件去执行命令,这里我推荐使用 Terminal & SSH 插件,比另外一款插件好用,另外一款插件总是初始化失败。在设置里面,找到 Add-ons,然后在 ADD-ON 商店里面去搜索,不过这里有一个坑是默认搜不到这个插件的,需要在设置里面把高级模式打开。 插件安装好了,可以参考官方文档去安装 HACS。按照 Terminal 插件之后就可以直接执行命令: wget -O - https://get.hacs.xyz | bash - 安装完毕后,需要重启一下 Home Assistant,可以直接在终端里面通过 reboot 来进行重启。安装重启之后,还需要在 Settings > Devices and Services > Add Integration > HACS 里面添加一下。因为 HACS 需要使用 github 去更新,你可能还需要一个 github 账号来进行配置,输入验证码后,即配置成功。

大佬,您这是在借鉴嘛

今天闲来没事看到一篇文章,感觉质量挺好的,就想翻译一下。之前写过一个将文档导出成 markdown 的插件,因为这个插件一开始是为了翻译 Medium 文章开发的,但是后来因为 Medium 的 json 接口启用了,所以这个插件后面也不怎么维护了。不搜不知道,一搜吓一跳,居然发现一个和插件差不多的插件,不会吧,这么烂的插件也有人抄?后来仔细看了一看,这个大佬应该是在借鉴我的插件,辛苦地改了几个中文。 两款插件名名字几乎一模一样,只是这个借鉴者加了一个后缀:掘金翻译计划版。不确定和掘金有没有关系,我知道掘金是有一个翻译项目的,以前我也参与过。 对比 插件介绍 我的插件 李鬼插件 代码对比 上面的简洁基本上已经展现了浓重的李鬼味道,本着客观严谨的态度,我还是去看了一下代码。 我的插件 李鬼插件 除了一个 js 文件的引用,几乎可以说是一模一样了。核心的文件是 widget.js 这个文件,这个属于插件自身的 js 文件。 从这代码对比,可以看得出这个借鉴者巨大的工作量。 总结 鄙人的这款插件是在 GitHub 上开源的,当时也是出于个人需求搞得这么个小玩意,但是没想到居然还有李鬼借鉴,还真是离谱他妈给离谱开门。大家如果有空的话,还是动一下发财的小手点一下 Report,这个李鬼插件还是下架比较好。我也联系了这个开发同学,希望他能及时下架。

如何使用 Git 撤消(几乎)任何操作

原文:How to undo (almost) anything with Git 译者:madneal welcome to star my articles-translator, providing you advanced articles translation. Any suggestion, please issue or contact me LICENSE: MIT 任何版本控制系统最有用的功能之一就是能够“撤消”错误。在 Git 中,“撤消”可能意味着许多略有不同的事情。 当你进行新的 commit 时,Git 会及时存储你的仓库在该特定时刻的快照;之后,你可以使用 Git 返回到项目的早期版本。 在这篇文章中,我将介绍一些你可能想要“撤消”所做更改的常见场景,以及使用 Git 执行此操作的最佳方法。 撤销一个“public”修改 场景: 你刚刚运行了 git push,将你的修改 push 到 GitHub,现在意识到有一个 commit 有问题。你想把这个 commit 撤销。 撤销: git revert <SHA> 结果: git revert 将创建一个与给定 SHA 相反的新 commit。如果旧 commit 是“matter”,则新 commit 是“anti-matter”——旧 commit 中删除的任何内容都将添加到新 commit 中,而旧 commit 中添加的任何内容都将在新 commit 中删除。

Google Drive 的信息检索

对于使用 Google 全家桶的公司,Google 文档类的信息泄露也时常发生。出现这种情况主要的原因是文档的权限设置问题,用户可能将文档配置为 anyoneCanFind, anyoneWithLink, domainCanFind, domainWithLink,这四种权限都属于比较公开的权限。后两个属于在域内可以查看到文档,一般来说也是不提倡如此设置,尤其是文档中包含敏感信息的。 Auth 如果要使用 Google Drive 的 API,毫无疑问,Google Workspace 的 Auth 则是第一步。对于 Auth,一般可以通过 OAuth 或者 service account 来进行实现,但是 service account 有一个问题是,默认这个 service acount 并没有赋予这个 servive account 这个域内所有资源的访问权限。必须要将这个文档分享给 service account,它才可以访问。这将会影响到对于 domainCanFind 以及 domainWithLink 的文档的搜索。解决办法是需要 delegate domain-wide authority,相当于是对于这个 service account 进行额外的授权,详细的介绍可以参考这个文档。当然,这个授权需要管理员账号来进行,如果申请比较麻烦的话,还可以通过使用 OAuth 的方式来进行认证,这也是 Google Drive API 文档指引中介绍使用的方式。 通过 OAuth 来使用 Drive API 也需要三个步骤: 启用 API 配置 OAuth 应用 生成 Credentials 详细介绍可以参考谷歌的文档介绍,基本上每一步都有详细的介绍。建议可以按照文档的方式来进行操作,OAuth 生成方式会用到一个 credentials.json 文件。如果对 OAuth 流程比较了解的话,应该知道流程中会有一个授权的流程。Go 的官方文档已经提供了一个授权的 demo,通过运行代码可以获取 autorization code,通过 aurhorization code 可以生成 token.json。对于内部应用,生成的 token.json 包含 refresh_token 的话,这个 token 是不会过期的。