Match flea's O_NOFOLLOW fix by behaviour, not by spelling (#488)

Upstream sync has failed on every run since flea v0.3.0 was published, with
"Release v0.3.0 does not contain every required upstream security fix". Eight
of the nine required fixes are present. The ninth is too: the check is wrong.

The check pinned the literal call `regfile::open_if_regular(src, O_NOFOLLOW)`.
v0.3.0 introduced directory-relative opens and the first argument became
`src.at`. O_NOFOLLOW is still passed to the same function, on the same line,
under the same comment, and the release hardened symlink handling further --
it added copy_symlink_at, opens directories with O_DIRECTORY | O_NOFOLLOW, and
reaches every child through this process's own descriptor. The guard refused a
release that is strictly safer than the one it accepted.

The property worth asserting is that the copy opens its source with
O_NOFOLLOW, so a symlink swapped in cannot redirect the read. Pinning the
exact expression asserted the spelling instead, which is why a rename read as
a removed fix. The check now matches the call and the flag together.

Verified against the real archives rather than by inspection:

  v0.3.0 (src.at, O_NOFOLLOW)      accepted
  v0.2.1 (src, O_NOFOLLOW)         accepted, so the change is backwards
                                   compatible with what is packaged today
  first argument renamed           accepted
  extra flag or argument added     accepted
  O_NOFOLLOW dropped               refused
  call replaced with File::open    refused
  flag left only in a comment      refused

End to end with the real feed: the hook on master exits 1 with the refusal,
and with this change exits 0 and reports 0.3.0 with its verified checksum.
The other eight literals are untouched.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
OmarchybotandClaude Opus 5 authored and GitHub committed 2026-09-17 12:40:45 +02:00
1 parent 72b7998935
commit ce33f28414
1 file changed
+9 -1
+9 -1
View File
@@ -85,6 +85,14 @@ sharelink_qml=$(tar -xOzf "$tarball" "$expected_root/ui/ShareLink.qml")
copyfile_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/copyfile.rs")
regfile_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/regfile.rs")
# Every check below pins a literal line except the O_NOFOLLOW one. That check
# guards a property -- the copy opens its source with O_NOFOLLOW, so a symlink
# swapped in cannot redirect the read -- and pinning the exact call expression
# made it assert the spelling instead. v0.3.0 moved the first argument from
# `src` to `src.at` when directory-relative opens landed, kept O_NOFOLLOW, and
# hardened symlink handling further; the literal still refused it. Match the
# call and the flag together so a rename cannot read as a removed fix, while
# dropping O_NOFOLLOW still fails.
if ! grep -Fq 'a.push("--".to_string());' <<<"$archive_rs" ||
! grep -Fq 'let input = std::fs::canonicalize(input)' <<<"$archiveops_rs" ||
! grep -Fq 'if op != "compress" && op != "extract"' <<<"$run_rs$archivereq_rs" ||
@@ -92,7 +100,7 @@ if ! grep -Fq 'a.push("--".to_string());' <<<"$archive_rs" ||
! grep -Fq 'if !sandbox::available()' <<<"$mediaprobe_rs" ||
! grep -Fq 'if !sandbox::available()' <<<"$metareq_rs" ||
! grep -Fq 'copyToClipboard.command = ["wl-copy", url]' <<<"$sharelink_qml" ||
! grep -Fq 'regfile::open_if_regular(src, O_NOFOLLOW)' <<<"$copyfile_rs" ||
! grep -Eq 'open_if_regular\(.*O_NOFOLLOW' <<<"$copyfile_rs" ||
! grep -Fq '.custom_flags(O_NONBLOCK | extra_flags)' <<<"$regfile_rs"; then
printf 'Release %s does not contain every required upstream security fix\n' "$best_tag" >&2
exit 1