
Research
/Security News
jscrambler npm Package Compromised in Supply Chain Attack
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.
go.sia.tech/sia-storage
Advanced tools
The official Go SDK for storing and retrieving data on the Sia network.
For guides and additional resources, visit the developer portal. For detailed API documentation, see the Godocs.
Before uploading or downloading data, your application must connect to an
indexer. First, create a Builder with your application metadata, then walk
the user through the approval flow:
builder := sdk.NewBuilder("https://sia.storage", sdk.AppMetadata{
ID: appID, // a persistent, randomly-generated 32-byte app ID
Name: "MyApp", // display name
Description: "My first Sia application", // short description
LogoURL: "https://my.app/logo.png", // logo shown in the indexer UI
ServiceURL: "https://my.app", // your application's homepage
})
// request a connection — the user must visit the returned URL to approve
responseURL, err := builder.RequestConnection(ctx)
if err != nil {
log.Fatal("failed to request connection:", err)
}
fmt.Println("Approve the connection:", responseURL)
// block until the user approves or rejects
approved, err := builder.WaitForApproval(ctx)
if err != nil {
log.Fatal("failed to wait for approval:", err)
} else if !approved {
log.Fatal("user denied the connection")
}
// derive an app key from a BIP-39 seed phrase and register it
mnemonic := sdk.NewSeedPhrase() // generate once — store securely
client, err := builder.Register(ctx, mnemonic)
if err != nil {
log.Fatal("failed to register:", err)
}
defer client.Close()
On subsequent launches, skip the approval flow and create the SDK directly with the previously derived app key:
builder := sdk.NewBuilder("https://sia.storage", sdk.AppMetadata{ID: appID})
client, err := builder.SDK(appKey)
if err != nil {
log.Fatal("failed to create SDK:", err)
}
defer client.Close()
Once connected, you can upload and download files using the SDK:
// upload
obj := sdk.NewEmptyObject()
f, _ := os.Open("path/to/src.dat")
defer f.Close()
if err := client.Upload(ctx, &obj, f); err != nil {
log.Fatal("upload failed:", err)
}
// pin the object so the indexer tracks it
if err := client.PinObject(ctx, obj); err != nil {
log.Fatal("pin failed:", err)
}
// download
out, _ := os.Create("path/to/dst.dat")
defer out.Close()
if err := client.Download(ctx, out, obj); err != nil {
log.Fatal("download failed:", err)
}
The Object returned by Upload contains the encryption key and slab
metadata required to download the data later. After uploading, call
PinObject to persist the object on the indexer. Applications should store
the sealed object (via obj.Seal(appKey)) so it can be reopened later.
When uploading many small objects, UploadPacked combines them into shared
slabs to reduce overhead:
packed, err := client.UploadPacked()
if err != nil {
log.Fatal("failed to create packed upload:", err)
}
defer packed.Close()
for _, data := range smallObjects {
if _, err := packed.Add(ctx, bytes.NewReader(data)); err != nil {
log.Fatal("failed to add object:", err)
}
}
objects, err := packed.Finalize(ctx)
if err != nil {
log.Fatal("failed to finalize:", err)
}
// pin and download each object individually
for _, obj := range objects {
client.PinObject(ctx, obj)
}
Use Remaining() and Length() to monitor padding and decide when to
finalize:
const paddingTarget = 0.05
for len(uploads) > 0 {
packed, err := client.UploadPacked()
if err != nil {
log.Fatal(err)
}
for len(uploads) > 0 {
if _, err := packed.Add(ctx, bytes.NewReader(uploads[0])); err != nil {
log.Fatal(err)
}
uploads = uploads[1:]
if packed.Length() == 0 {
continue
}
if float64(packed.Remaining())/float64(packed.Length()) <= paddingTarget {
break
}
}
objects, err := packed.Finalize(ctx)
if err != nil {
log.Fatal(err)
}
for _, obj := range objects {
client.PinObject(ctx, obj)
}
packed.Close()
}
PackedUpload is not thread-safe; do not call Add concurrentlyErrEmptyObjectFinalize is called, subsequent Add calls return ErrUploadFinalizedObjects can be shared via time-limited URLs:
url, err := client.CreateSharedObjectURL(ctx, obj.ID(), time.Now().Add(24*time.Hour))
if err != nil {
log.Fatal("failed to create shared URL:", err)
}
// anyone with the URL can download the object
var buf bytes.Buffer
if err := client.DownloadSharedObject(ctx, &buf, url); err != nil {
log.Fatal("failed to download shared object:", err)
}
FAQs
Unknown package
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.

Research
/Security News
A malicious .NET package is typosquatting the Braintree SDK to steal live payment card data, merchant API keys, and host secrets from production apps.

Security News
/Research
Compromised Injective SDK npm version 1.20.21 exfiltrates wallet private keys and mnemonics through fake telemetry functionality.