diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-02-11 00:40:54 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-02-11 00:40:54 +0900 |
| commit | 05a828c47453dc36c8f333b18588299067c34fc7 (patch) | |
| tree | 9cf3bb1b684bd03fd9e79ee734d2a4a8505fe605 | |
| parent | 0061d11f939157e181a908f50b0ffb4c991e0375 (diff) | |
internal/pkg: validate tar pathnames
TContext no longer validates FileArtifact ahead of time, validation outcome is instead determined after consuming the reader to EOF. All data must therefore be treated as untrusted input until the reader is closed.
Signed-off-by: Ophestra <cat@gensokyo.uk>
| -rw-r--r-- | internal/pkg/tar.go | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/internal/pkg/tar.go b/internal/pkg/tar.go index 1215adbd..77e4ee27 100644 --- a/internal/pkg/tar.go +++ b/internal/pkg/tar.go @@ -10,8 +10,7 @@ import ( "io/fs" "net/http" "os" - - "hakurei.app/container/check" + "path" ) const ( @@ -100,7 +99,6 @@ func (e DisallowedTypeflagError) Error() string { // Cure cures the [Artifact], producing a directory located at work. func (a *tarArtifact) Cure(t *TContext) (err error) { - temp := t.GetTempDir() var tr io.ReadCloser if tr, err = t.Open(a.f); err != nil { return @@ -137,14 +135,24 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { } type dirTargetPerm struct { - path *check.Absolute + path string mode fs.FileMode } var madeDirectories []dirTargetPerm - if err = os.MkdirAll(temp.String(), 0700); err != nil { + if err = os.MkdirAll(t.GetTempDir().String(), 0700); err != nil { return } + var root *os.Root + if root, err = os.OpenRoot(t.GetTempDir().String()); err != nil { + return + } + defer func() { + closeErr := root.Close() + if err == nil { + err = closeErr + } + }() var header *tar.Header r := tar.NewReader(tr) @@ -158,9 +166,8 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { } } - pathname := temp.Append(header.Name) if typeflag >= '0' && typeflag <= '9' && typeflag != tar.TypeDir { - if err = os.MkdirAll(pathname.Dir().String(), 0700); err != nil { + if err = root.MkdirAll(path.Dir(header.Name), 0700); err != nil { return } } @@ -168,8 +175,8 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { switch typeflag { case tar.TypeReg: var f *os.File - if f, err = os.OpenFile( - pathname.String(), + if f, err = root.OpenFile( + header.Name, os.O_CREATE|os.O_EXCL|os.O_WRONLY, header.FileInfo().Mode()&0500, ); err != nil { @@ -184,26 +191,29 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { break case tar.TypeLink: - if err = os.Link( - temp.Append(header.Linkname).String(), - pathname.String(), + if err = root.Link( + header.Linkname, + header.Name, ); err != nil { return } break case tar.TypeSymlink: - if err = os.Symlink(header.Linkname, pathname.String()); err != nil { + if err = root.Symlink( + header.Linkname, + header.Name, + ); err != nil { return } break case tar.TypeDir: madeDirectories = append(madeDirectories, dirTargetPerm{ - path: pathname, + path: header.Name, mode: header.FileInfo().Mode(), }) - if err = os.MkdirAll(pathname.String(), 0700); err != nil { + if err = root.MkdirAll(header.Name, 0700); err != nil { return } break @@ -220,7 +230,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { } if err == nil { for _, e := range madeDirectories { - if err = os.Chmod(e.path.String(), e.mode&0500); err != nil { + if err = root.Chmod(e.path, e.mode&0500); err != nil { return } } @@ -228,6 +238,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) { return } + temp := t.GetTempDir() if err = os.Chmod(temp.String(), 0700); err != nil { return } |
