fixing sec issues
Some checks failed
CloudSave/pipeline/head There was a failure building this commit

This commit is contained in:
2025-09-07 01:14:19 +02:00
parent b3232e79d5
commit af11e843a4
13 changed files with 88 additions and 37 deletions

View File

@@ -63,9 +63,15 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
pg := progressbar.New(-1) pg := progressbar.New(-1)
destroyPg := func() { destroyPg := func() {
pg.Finish() if err := pg.Finish(); err != nil {
pg.Clear() slog.Error("failed to finish progressbar", "err", err)
pg.Close() }
if err := pg.Clear(); err != nil {
slog.Error("failed to clear progressbar", "err", err)
}
if err := pg.Close(); err != nil {
slog.Error("failed to close progressbar", "err", err)
}
} }
pg.Describe(fmt.Sprintf("[%s] Checking status...", g.Name)) pg.Describe(fmt.Sprintf("[%s] Checking status...", g.Name))

View File

@@ -30,7 +30,7 @@ func main() {
} }
datastorepath := filepath.Join(roaming, "cloudsave", "data") datastorepath := filepath.Join(roaming, "cloudsave", "data")
err = os.MkdirAll(datastorepath, 0740) err = os.MkdirAll(datastorepath, 0600)
if err != nil { if err != nil {
panic("cannot make the datastore:" + err.Error()) panic("cannot make the datastore:" + err.Error())
} }

View File

@@ -89,7 +89,7 @@ func save(store map[string]credential) error {
Store: store, Store: store,
} }
f, err := os.OpenFile(filepath.Join(datastorePath, "credential.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0740) f, err := os.OpenFile(filepath.Join(datastorePath, "credential.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to open datastore: %w", err) return fmt.Errorf("failed to open datastore: %w", err)
} }

View File

@@ -76,6 +76,7 @@ func NewServer(documentRoot string, srv *data.Service, creds map[string]string,
s.Server = &http.Server{ s.Server = &http.Server{
Addr: fmt.Sprintf(":%d", port), Addr: fmt.Sprintf(":%d", port),
Handler: router, Handler: router,
ReadHeaderTimeout: 2,
} }
return s return s
} }

View File

@@ -66,7 +66,9 @@ func run(updateChan <-chan struct{}) {
for { for {
<-updateChan <-updateChan
if r, ok := repo.(*repository.EagerRepository); ok { if r, ok := repo.(*repository.EagerRepository); ok {
r.Reload() if err := r.Reload(); err != nil {
fatal("failed to reload data: "+err.Error(), 1)
}
} }
h, err := htpasswd.Open(filepath.Join(documentRoot, ".htpasswd")) h, err := htpasswd.Open(filepath.Join(documentRoot, ".htpasswd"))
if err != nil { if err != nil {

View File

@@ -74,13 +74,19 @@ var (
// NewServer start the http server // NewServer start the http server
func NewServer(c config.Configuration) *HTTPServer { func NewServer(c config.Configuration) *HTTPServer {
dashboardTemplate := template.New("dashboard") dashboardTemplate := template.New("dashboard")
dashboardTemplate.Parse(DashboardHTMLPage) if _, err := dashboardTemplate.Parse(DashboardHTMLPage); err != nil {
panic("failed to load template 'dashboard': " + err.Error())
}
detailledTemplate := template.New("detailled") detailledTemplate := template.New("detailled")
detailledTemplate.Parse(DetailledHTMLPage) if _, err := detailledTemplate.Parse(DetailledHTMLPage); err != nil {
panic("failed to load template 'detailled': " + err.Error())
}
systemTemplate := template.New("system") systemTemplate := template.New("system")
systemTemplate.Parse(SystemHTMLPage) if _, err := systemTemplate.Parse(SystemHTMLPage); err != nil {
panic("failed to load template 'system': " + err.Error())
}
s := &HTTPServer{ s := &HTTPServer{
Config: c, Config: c,
@@ -101,6 +107,7 @@ func NewServer(c config.Configuration) *HTTPServer {
s.Server = &http.Server{ s.Server = &http.Server{
Addr: fmt.Sprintf(":%d", c.Server.Port), Addr: fmt.Sprintf(":%d", c.Server.Port),
Handler: router, Handler: router,
ReadHeaderTimeout: 2,
} }
return s return s
} }

View File

@@ -6,7 +6,10 @@ pipeline {
steps { steps {
sh ''' sh '''
go install github.com/securego/gosec/v2/cmd/gosec@v2.22.8 go install github.com/securego/gosec/v2/cmd/gosec@v2.22.8
/var/lib/jenkins/go/bin/gosec ./... go install honnef.co/go/tools/cmd/staticcheck@v0.6.1
/var/lib/jenkins/go/bin/staticcheck ./...
/var/lib/jenkins/go/bin/gosec -exclude="G401,G501,G103" ./...
''' '''
} }
} }

View File

@@ -258,7 +258,7 @@ func (l Service) PullCurrent(id, path string, cli *client.Client) error {
} }
} }
if err := os.MkdirAll(path, 0740); err != nil { if err := os.MkdirAll(path, 0600); err != nil {
return fmt.Errorf("failed to create destination directory: %w", err) return fmt.Errorf("failed to create destination directory: %w", err)
} }

View File

@@ -9,6 +9,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"log/slog"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/url" "net/url"
@@ -220,7 +221,7 @@ func (c *Client) Pull(gameID, archivePath string) error {
req.SetBasicAuth(c.username, c.password) req.SetBasicAuth(c.username, c.password)
f, err := os.OpenFile(archivePath+".part", os.O_CREATE|os.O_WRONLY, 0740) f, err := os.OpenFile(archivePath+".part", os.O_CREATE|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to open file: %w", err) return fmt.Errorf("failed to open file: %w", err)
} }
@@ -275,20 +276,24 @@ func (c *Client) PullBackup(gameID, uuid, archivePath string) error {
req.SetBasicAuth(c.username, c.password) req.SetBasicAuth(c.username, c.password)
f, err := os.OpenFile(archivePath+".part", os.O_CREATE|os.O_WRONLY, 0740) f, err := os.OpenFile(archivePath+".part", os.O_CREATE|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to open file: %w", err) return fmt.Errorf("failed to open file: %w", err)
} }
res, err := cli.Do(req) res, err := cli.Do(req)
if err != nil { if err != nil {
f.Close() if err := f.Close(); err != nil {
slog.Error("failed to close file", "err", err)
}
return fmt.Errorf("cannot connect to remote: %w", err) return fmt.Errorf("cannot connect to remote: %w", err)
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != http.StatusOK { if res.StatusCode != http.StatusOK {
f.Close() if err := f.Close(); err != nil {
slog.Error("failed to close file", "err", err)
}
return fmt.Errorf("cannot connect to remote: server return code: %s", res.Status) return fmt.Errorf("cannot connect to remote: server return code: %s", res.Status)
} }
@@ -299,10 +304,14 @@ func (c *Client) PullBackup(gameID, uuid, archivePath string) error {
defer bar.Close() defer bar.Close()
if _, err := io.Copy(io.MultiWriter(f, bar), res.Body); err != nil { if _, err := io.Copy(io.MultiWriter(f, bar), res.Body); err != nil {
f.Close() if err := f.Close(); err != nil {
slog.Error("failed to close file", "err", err)
}
return fmt.Errorf("an error occured while copying the file from the remote: %w", err) return fmt.Errorf("an error occured while copying the file from the remote: %w", err)
} }
f.Close() if err := f.Close(); err != nil {
slog.Error("failed to close file", "err", err)
}
if err := os.Rename(archivePath+".part", archivePath); err != nil { if err := os.Rename(archivePath+".part", archivePath); err != nil {
return fmt.Errorf("failed to move temporary data: %w", err) return fmt.Errorf("failed to move temporary data: %w", err)
@@ -431,9 +440,15 @@ func (c *Client) push(u, archivePath string, m repository.Metadata) error {
return fmt.Errorf("failed to copy data: %w", err) return fmt.Errorf("failed to copy data: %w", err)
} }
writer.WriteField("name", m.Name) if err := writer.WriteField("name", m.Name); err != nil {
writer.WriteField("version", strconv.Itoa(m.Version)) return err
writer.WriteField("date", m.Date.Format(time.RFC3339)) }
if err := writer.WriteField("version", strconv.Itoa(m.Version)); err != nil {
return err
}
if err := writer.WriteField("date", m.Date.Format(time.RFC3339)); err != nil {
return err
}
if err := writer.Close(); err != nil { if err := writer.Close(); err != nil {
return err return err

View File

@@ -32,7 +32,7 @@ func init() {
} }
datastorepath = filepath.Join(roaming, "cloudsave", "data") datastorepath = filepath.Join(roaming, "cloudsave", "data")
err = os.MkdirAll(datastorepath, 0740) err = os.MkdirAll(datastorepath, 0600)
if err != nil { if err != nil {
panic("cannot make the datastore:" + err.Error()) panic("cannot make the datastore:" + err.Error())
} }
@@ -62,7 +62,7 @@ func Set(gameID, url string) error {
URL: url, URL: url,
} }
f, err := os.OpenFile(filepath.Join(datastorepath, gameID, "remote.json"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0740) f, err := os.OpenFile(filepath.Join(datastorepath, gameID, "remote.json"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -117,7 +117,7 @@ func (bi BackupIdentifier) Key() string {
func NewLazyRepository(dataRootPath string) (*LazyRepository, error) { func NewLazyRepository(dataRootPath string) (*LazyRepository, error) {
if m, err := os.Stat(dataRootPath); err != nil { if m, err := os.Stat(dataRootPath); err != nil {
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
if err := os.MkdirAll(dataRootPath, 0740); err != nil { if err := os.MkdirAll(dataRootPath, 0600); err != nil {
return nil, fmt.Errorf("failed to make the directory: %w", err) return nil, fmt.Errorf("failed to make the directory: %w", err)
} }
} else { } else {
@@ -137,8 +137,8 @@ func NewLazyRepository(dataRootPath string) (*LazyRepository, error) {
func (l *LazyRepository) Mkdir(id Identifier) error { func (l *LazyRepository) Mkdir(id Identifier) error {
path := l.DataPath(id) path := l.DataPath(id)
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
slog.Debug("making directory", "path", path, "id", id, "perm", "0740") slog.Debug("making directory", "path", path, "id", id, "perm", "0600")
return os.MkdirAll(path, 0740) return os.MkdirAll(path, 0600)
} }
return nil return nil
} }
@@ -182,7 +182,7 @@ func (l *LazyRepository) WriteBlob(ID Identifier) (io.Writer, error) {
path := l.DataPath(ID) path := l.DataPath(ID)
slog.Debug("loading write buffer...", "id", ID) slog.Debug("loading write buffer...", "id", ID)
dst, err := os.OpenFile(filepath.Join(path, "data.tar.gz"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0740) dst, err := os.OpenFile(filepath.Join(path, "data.tar.gz"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open destination file: %w", err) return nil, fmt.Errorf("failed to open destination file: %w", err)
} }
@@ -195,7 +195,7 @@ func (l *LazyRepository) WriteMetadata(id GameIdentifier, m Metadata) error {
path := l.DataPath(id) path := l.DataPath(id)
slog.Debug("writing metadata", "id", id, "metadata", m) slog.Debug("writing metadata", "id", id, "metadata", m)
dst, err := os.OpenFile(filepath.Join(path, "metadata.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0740) dst, err := os.OpenFile(filepath.Join(path, "metadata.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to open destination file: %w", err) return fmt.Errorf("failed to open destination file: %w", err)
} }
@@ -292,7 +292,7 @@ func (l *LazyRepository) ResetLastScan(id GameIdentifier) error {
path := l.DataPath(id) path := l.DataPath(id)
slog.Debug("resetting last scan datetime for", "id", id) slog.Debug("resetting last scan datetime for", "id", id)
f, err := os.OpenFile(filepath.Join(path, ".last_run"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0740) f, err := os.OpenFile(filepath.Join(path, ".last_run"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to open file: %w", err) return fmt.Errorf("failed to open file: %w", err)
} }
@@ -325,7 +325,7 @@ func (l *LazyRepository) ReadBlob(id Identifier) (io.ReadSeekCloser, error) {
func (l *LazyRepository) SetRemote(id GameIdentifier, url string) error { func (l *LazyRepository) SetRemote(id GameIdentifier, url string) error {
path := l.DataPath(id) path := l.DataPath(id)
src, err := os.OpenFile(filepath.Join(path, "remote.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0740) src, err := os.OpenFile(filepath.Join(path, "remote.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to open remote description: %w", err) return fmt.Errorf("failed to open remote description: %w", err)
} }

View File

@@ -5,10 +5,17 @@ import (
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"io" "io"
"log/slog"
"os" "os"
"path/filepath" "path/filepath"
) )
const (
// Tune these to your apps needs
maxCompressedUpload = 500 << 20 // 500 MiB compressed
maxUncompressedOutput = 1000 << 20 // 100 MiB after inflate
)
func Untar(file io.Reader, path string) error { func Untar(file io.Reader, path string) error {
gzr, err := gzip.NewReader(file) gzr, err := gzip.NewReader(file)
if err != nil { if err != nil {
@@ -49,26 +56,35 @@ func Untar(file io.Reader, path string) error {
// if its a dir and it doesn't exist create it // if its a dir and it doesn't exist create it
case tar.TypeDir: case tar.TypeDir:
if _, err := os.Stat(target); err != nil { if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil { if err := os.MkdirAll(target, 0600); err != nil {
return err return err
} }
} }
// if it's a file create it // if it's a file create it
case tar.TypeReg: case tar.TypeReg:
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, header.FileInfo().Mode())
if err != nil { if err != nil {
return err return err
} }
limited := &io.LimitedReader{R: gzr, N: maxUncompressedOutput}
// copy over contents // copy over contents
if _, err := io.Copy(f, tr); err != nil { if _, err := io.Copy(f, limited); err != nil {
return err return err
} }
// manually close here after each file operation; defering would cause each file close // manually close here after each file operation; defering would cause each file close
// to wait until all operations have completed. // to wait until all operations have completed.
f.Close() if err := f.Close(); err != nil {
slog.Error("failed to close file", "err", err)
}
if limited.N == 0 {
// Limit exhausted → likely bomb
return fmt.Errorf("payload too large after decompression")
}
} }
} }
} }

View File

@@ -14,6 +14,7 @@ func FileMD5(fp string) (string, error) {
} }
defer f.Close() defer f.Close()
hasher := md5.New() hasher := md5.New()
if _, err := io.Copy(hasher, f); err != nil { if _, err := io.Copy(hasher, f); err != nil {
return "", err return "", err