Skip to content

feat(security): encrypt userId and userHash at rest with AES-256-GCM#27

Merged
BigMichi1 merged 1 commit into
mainfrom
feat/encrypt-user-credentials
May 14, 2026
Merged

feat(security): encrypt userId and userHash at rest with AES-256-GCM#27
BigMichi1 merged 1 commit into
mainfrom
feat/encrypt-user-credentials

Conversation

@BigMichi1
Copy link
Copy Markdown
Owner

Store Idle Champions credentials encrypted in the database so a leaked DB file cannot be used to impersonate users.

  • Add src/bot/utils/crypto.ts with AES-256-GCM encrypt/decrypt helpers (random 12-byte IV + 128-bit auth tag per value, stored as hex triplet)
  • Encrypt userId and userHash in UserManager before writing to SQLite; decrypt transparently on read via rowToCredentials()
  • Require ENCRYPTION_KEY env var (64-char hex / 32 bytes); bot exits early with a clear error if it is missing or malformed
  • Add ENCRYPTION_KEY to .env.example with openssl generation hint
  • Set a fixed test ENCRYPTION_KEY in src/test/setup.ts preload
  • Update userManager tests to assert credentials are NOT stored as plaintext and that getCredentials() returns correctly decrypted values

Copilot AI review requested due to automatic review settings May 14, 2026 09:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds encryption-at-rest for Idle Champions credentials by introducing AES-256-GCM helpers, encrypting userId/userHash before SQLite writes, and decrypting them on reads.

Changes:

  • Added crypto helpers for AES-256-GCM encryption/decryption using ENCRYPTION_KEY.
  • Updated UserManager persistence and tests to store encrypted credential values.
  • Documented and configured ENCRYPTION_KEY for local/test environments.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/bot/utils/crypto.ts Adds encryption/decryption utilities and key validation.
src/bot/database/userManager.ts Encrypts credentials on save and decrypts credentials on read.
src/bot/database/userManager.test.ts Updates credential persistence tests for encrypted storage.
src/test/setup.ts Sets a fixed encryption key for Bun tests.
.env.example Documents the required encryption key variable.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/bot/database/userManager.ts Outdated
Comment thread src/bot/utils/crypto.ts Outdated
Comment thread src/bot/utils/crypto.ts Outdated
Comment thread .env.example
Copilot AI review requested due to automatic review settings May 14, 2026 09:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Comment thread src/bot/database/userManager.ts Outdated
Comment thread src/bot/utils/crypto.ts
Comment thread src/bot/utils/crypto.ts Outdated
Comment thread src/bot/database/userManager.ts
Comment thread .env.example
Copilot AI review requested due to automatic review settings May 14, 2026 09:45
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Comment thread src/bot/utils/crypto.ts Outdated
Comment thread src/bot/database/userManager.ts
Comment thread src/bot/database/userManager.ts
Comment thread src/bot/database/userManager.ts
Comment thread src/bot/database/userManager.ts Outdated
Comment thread .env.example
Copilot AI review requested due to automatic review settings May 14, 2026 09:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Comment thread src/bot/database/userManager.test.ts Outdated
Comment thread src/test/setup.ts Outdated
Comment thread .env.example
Copilot AI review requested due to automatic review settings May 14, 2026 10:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Comment thread README.md Outdated
Comment thread docs/podman.md Outdated
Comment thread docs/podman.md Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread docs/full-documentation.md
Comment thread docs/development.md
Copilot AI review requested due to automatic review settings May 14, 2026 15:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Store game credentials encrypted in SQLite so a database leak cannot be
directly exploited. A stolen DB file yields only opaque ciphertext.

Implementation
- src/bot/utils/crypto.ts (new): AES-256-GCM helpers using Node.js crypto.
  Key loaded from ENCRYPTION_KEY env var (64-char hex / 32 bytes).
  Ciphertext format: enc1:<iv_hex>:<authTag_hex>:<ciphertext_hex>.
  Key is validated eagerly at module load time (fail-fast).
- src/bot/database/userManager.ts: encrypt on write, decrypt on read.
  saveCredentials() rejects empty userId/userHash.
  migratePlaintextCredentials() transparently upgrades existing rows on
  startup; each field is migrated independently (handles mixed-state rows).
- src/bot/bot.ts: calls migratePlaintextCredentials() after DB init.
- src/test/setup.ts: sets ENCRYPTION_KEY to a clearly non-secret
  'deadbeef'-repeated test fixture to avoid secret-scanner false positives.
- src/bot/database/userManager.test.ts: 5 new migration tests; existing
  tests updated to assert encrypted-at-rest storage.

Configuration
- .env.example: documents ENCRYPTION_KEY with generation hint.
- docker-compose.yml / docker-compose.example.yml: forwards ENCRYPTION_KEY
  into the container.

Docs updated in README, docs/development.md, docs/full-documentation.md,
docs/podman.md, docs/github-secrets.md: ENCRYPTION_KEY listed as a required
variable with openssl rand -hex 32 generation hint and a warning that the
key must be generated once and retained — changing it after credentials have
been saved makes those rows unreadable.

Signed-off-by: Michael Cramer <michael@bigmichi1.de>
@BigMichi1 BigMichi1 force-pushed the feat/encrypt-user-credentials branch from b42a34e to 579203c Compare May 14, 2026 16:20
@BigMichi1 BigMichi1 merged commit cedda0f into main May 14, 2026
11 checks passed
@BigMichi1 BigMichi1 deleted the feat/encrypt-user-credentials branch May 14, 2026 17:11
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.

2 participants