意外提交敏感信息 - GitLab

2024-04-06

我不小心提交了包含敏感数据的文件。我需要通过删除敏感数据来更新该文件,并确保旧版本不会出现在历史记录中。

据我所知,那些在本地克隆了存储库的人仍然可以访问它。但是,一旦他们提取最新的数据,是否可以通过设置方式让他们看不到敏感数据继续前进或无法在日志中看到它?


虽然 GitLab 通常不像 GitHub 那样公开,但有关数据的一般规则适用于此:如果您已将敏感/秘密数据提供给不可信的人,那么您的秘密已经泄露,您应该停止依赖它。

这意味着关键问题不是——或者至少现在不是——“我如何说服 GitLab 忘记我的秘密”,而是“我是否完全、完全信任 GitLab 服务器和其他有权访问的人”一直都是那些服务器?”如果答案是否定的,你无论如何都必须停止依赖这个秘密。

也就是说,这里有关于如何进行的规则Git 本身存储数据。假设您的 GitLab 服务器正在使用onlyGit(而不是在它们之上构建的一些其他东西可能会添加更多访问数据的方式,从而为您的敏感/秘密数据泄露提供更多方式),您所要做的就是说服 GitLab 服务器做同样的事情你会在你自己的 Git 中做。

Git's underlying storage model is that a repository is a collection of what Git calls objects. Each object has a unique hash ID, and is one of four types: blob, tree, commit and annotated tag. A blob is, roughly, file data. If the sensitive / secret data are inside a file, they are actually inside a blob object. A tree pairs up—well, more than pair, but let's use that for now1—each file's name with its blob hash ID, so if the file's name is the sensitive / secret data, your secret is actually inside a tree object. A commit object contains your name, email address, time stamp, log message, and the hash ID of some previous or parent commit(s), along with the hash ID of the tree that holds the files that make up the snapshot that is that commit. An annotated tag object holds much the same as a commit except that instead of a tree object, it usually has the hash ID of a commit; this is where one usually stores a PGP signature marking some particular commit as "blessed" and, say, called version 2.3.4 or whatever.

假设您的秘密位于一个特定文件中,该文件的名称本身并不是秘密,此时您的目标是使 Git 停止使用保存该特定文件数据的 blob。为此,您必须使对象本身变成未引用的,然后使用git gc让 Git 物理删除未引用的对象。此时,一旁长成可达性总的来说很有用,但我会把它外包给像 Git 一样思考 http://think-like-a-git.net/。在这里我们就说一下,一般来说,在你不小心提交了一些秘密文件之后,Git 会如何查找commit对象正在使用分支名称:

... <-F <-G <-H   <--master

The name master包含hash ID提交的H。犯罪H包含其父提交的哈希 ID,commitG,这样 Git 才能找到提交G,它从读取名称开始master(生成哈希 IDH)然后从数据库读取提交对象(这会产生一个tree物体和一parent提交哈希值,G,以及日志消息以及您的姓名和电子邮件地址等),抛出除哈希值之外的所有内容G,然后读取实际的提交对象G从数据库中。如果您要求 Git 获取某个特定文件(或更准确地说,该文件的内容)from commit G,然后它使用G的树来查找包含该文件的 blob 的哈希 ID,然后从数据库中获取 blob 对象,现在 Git 就拥有了内容。

因此,假设您的秘密数据位于附加到附加到提交的树上的 blob 中H,并且这些相同的数据不在any其他文件——这样就没有树附加到任何other提交将具有该 blob 的哈希 ID。然后,为了使H本身未引用,只需命名即可master指向G代替H:

git checkout master
git reset --hard HEAD~1

现在你有:

...--E--F--G   <-- master
            \
             H   [abandoned]

但同时H has no obviousname 持有其哈希 ID,我们还没有完成:git gc不会——至少不会yet—remove H,这就是事情开始变得复杂的地方。

如果里面有有价值的文件H,我们可以推H一边,使用git commit --amend,进行新的提交I谁的父母是G代替H,并且有master指向I:

... edit files, git add, git commit --amend ...

giving:

             H   [abandoned]
            /
...--E--F--G--I   <-- master

1Technically, each tree entry has:

  • 该条目的mode,一个文本字符串,例如100755 or 100644。该字符串是40000如果条目是子树。
  • 保存文件名的字节字符串,通常采用 UTF-8 编码
  • 与条目相关的哈希 ID

(模式和名称由空格分隔,名称以 ASCII NUL 结尾,而哈希 ID 以 20 个二进制字节编码。当 Git 切换到 SHA-256 时,这一点必须改变。我不知道我认为新的格式尚未确定,但它可以像使用某种模式一样简单0n where n是一个版本号,因为模式是八进制且前导零被抑制,所以现有的树不会有01作为一种模式。或者,它可能是一个 NUL 字节,后跟一个版本号,因为它当前也是一个无效的树条目。)因此,对于子目录,树仅列出子树,对于常规文件,有两个值加上一个哈希。对于符号链接,哈希 ID 仍然是 blob 的哈希 ID,但 blob 的content is the target符号链接;对于子模块的 gitlink,哈希 ID 是commitgit 应该git checkout在子模块中。


主要的并发症是 reflogs

Git 的部分does记住H为了你,即使在你之后git reset它消失了,这就是 Git 所说的reflogs。转发日志会记住previous的参考值。也就是分支名称master可能指向H 现在,在我们之前git reset它。然后它指向G or I 现在,我们使用后git reset --hard or git commit --amend放弃提交H。但它used to指向H, so H的哈希 ID 位于名称的引用日志中master.

The @{1} or @{yesterday}语法是告诉 Git 查找这些引用日志值的方式。写作master@{1}告诉你的 Git:看看我的masterreflog,并获取之前的值master.该条目存在的事实将使您的 Git 保留提交H这将使您的 Git 保留包含秘密的 blob。

事实上至少有two包含提交哈希 ID 的引用日志H: 一个用于master, in master@{1},还有一个用于HEAD本身。所以如果你要说服你的 Git 真正放弃提交H,因此丢弃该树H,因此丢弃树特有的任何斑点H,您必须让这些引用日志条目消失。

Normally, they go away on their own, generally after about 30 days. This happens because each reflog entry has a time-stamp as well, and git reflog expire will expire—and remove—old reflog entries based on this time-stamp, vs the current time on your computer. The master git gc command runs git reflog expire for you, and sets it up to expire unreachable commits2 in 30 days by default. (Reachable commits get 90 days by default.) So on your own Git, you would need to run:

git reflog expire --expire-unreachable=now --all

告诉你的 Git:查找所有无法访问的提交,例如H并立即使他们的转发条目过期。


2Technically, it's unreachable from the current value of the reference. That is, Git is not going to test a global reachability here, but rather do a somewhat simpler test: does this reflog entry point to a commit that is an ancestor of the commit to which the reference itself points right now?


第二个复杂因素是对象修剪宽限时间

即使双方的引用日志条目都已过期HEAD和分支名称,你会发现你自己的git gc不会立即丢弃 blob 对象。原因是allGit 对象有一个宽限期,在此期间git gc不会把它们修剪掉。默认宽限期为 14 天。这给出了allGit 命令在一段时间内可以创建对象而无需担心它们,只要它们finish他们在这 14 天内的所有工作,方法是将所有这些对象链接到提交或标记对象或其他对象中,并使用适当的引用名称(例如分支或标记名称)记录该对象的哈希 ID。

为了让你不小心犯下的blobH走开,那么,您不仅需要使无法访问的引用日志条目过期,还需要告诉 Git 修剪对象,即使它们是zero天数:

git prune --expire=now

这个修剪步骤是git gc实际上删除了该对象,因此通过运行git prune,您无需运行git gc. (git gc还运行 reflog expire 等,但协调一切以确保 Git 有这些宽限期。由于我们绕过了所有宽限期,所以我们只是绕过git gc以及。)

确保执行此操作时没有其他 Git 命令正在运行,因为它们可能会创建期望在完成工作时持续 14 天的对象。

最后一个复杂因素是包文件

如果你的秘密存储在 Git 所谓的loose对象,上述步骤就足够了:该对象将完全消失,并且:

git rev-parse <hash-ID>

将不再找到该对象。此 Git 存储库中的任何位置都不再提供它。

But not all objects are loose. Eventually, to save space, Git packs these loose objects into pack files. Objects stored inside pack files get compressed against other objects in the same pack file.3 In this case, if your secret data have become packed, it's possible to retrieve them from the pack file.

这通常不会很快发生,因此很少会在包文件中出现刚刚提交的秘密。但如果它has发生了,清理它的唯一方法是让 Gitre-pack所有现有的包文件。也就是说,您可以让 Git 将包分解为其组成的松散对象,然后丢弃不需要的对象,然后构建一个新的(通常是单个)包文件,或者至少使用具有该效果的进程。重建包的 Git 命令是git repack它有很多选择。由于时间有限,我不会在这里讨论更多细节。


3In thin packs, objects may be compressed against other objects in the repository that are not in the pack file, but thin packs are used only for fetch and push operations, after which they're "fattened up" by adding the missing bases back.


服务器通常没有重新日志

为了处理所有这些,您需要能够登录到 GitLab 服务器,因为这些维护 Git 命令(也不是 BFG,见下文)都不能通过 fetch 或 push 调用。特别是,虽然您可以使用git push -f来自您的客户的名字master在服务器上不再指向提交H,你不能调用git prune使松动的物体消失。

如果并且当你do登录服务器,您可以检查您的存储库是否启用了引用日志。如果没有,则无需执行任何重新记录到期操作。您还可以通过查看物品来了解物品是否松散或包装。.git/objects目录。如果您的 blob 哈希 ID 是,0123456789...它将存在于一个名为的文件中.git/objects/01/23456789...。一旦它被取消引用和修剪,该文件就会消失,您就完成了。

使用 BFG 仓库清理器

您可以通过使用来避免很多并发症BFG 回购清理器 https://stackoverflow.com/q/49580624/1256452。 BFG 无论如何都不尊重任何宽限期,因为它有不同的目的。这也可以解决任何包文件问题。与其他方法一样,这必须在服务器上运行,并且它有自己的怪癖(请参阅链接的问题和答案)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

