Skip to content

security: stop persisting and returning secret values in plaintext - #2

Merged
merlik787-droi merged 1 commit into
mainfrom
fix/remove-plaintext-secret-storage
Oct 9, 2026
Merged

merlik787-droi merged 1 commit into
mainfrom
fix/remove-plaintext-secret-storage

Conversation

@merlik787-droi

Copy link
Copy Markdown
Contributor

Closes #1

Problem

config-service persisted every secret in plaintext (secrets.value) in addition to the encrypted copy, and returned that entity from the secrets API — so the AES encryption protected nothing.

Changes

  • src/entities/secret.entity.ts — removed the plaintext value column.
  • src/modules/secret/secret.service.ts — createSecret, updateSecret and rotateSecret no longer write plaintext; only encryptedValue + iv are stored. Values continue to be readable through getSecretValue() (decrypt).
  • src/migrations/1730000000000-RemovePlaintextSecretValue.ts — drops the value column from existing databases (down() restores an empty column, since the original cleartext cannot be recovered).
  • test/secret.service.spec.ts — new tests: the entity has no value property, and create/rotate never persist a plaintext field.

Verification (in microservices/config-service)

npm run lint:check    → clean
npm run format:check  → clean
npm run type-check    → clean
npm test              → 3 suites, 5 tests passed
npm run build         → nest build OK

Note

For non-production environments synchronize is enabled, so the schema updates automatically from the entity; production applies the new migration. A follow-up will redact encryptedValue/iv from API responses.

The secrets table persisted each value twice: an encrypted copy
(encryptedValue + iv) AND a plaintext copy in a non-nullable `value`
column. createSecret/updateSecret/rotateSecret wrote the plaintext, and
the secrets API returned the entity as-is, so every secret was readable
in cleartext from the database and over the API - defeating the
encryption entirely.

- Remove the plaintext `value` column from the Secret entity and stop
  writing it (create/update/rotate now persist only encryptedValue + iv)
- Add migration 1730000000000 to drop the column from existing databases
- Add SecretService tests asserting the entity has no plaintext field and
  that create/rotate never persist one
@merlik787-droi
merlik787-droi merged commit c31e807 into main Oct 9, 2026
@merlik787-droi
merlik787-droi deleted the fix/remove-plaintext-secret-storage branch October 9, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security: config-service persists and returns secret values in plaintext

2 participants