跳转至

危险指令

这个项目里有一类命令必须被单独看待:危险命令。

什么叫危险命令

危险命令通常具有以下特征之一:

  • 会删除文件;
  • 会覆盖工作区内容;
  • 会改写 refs;
  • 会批量写对象;
  • 会对仓库状态做不可逆前进。

典型例子包括:

  • reset --hard
  • checkout
  • switch
  • rm
  • stash pop
  • update-ref
  • pack 解包
  • fetch / push / clone 中的目标路径和 ref 更新

为什么它们必须单独设计

因为这类命令的 bug 代价很高。
它们不像普通文本处理逻辑,出错了可以重试一下就过去。
出错时,最坏情况可能是:

  • 用户文件被删;
  • 仓库状态半写入;
  • 分支指针错误移动;
  • 工作区和 index 脱节。

必须做哪些保护

最关键的保护包括:

  • 路径必须在仓库内部;
  • 防止 .. 路径逃逸;
  • 防止绝对路径误操作;
  • 防止符号链接逃逸;
  • 删除前确认文件是可解释的追踪文件;
  • 删除前确认目标对象和 tree 是可读的;
  • 用锁文件和原子替换保护元数据写入。

项目把这些保护写进工程要求,是因为“事后补安全”通常补不干净。