Skip to content

[Security][Low] AES-GCM ciphertext not bound to row context (no AAD) #49

@tembo

Description

@tembo

Severity: Low
Area: API + Web — crypto hardening

Location

api/src/crypto.rs:24-71; web/src/lib/crypto.ts

Problem

Encryption uses AES-256-GCM with a random nonce (sound), but no AAD. Ciphertext is therefore not cryptographically bound to its row context (workspace_id, kind). A ciphertext blob from one row would still decrypt if substituted into another row.

Why it matters

Combined with the DB lookups, a blob moved into the wrong row still decrypts cleanly — there's no integrity binding tying a secret to its workspace/kind. Low impact today (requires DB write access) but cheap to harden.

Suggested fix

Bind context as AAD (e.g. workspace_id || kind) on both the Rust and TS encrypt/decrypt paths.

Note

The rest of the crypto is correct: AES-256-GCM, fresh random 12-byte nonce per call (no IV reuse), auth tag enforced.

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity vulnerability or hardeningseverity: lowLow severity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions