fix(client): upload an attachment through the root that checked it - #198
Merged
Merged
Conversation
Answers #186: open an attachment through the os.Root that checked it, and verify the upload sends the bytes whose checksum it records.
Closes #186. The converter checks an image through the documentation root's os.Root, but the checksum and the upload opened it by absolute path, so a directory on that path replaced by a symbolic link in between could make markfluence upload a file from outside the root (S2). LocalAttachment now carries the root (json:"-") and an Open method that reads Source through it; the converter sets it. attachment-upload's files have no root, since the person named them on the command line. Either way the open is non-blocking and the handle must be a regular file. The upload also hashes what it sends and refuses, sending nothing, when the bytes no longer match the checksum taken while planning: the comment would otherwise misdescribe the attachment's content.
- Open refuses a symbolic link inside the root, not only one out of it: os.Root follows an in-root link, and markfluence follows none, so a link swapped in at an image's name could publish an in-root .env under it. After opening it re-Lstats the name and requires os.SameFile with the handle. - An escape reads as "outside the documentation root", the converter's wording, rather than os.Root's bare error, which read as a disk failure. - A file changed between planning and upload no longer fails the publish: uploadAttachment reads it whole and stamps the comment with the checksum of the bytes it sends. This replaces the plan's D5. - uploadAttachment drops its duplicate local names, and the CLAUDE.md sentence moves out of the parenthetical it landed in.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #186.
The converter checked each image through the documentation root's
os.Root, but the checksum and the upload then opened it by absolute path. That made three lookups, and only the first was bounded. A directory on the path replaced by a symlink between the check and the upload could make markfluence upload a file from outside the root, which S2 (no-read-outside-root) rules out. The plan is_plans/052_upload-through-the-root.md, including what the code review changed.What changed
LocalAttachmentcarries the root (json:"-", socheck --show-html --jsonand the schema are unchanged) and anOpenmethod, which the checksum and the upload both use. With a root,OpenopensSourcethrough it. After opening, it looks up the name again and refuses a symlink, or a name that is no longer the opened file.os.Rootblocks escapes but follows a symlink that stays inside the root, and markfluence follows no symlinks, so without this a link swapped in at an image's name could publish an in-root.envunder that name.attachment-upload. It sets no root, because its files come from the command line rather than from a Markdown reference, and--namelets them live anywhere.os.Root's bare error.Not changed
When a batch of uploads stops partway, the result still omits the uploads that landed before the failure. That predates this PR and is left alone.
Tests
Openrefuses:Openwithout a root opens the file's path.SyncAttachmentsfails on an escape and uploads nothing.make checkpasses.