fix(05): WR-02 fill Encrypted columns from plaintext, never Scan request input

This commit is contained in:
Jakub Zych
2026-09-18 23:47:28 +02:00
parent 3943ea3a2e
commit 6d2262d95f
2 changed files with 79 additions and 0 deletions

View File

@@ -103,3 +103,60 @@ func TestFillDroppedKeyNeverErrors(t *testing.T) {
t.Fatalf("collection_id = %d", row.CollectionID)
}
}
type fillSecretFixture struct {
Name string `gorm:"column:name"`
APIKey Encrypted `gorm:"column:api_key" json:"-"`
Token *Encrypted `gorm:"column:token" json:"-"`
}
func TestFillEncryptedTakesPlaintext(t *testing.T) {
if err := PublishEncryptionKeys(nil, bytes.Repeat([]byte("F"), 32), nil); err != nil {
t.Fatal(err)
}
allowed := []string{"name", "api_key", "token"}
var row fillSecretFixture
if err := Fill(&row, allowed, map[string]any{"api_key": "sk-plain", "token": "tok-plain"}, true); err != nil {
t.Fatal(err)
}
if row.APIKey.Reveal() != "sk-plain" {
t.Fatalf("api_key Reveal = %q", row.APIKey.Reveal())
}
if row.Token == nil || row.Token.Reveal() != "tok-plain" {
t.Fatalf("token = %v", row.Token)
}
// Another row's ciphertext is stored as literal text, never decrypted.
stolen, err := NewEncrypted("victim-secret").Value()
if err != nil {
t.Fatal(err)
}
ciphertext, ok := stolen.(string)
if !ok {
t.Fatalf("ciphertext driver value is %T", stolen)
}
var thief fillSecretFixture
if err := Fill(&thief, allowed, map[string]any{"api_key": ciphertext}, true); err != nil {
t.Fatal(err)
}
if thief.APIKey.Reveal() != ciphertext {
t.Fatal("ciphertext in a request must not be decrypted into the victim's plaintext")
}
for _, bad := range []any{42, true, map[string]any{"x": 1}, []byte("raw")} {
var r fillSecretFixture
if err := Fill(&r, allowed, map[string]any{"api_key": bad}, true); err == nil {
t.Fatalf("api_key=%T must be rejected", bad)
}
if r.APIKey.Reveal() != "" {
t.Fatalf("api_key=%T left a value behind", bad)
}
}
if err := Fill(&row, allowed, map[string]any{"api_key": nil, "token": nil}, true); err != nil {
t.Fatal(err)
}
if row.APIKey.Reveal() != "" || row.Token != nil {
t.Fatalf("nil must clear: api_key=%q token=%v", row.APIKey.Reveal(), row.Token)
}
}