Skip to content

[Bug]: SYSTEM_AES_KEY encryption silently lost on tenant settings update #798

@ochanism

Description

@ochanism

相关组件

后端服务及API

Bug 描述

When a tenant setting is updated via the PUT /tenants/kv/{key} endpoints (e.g., web-search-config, parser-engine-config, storage-engine-config, retrieval-config), the encrypted api_key is silently reverted to plaintext in the database.

Root cause: tenantRepository.UpdateTenant() uses db.Updates(tenant) which does not trigger GORM's BeforeSave hook. The AfterFind hook decrypts enc:v1:...sk-... (plaintext) when loading the tenant, and then Updates() writes the decrypted plaintext back to the database.

The existing codebase already acknowledges this GORM limitation — both CreateTenant and UpdateAPIKey (renamed from RegenerateApiKey) contain manual EncryptAESGCM calls with the comment:

// Manually encrypt APIKey before update, because db.Updates() does not trigger BeforeSave hook

However, the general UpdateTenant path is missing this treatment.

Reproduction flow (UpdateTenantKV path):

  1. AfterFind hook decrypts api_key: enc:v1:...sk-... in the Go struct
  2. User updates a config via API (e.g., PUT /tenants/kv/retrieval-config)
  3. Handler loads full tenant from context (already decrypted), modifies one config field
  4. service.UpdateTenant()repo.UpdateTenant()db.Updates(tenant)
  5. BeforeSave is not triggered by Updates()
  6. Decrypted plaintext sk-... overwrites the encrypted value in the database

Note: ModelParameters JSONB encryption is not affected — its Value() method (implementing driver.Valuer) is correctly called by GORM during Updates().

期望行为

  • Tenant api_key remains enc:v1:... in the database after any tenant settings update
  • The UpdateTenant repository method should re-encrypt api_key before calling db.Updates(), consistent with the existing pattern in CreateTenant and UpdateAPIKey

相关日志

N/A — this is a silent data corruption issue discovered through code analysis. No error is logged when the encryption is lost.

操作系统

N/A (server-side logic bug, platform-independent)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions