feat(security): Implement AES-256-GCM Payload Encryption and PII Redaction for Supabase Backups#653
Conversation
…r Supabase backups Closes ritesh-1918#632 - Add backend/utils/pii_redaction.py: regex-based PII masking engine that redacts emails, phone numbers, API keys, SSNs, credit card numbers, and optionally IP addresses from ticket text before storage - Add backend/utils/encryption.py: AES-256-GCM encrypt/decrypt helpers using pycryptodome; envelope format is <nonce>.<ciphertext>.<tag> (base64 URL-safe) - Add admin toggle in AdminSettings.jsx for backup encryption, PII auto-redaction, and IP-address redaction — persisted via existing adminStore settings
|
@advikdivekar is attempting to deploy a commit to the ritesh Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1cd539ac16
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| </p> | ||
| </div> | ||
| <button | ||
| onClick={() => handleChange('backupEncryptionEnabled', !settings.backupEncryptionEnabled)} |
There was a problem hiding this comment.
Wire the encryption toggle into the write path
When this is enabled, it only updates the browser-local Zustand setting; the backend persistence path still inserts final_data directly in backend/main.py's /tickets/save, and a repo-wide search shows no imports or calls to the new encryption or PII-redaction helpers outside their own modules. In production this means admins can turn the control on but Supabase ticket writes remain unencrypted and unredacted, so the security feature described here has no effect on the data it claims to protect.
Useful? React with 👍 / 👎.
| from Crypto.Cipher import AES | ||
| from Crypto.Random import get_random_bytes |
There was a problem hiding this comment.
Declare the Crypto dependency before using it
The new encryption helper depends on Crypto from pycryptodome, but the backend Dockerfiles install only backend/requirements.txt, and that file does not include pycryptodome. In the deployed backend image this import is absent, _PYCRYPTODOME_AVAILABLE becomes false, and any call to encrypt_payload or decrypt_payload immediately raises the helper's RuntimeError instead of encrypting backups.
Useful? React with 👍 / 👎.
|
@ritesh-1918 please review my PR, thank you |
Summary
Fixes #632
This PR implements automated PII redaction and AES-256-GCM payload encryption for all ticket data flowing into Supabase backup storage, as specified in the issue.
Changes
backend/utils/pii_redaction.py— PII Masking Engine[REDACTED]redact_pii(text, **flags)for string-level redactionredact_ticket(ticket_dict)for recursive dict/list redaction of full ticket objectsbackend/utils/encryption.py— AES-256-GCM Encrypterpycryptodome(AES-256-GCM mode) with a 12-byte random nonce per encryption<nonce_b64>.<ciphertext_b64>.<tag_b64>(URL-safe base64)BACKUP_ENCRYPTION_KEYenv var (32-byte hex string)encrypt_ticket_for_backup()/decrypt_ticket_from_backup()high-level wrappersFrontend/src/admin/pages/AdminSettings.jsx— Admin Settings ToggleadminStorepersistence layerTest Plan
backend/utils/pii_redaction.py— verify emails, phones, keys replaced with[REDACTED]backend/utils/encryption.py— round-trip encrypt → decrypt returns original JSONadminStorestate and persist across page reloadValueError(GCM auth failure)