check / check (pull_request) Successful in 1m22s
Objects fetched from the store are untrusted; several decode paths let one expand or print without limit. - blobgen.LimitReader errors past a byte cap (not io.LimitReader's silent EOF). DecodeManifest reads through caps on both compressed input and decompressed output, far above any real manifest, so json.Decode cannot buffer a compressible bomb. FetchAndDecryptBlob bounds decompression to the blob's recorded uncompressed_size (not the restoring host's blob_size_limit). - downloadSnapshotDB streams straight from storage to its temp file with io.Copy, replacing two ReadAll calls that held the whole database twice. - FetchBlob drops the per-blob Stat round-trip, its expectedSize parameter and returned size, all of which only fed a debug log. - TTYHandler and ui.Writer escape control characters in messages, attribute keys/values, and rendered identifiers/paths before colour codes are applied, so a crafted value cannot drive the terminal. Model: opus-4-8
44 lines
1.2 KiB
Go
44 lines
1.2 KiB
Go
package blobgen_test
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/vaultik/internal/blobgen"
|
|
)
|
|
|
|
// TestLimitReaderPassesExactSize checks that a stream of exactly the limit
|
|
// reads back cleanly to EOF: the bound must not reject a legitimate blob
|
|
// whose plaintext equals its recorded size.
|
|
func TestLimitReaderPassesExactSize(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const n = 1000
|
|
|
|
r := blobgen.LimitReader(bytes.NewReader(bytes.Repeat([]byte("a"), n)), n)
|
|
|
|
got, err := io.ReadAll(r)
|
|
require.NoError(t, err)
|
|
require.Len(t, got, n)
|
|
}
|
|
|
|
// TestLimitReaderFailsPastLimit feeds a large, highly compressible run of
|
|
// zeros — the decompressed output a zip bomb would produce — through a
|
|
// small limit and checks it fails within the bound rather than passing
|
|
// the whole stream through.
|
|
func TestLimitReaderFailsPastLimit(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const limit = 1000
|
|
|
|
r := blobgen.LimitReader(
|
|
bytes.NewReader(bytes.Repeat([]byte{0}, limit*1000)), limit)
|
|
|
|
n, err := io.Copy(io.Discard, r)
|
|
require.ErrorIs(t, err, blobgen.ErrOutputTooLarge)
|
|
require.LessOrEqual(t, n, int64(limit)+1,
|
|
"reader must stop within one byte of the limit")
|
|
}
|