意外提交敏感信息 - GitLab 的相关文章

  • 有没有办法缓存 https 凭据以推送提交?

    我最近转而将我的存储库同步到 GitHub 上的 https 由于防火墙问题 并且每次都要求输入密码 有没有办法缓存凭据 而不是每次都进行身份验证git push 自 Git 1 7 9 2012 年发布 以来 Git 中有一个巧妙的机制可
  • 如何在 Windows 上向 git 存储库添加符号链接?

    我使用 GitHub 的电子环境编译 OS X 的二进制文件 并希望将输出添加到 git 存储库 我试过 git add error readlink sulu app Contents Frameworks Electron Framew
  • git subtree pull -P 不管 总是合并冲突

    问题 即使我没有进行任何更改 每次尝试拉入子树时 我都会遇到合并冲突 我在做什么 In 子树仓库 Make some changes git commit am Changes made git push origin master In
  • 在推送到容器注册表之前如何对构建的映像运行测试?

    从 gitlab 文档中可以看出如何使用 kaniko 创建 docker 镜像 build stage build image name gcr io kaniko project executor debug entrypoint sc
  • 使用 TFS 个人访问令牌克隆 Git 存储库

    我正在尝试以编程方式克隆 git 存储库 我的 ASP NET MVC 应用程序正在创建并启动一个进程 处理进程的代码工作正常 但是当尝试使用本地 TFS PAT 克隆 git 存储库时 身份验证失败 我无法使用 NTLM 或要求用户输入凭
  • Git 不断提示我输入密码

    我已经使用 Git 一段时间了 但是不断要求输入密码开始让我感到厌烦 我使用的是 Mac OS X 和 GitHub 并且按照 GitHub 的说明设置了 Git 和我的 SSH 密钥设置 Git 页面 http help github c
  • 运行“git apply”时出错

    当我尝试时 您能否告诉我如何解决 补丁不适用 错误 git 应用补丁 git apply 0001 my patch error patch failed test xml 114 error text xml patch does not
  • Git:如何变基到特定提交?

    我想变基到特定的提交 而不是另一个分支的 HEAD A B C master D topic to A B C master D topic 代替 A B C master D topic 我怎样才能做到这一点 您可以通过在您喜欢的提交上创
  • 分支明显不同,但提交历史是相同的

    git status告诉我我的分支和我在另一个存储库上开始的分支已经分歧 On branch master Your branch and origin master have diverged and have 13 and 13 dif
  • 如何解决 VSTS 中拉取请求中的合并冲突?

    我已经创建了拉取请求 我进入了这个 批准 按钮不执行任何操作 并且 完成 被禁用 如何解决拉取请求中的冲突 Update 微软刚刚添加了基于浏览器的合并 这可能会让你摆脱小冲突的困境 并提供自 Sprint 150 起改进了不同场景的可视化
  • git pull,忽略深度,如何不拉取整个历史记录?

    我们有一个巨大的多 GB git 存储库 主要是二进制对象 克隆需要几天时间 实际的主分支 没有历史记录 只有大约 20MB 所以我想 深度为 1 的 git 克隆就是解决办法 然而 现在我需要将某人的更新拉到主服务器 我们没有分支 当我拉
  • git Push over sshfs 失败,并显示“关闭 sha1 文件时出错:错误的文件描述符”

    我们使用 sshfs 通过 SSH 安装文件系统 并将其用作 git 存储库协作的远程存储 Mac OSX 10 6 6 到 RHEL 3 服务器 SSHFS 版本 2 2 MacFUSE SSHFS 2 2 0 MacFUSE 库版本 F
  • 第一次使用node.js - “ReferenceError:节点未定义”

    我刚刚安装了node js 我尝试编写应该检查版本的node v 但它不起作用 这是输出 gt node v ReferenceError node is not defined at repl 1 2 at REPLServer self
  • git 别名中的 AWK 语句

    我正在尝试创建一个 git 别名来以特定格式打印日志中的所有拉取请求 但是 我在使用 AWK 删除双空格时遇到问题 这是使用以下命令的 git log 的输出 git log merges grep pull request pretty
  • apt-get 无法在 ubuntu dockerfile 中工作

    我对 docker 相当陌生 正在尝试通过编写自己的镜像来学习 并且目前正在阅读 Docker 的实际操作 ISBN 1633430235 在我自己的代码和书中的示例 第 146 页 中 我想通过 dockerfile 安装 git My
  • 如何将工作树与提交进行比较?

    我在用着 git diff mycommit 用于比较我的工作树mycommit 但它似乎忽略当前索引中不存在的文件 您可以按如下方式重现它 git init echo A gt A txt git add git commit m A g
  • git 日志历史记录图,每次提交一行,彩色,带有日期

    我需要的格式如下 git log decorate graph oneline date order 但我也需要它 包含日期 短 具有相同的颜色 I tried git log decorate graph oneline date ord
  • GIT:以下未跟踪的工作树文件将被签出覆盖

    我有两个分支 一个称为 master 另一个称为 dev 我目前位于 master 分支 我想转到 dev 分支将文件移动到开发服务器 但是当我执行 git checkout dev 我收到消息 以下未跟踪的工作树文件将被覆盖 查看 pag
  • 当当前分支上有未提交的更改时签出另一个分支

    大多数时候 当我尝试签出另一个现有分支时 如果我在当前分支上有一些未提交的更改 Git 会不允许我这样做 所以我必须首先提交或隐藏这些更改 然而 有时 Git 确实允许我在不提交或存储这些更改的情况下签出另一个分支 并且它会将这些更改携带到
  • Git 提交失败:“请使用 -m 或 -F 选项提供消息。”

    当我键入 git commit 命令来提交文件时 我收到以下错误消息 Microsoft Visual Studio 微软 找不到命令 错误 核心编辑器 Microsoft Visual Studio 存在问题 请使用 m 或 F 选项提供

随机推荐