Repository navigation
Security dependencies: patched releases, streaming archives, no loopback trust - #1
Merged
Merged
Conversation
setup-go read the version from go.mod, which pins exactly go 1.26.0, so CI ran without the standard library security fixes shipped in later 1.26 patches (crypto/tls, net/http, html/template, os, ...). Ask for 1.26 with check-latest so every run picks up the newest patch. The go directive in go.mod is left as is.
golang-jwt/jwt/v4 v4.5.0 -> v4.5.2 (GO-2024-3250, GO-2025-3553), golang-jwt/jwt/v5 v5.0.0 -> v5.3.1 (GO-2025-3553), gorilla/websocket v1.5.0 -> v1.5.3 (GO-2026-6278), sirupsen/logrus v1.9.0 -> v1.9.4. ulikunitz/xz is left alone: it only comes in through archiver/v3, which the next commit removes.
…r/v3 archiver/v3 is unmaintained and carries advisories with no fix (GO-2024-2698, GO-2025-3605); it also pulled in rardecode v1 and xz v0.5.11. Its successor mholt/archives replaces it. GetCompressionAlgorithm keeps its formats and extensions (zip, tar, tar.gz, tar.bz2, tar.xz, tar.lz4, tar.sz) but now returns an archives.Archiver. AddFile no longer writes into an open archive: it appends the entries for a path to a slice, and the caller passes that slice to Archiver.Archive. No service calls these two functions; the CasaOS core has its own copy. Entry names are unchanged: the last element of commonPath followed by the path under commonPath, directories included, commonPath itself not listed. Symlinks used to be followed (os.Stat), so a link could pull in files or whole directories from outside the tree; they are now stored as symlinks. Devices, pipes and sockets are still skipped. A test writes a nested tree, with a symlink leaving it where the OS allows one, as zip and tar.gz and reads both back with the standard library.
JWT() let any request whose RealIP was ::1 or 127.0.0.1 through without a token. The services stopped trusting loopback on 2026-09-13 and now check external.IsInternalRequest with the per-boot secret, and none of them calls jwt.JWT any more (checked CasaOS, AppManagement, LocalStorage, UserService, Gateway and MessageBus). Remove it, with the two tests that only exercised it, so nobody can wire it back in. Validate, the key helpers and JWKSHandler stay. echo-jwt and golang-jwt/jwt/v5 were only needed by this middleware and leave go.mod.
mholt/archives brought in klauspost/compress v1.18.0, which has an out-of-bounds read in its s2 package (GO-2026-5841, fixed in v1.18.7). Our code does not reach it today, but tar.sz goes through s2, so take the fixed release.
archiver/v3 named tar directory entries "dir/" (as tar.FileInfoHeader does); mholt/archives writes "dir". Add the slash in AddFile so tar and zip names stay exactly what they were, and make the test check the raw names.
WriteArchive(ctx, w, format, commonPath, paths) replaces AddFile, which nothing called. It walks each selected path and hands entries to ArchiveAsync as they are found, so the first bytes go out before the walk ends; ctx stops the walk and the writes. GetCompressionAlgorithm keeps its formats and extensions and now returns archives.ArchiverAsync, which all seven implement. Names are unchanged: base(commonPath) plus the place under commonPath, directories with a trailing slash, no entry for a selected commonPath directory. A selected commonPath file is now archived instead of dropped. A selected symlink is followed and its target archived under the link's name, as archiver/v3 did; symlinks inside the tree stay links. A missing or unreadable path, or an empty selection, is an error instead of an empty archive. Files are opened through os.Root at their walk root, non-blocking, and must still be the regular file the walk saw (os.SameFile), so a file swapped for a symlink or another file between the walk and the read is an error, not a read of outside content. A file that shrank is an error too. The output writer records the first write error, which archives drops when its deferred Close fails the final flush, and refuses writes after any error so a failed archive is left unterminated.
The walk moves at the pace of the client downloading, so on a live folder a temporary file renamed or a cache emptied between a directory's listing and the walk reaching it is routine; failing the whole download for it was worse than archiver/v3, whose callers skipped it. The selected path itself going missing is still an error, and so is a file that vanishes after its header was written. Metadata is read with Lstat through the root rather than DirEntry.Info: Windows answers Info from the directory listing, and Lstat keeps the read confined to the tree on every platform. The archiver's early-exit error is wrapped with %w.
The clients oapi-codegen generates, the message bus one first of all, do not go through this module's HTTP helpers and so never sent the secret: a service could not have authenticated to the message bus the day it stops trusting loopback alone. InternalRequestEditor goes to their WithRequestEditorFn and adds the secret to loopback destinations only, leaving any Authorization already set.
WriteArchive's containment relies on os.Root, whose trailing-slash symlink escape was fixed in 1.26.5, and a build on 1.26.0 also carries every stdlib fix since. With 1.26.8 as the floor, whatever builds a service that uses this module switches to a toolchain that has them.
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.
go-version-filepinned the build to go1.26.0 and its stdlib fixes), and the module now requires Go 1.26.8.WriteArchive: entries are fed as the walk finds them, files are opened throughos.Rootand must still be the file the walk saw, write errors and cancellation are returned, symlinks inside the tree are stored as links.JWT()middleware that let any loopback request through is gone; nothing used it.InternalRequestEditorlets generated API clients (the message bus one) send the internal secret, so the message bus can stop trusting loopback alone.govulncheck: no reachable vulnerability left. Opened so the tests run on Linux.