56 results available
Sign in
Skills directory

go-bucket

encoredev

·

Last changed
Hardened

This skill has been hardened by Chainguard

Last changed

This version passed the hardening gate. Hardening updated the skill content and independently checked the resulting changes. Classified findings before hardening: 0. Classified findings closed: 0. Classified findings remaining: 0. Unclassified scanner findings remaining: 0. Review findings closed: 9. Review findings remaining: 2.


Open before hardening

None

Open after hardening

None


Expand
File
Group
Subtype
Severity
Status

No findings available

0 findings


SKILL.md

Encore Go Object Storage

Instructions

A Bucket is a logical store for files. Encore provisions the underlying object storage (S3 on AWS, GCS on GCP, in-memory locally). Declare buckets as package-level variables.

package uploads

import "encore.dev/storage/objects"

// Private bucket (default)
var Uploads = objects.NewBucket("user-uploads", objects.BucketConfig{})

// Public bucket — files accessible via public URL
var PublicAssets = objects.NewBucket("public-assets", objects.BucketConfig{
    Public: true,
})

Operations

import (
    "fmt"
    "io"
)

// Upload (streaming pattern)
writer := Uploads.Upload(ctx, "path/to/file.jpg")
_, err := io.Copy(writer, dataReader)
if err != nil {
    writer.Abort()
    return err
}
err = writer.Close()
if err != nil {
    return err
}

// Download
reader := Uploads.Download(ctx, "path/to/file.jpg")
if err := reader.Err(); err != nil {
    return err
}
defer reader.Close()
data, _ := io.ReadAll(reader)

// Existence check
exists, err := Uploads.Exists(ctx, "path/to/file.jpg")

// Attributes (size, content type, ETag)
attrs, err := Uploads.Attrs(ctx, "path/to/file.jpg")

// List
for err, entry := range Uploads.List(ctx, &objects.Query{}) {
    if err != nil {
        return err
    }
    fmt.Println(entry.Key, entry.Size)
}

// Delete
err := Uploads.Remove(ctx, "path/to/file.jpg")

// Public URL (only for public buckets)
url := PublicAssets.PublicURL("image.jpg")

Each snippet above is an independent example. When combining them in one function, adapt the variable names so the code compiles and every error check is kept, including the check on the full read of a download. The fixed keys shown are illustrative; real keys should be unique per user.

Signed URLs

Generate temporary URLs so clients can upload/download directly without going through your service:

import "time"

// Signed upload URL (expires in 2 hours)
url, err := Uploads.SignedUploadURL(ctx, "user-uploads/avatar.jpg",
    objects.WithTTL(time.Duration(7200)*time.Second))

// Signed download URL
url, err := Uploads.SignedDownloadURL(ctx, "documents/report.pdf",
    objects.WithTTL(time.Duration(7200)*time.Second))

The two hour lifetime above is only an example; use the shortest practical lifetime, usually minutes.

Bucket References

Pass bucket access to library code with a specific permission set:

// Create a reference with download permission only
ref := objects.BucketRef[objects.Downloader](Uploads)

// Combine permissions via an interface
type myPerms interface {
    objects.Downloader
    objects.Uploader
}
ref := objects.BucketRef[myPerms](Uploads)

// Permission types: Downloader, Uploader, Lister, Attrser, Remover,
// SignedDownloader, SignedUploader, ReadWriter

Guidelines

  • Declare buckets as package-level variables.
  • Default to private buckets; opt into Public: true only for assets meant for unauthenticated download.
  • A public bucket makes every object in it readable by anyone, with no control per file; keep public buckets dedicated to assets meant to be public, and store user uploads and private data in private buckets.
  • Use signed URLs for browser uploads/downloads instead of streaming through your service.
  • Treat files uploaded through signed URLs as untrusted: after upload, the service checks their size and content type against an allowlist, and removes or quarantines any object that fails before it is used.
  • Build object keys on the server from the signed in user and a generated identifier, and reject client keys that contain unexpected prefixes, parent directory segments, or a leading slash.
  • Confirm the caller owns a key before any upload, download, removal, attribute lookup, or signed URL call.
  • Issue signed URLs only from authenticated endpoints after that ownership check, keep their lifetime short, and treat them as bearer secrets that stay out of logs.
  • Set an explicit content type that the server has validated when storing user files, and serve user content from a separate domain or as an attachment download, keeping user HTML and SVG files off public buckets on a trusted origin.
  • Check the object size before reading it fully into memory, stream large files instead, and check the read error.
  • Scope list queries to a prefix the caller is allowed to see, with a result limit, and keep full bucket listings internal.
  • Use bucket references when passing access to helpers — they encode the permission contract in the type system.

Install

Install with chainctl
chainctl skill install public/encoredev/go-bucket:latest
Get started with chainctl
View source

Harden your own skills

Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.

Provenance

Upstream sourcehttps://github.com/encoredev/skills
Upstream commitcb69bb1f246274419aed69c84ee5815955c4c499
OCI reference

skills.cgr.dev/public/github.com/encoredev/encore/go-bucket:latest

License

Apache-2.0

Files

HARDENING.md

LICENSE

SKILL.md


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.