Commit 2bb8cd7
committed
backup: PR810 r2 — codex r2 P1 (symlink escape on VerifyChecksums)
Codex r2 P1: after the r1 textual `..`-traversal guard,
VerifyChecksums still followed symlinks when sha256-ing the
joined path. A CHECKSUMS line `<hex> safe/file` could direct
the verifier to hash a host file outside the dump root via a
planted symlink at `safe/file` (or any intermediate parent).
Fix: refuseSymlinkComponents walks the relative path segment by
segment from root, os.Lstat()s each component, and returns
ErrChecksumsSymlinkEscape the moment any component is a
symlink. Catches BOTH terminal symlinks AND intermediate ones
(a parent directory along the way being symlinked). The
per-component walk is stricter than syscall O_NOFOLLOW (which
only covers the terminal case) and avoids the
filepath.EvalSymlinks resolution we are trying to refuse.
Phase 0a dumps contain only regular files by design, so
refusing every symlink found in the path is the right policy
for the only honest dump shape.
Tests:
- TestVerifyChecksums_RejectsTerminalSymlink — plant a symlink
at safe/escape pointing at a host file, add a CHECKSUMS line
for it; assert ErrChecksumsSymlinkEscape.
- TestVerifyChecksums_RejectsIntermediateSymlink — plant a
symlink at safe/ (a directory link to an outside dir),
reference safe/target.txt in CHECKSUMS; same assertion.
- Both tests skip on Windows (os.Symlink requires
SeCreateSymbolicLinkPrivilege there; the lstat-walk fix
itself runs on every platform).
Caller audit (CLAUDE.md "semantic-change → grep all callers"):
- refuseSymlinkComponents is only called from
verifyOneChecksumLine, which is only called from
VerifyChecksums. VerifyChecksums has no production callers
(test-only); CLI uses WriteChecksums.
Self-review:
1. Data loss — none (read-side hardening).
2. Concurrency — none.
3. Performance — one extra Lstat per path component during
verify; verify is offline-only and rare.
4. Data consistency — symlink-escape closed.
5. Test coverage — two regression tests (terminal + intermediate
symlink); existing five-shape traversal-path table test
still passes.1 parent b60f468 commit 2bb8cd7
2 files changed
Lines changed: 136 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
187 | 187 | | |
188 | 188 | | |
189 | 189 | | |
190 | | - | |
191 | | - | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
192 | 193 | | |
193 | 194 | | |
194 | 195 | | |
| |||
201 | 202 | | |
202 | 203 | | |
203 | 204 | | |
204 | | - | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
205 | 210 | | |
206 | 211 | | |
207 | 212 | | |
| |||
211 | 216 | | |
212 | 217 | | |
213 | 218 | | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
214 | 261 | | |
215 | 262 | | |
216 | 263 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
158 | 159 | | |
159 | 160 | | |
160 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
161 | 247 | | |
162 | 248 | | |
163 | 249 | | |
| |||
0 commit comments