From dd71070a9d9870745c3f26f6ea9d1a8c90085c44 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 14:30:04 +0000 Subject: [PATCH] fix(manifest): validate signing inputs Co-Authored-By: Virgil --- cmd/scm/cmd_compile_test.go | 16 ++++++++++++++++ manifest/sign.go | 10 ++++++++++ manifest/sign_test.go | 22 ++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/cmd/scm/cmd_compile_test.go b/cmd/scm/cmd_compile_test.go index 182ac39..4a14bb4 100644 --- a/cmd/scm/cmd_compile_test.go +++ b/cmd/scm/cmd_compile_test.go @@ -5,6 +5,7 @@ package scm import ( filepath "dappco.re/go/core/scm/internal/ax/filepathx" os "dappco.re/go/core/scm/internal/ax/osx" + "encoding/hex" "testing" "dappco.re/go/core/io" @@ -57,3 +58,18 @@ version: 2.0.0 assert.Equal(t, "compile-custom", cm.Code) assert.Equal(t, "custom builder", cm.BuiltBy) } + +func TestRunCompile_Bad_InvalidSignKey_Good(t *testing.T) { + dir := t.TempDir() + coreDir := filepath.Join(dir, ".core") + require.NoError(t, os.MkdirAll(coreDir, 0755)) + require.NoError(t, os.WriteFile(filepath.Join(coreDir, "manifest.yaml"), []byte(` +code: compile-invalid-key +name: Compile Invalid Key +version: 1.0.0 +`), 0644)) + + err := runCompile(dir, hex.EncodeToString([]byte("short")), "core scm compile", "core.json") + require.Error(t, err) + assert.Contains(t, err.Error(), "invalid private key length") +} diff --git a/manifest/sign.go b/manifest/sign.go index c803c84..2cbf657 100644 --- a/manifest/sign.go +++ b/manifest/sign.go @@ -20,6 +20,13 @@ func signable(m *Manifest) ([]byte, error) { // Sign computes the ed25519 signature and stores it in m.Sign (base64). // Usage: Sign(...) func Sign(m *Manifest, priv ed25519.PrivateKey) error { + if m == nil { + return coreerr.E("manifest.Sign", "nil manifest", nil) + } + if len(priv) != ed25519.PrivateKeySize { + return coreerr.E("manifest.Sign", "invalid private key length", nil) + } + msg, err := signable(m) if err != nil { return coreerr.E("manifest.Sign", "marshal failed", err) @@ -32,6 +39,9 @@ func Sign(m *Manifest, priv ed25519.PrivateKey) error { // Verify checks the ed25519 signature in m.Sign against the public key. // Usage: Verify(...) func Verify(m *Manifest, pub ed25519.PublicKey) (bool, error) { + if m == nil { + return false, coreerr.E("manifest.Verify", "nil manifest", nil) + } if m.Sign == "" { return false, coreerr.E("manifest.Verify", "no signature present", nil) } diff --git a/manifest/sign_test.go b/manifest/sign_test.go index 5b57c96..27ed86a 100644 --- a/manifest/sign_test.go +++ b/manifest/sign_test.go @@ -51,3 +51,25 @@ func TestVerify_Bad_Unsigned_Good(t *testing.T) { assert.Error(t, err) assert.False(t, ok) } + +func TestSign_Bad_InvalidPrivateKey_Good(t *testing.T) { + m := &Manifest{Code: "test-app", Version: "1.0.0"} + + err := Sign(m, ed25519.PrivateKey([]byte("short"))) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid private key length") + assert.Empty(t, m.Sign) +} + +func TestSign_Bad_NilManifest_Good(t *testing.T) { + err := Sign(nil, ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))) + assert.Error(t, err) + assert.Contains(t, err.Error(), "nil manifest") +} + +func TestVerify_Bad_NilManifest_Good(t *testing.T) { + ok, err := Verify(nil, ed25519.PublicKey(make([]byte, ed25519.PublicKeySize))) + assert.Error(t, err) + assert.False(t, ok) + assert.Contains(t, err.Error(), "nil manifest") +}