T09 · Insecure Skill Coding Practices
Error
- Location
- medcrypt.py:95
- Finding
- Patient Identifier Exposed Through Reversible Base64 Encoding<![CDATA[ ## Vulnerability Details **File Location**: `medcrypt.py`, lines 95–125 **Vulnerability Type**: Sensitive medical metadata exposure **Risk Level**: High ### Vulnerable Code ```python def encrypt_message(plaintext: str, key: SecureKey, patient_id: str) -> str: """Encrypt plaintext → MedCrypt wire format. Wire format: [MEDCRYPT:v1:<patient_id>:<nonce_b64>:<ct_b64>:<tag_b64>] - patient_id is base64-encoded to avoid ':' delimiter collisions - nonce: 96-bit CSPRNG (os.urandom) - AAD: raw patient_id bytes (bound to ciphertext via GCM tag) """ if not patient_id: raise ValueError("patient_id must not be empty") nonce = os.urandom(12) # 96-bit CSPRNG nonce aesgcm = AESGCM(key.raw) aad = patient_id.encode("utf-8") ct_with_tag = aesgcm.encrypt(nonce, plaintext.encode("utf-8"), aad) # AESGCM appends 16-byte tag ciphertext = ct_with_tag[:-16] tag = ct_with_tag[-16:] # Base64-encode patient_id to avoid ':' in wire format pid_b64 = base64.b64encode(aad).decode("ascii") return ( f"[{WIRE_PREFIX}:{WIRE_VERSION}:{pid_b64}" f":{base64.b64encode(nonce).decode('ascii')}" f":{base64.b64encode(ciphertext).decode('ascii')}" f":{base64.b64encode(tag).decode('ascii')}]" ) ``` ### Technical Analysis The clinical message body is protected with AES-256-GCM, but `patient_id` is placed directly in the wire envelope using Base64. Base64 only converts binary data into a transport-safe textual representation; it does not provide confidentiality. The patient identifier is also used as authenticated additional data. AES-GCM authenticates AAD but does not encrypt it. Including the Base64 value in the transmitted envelope consequently allows anyone who can observe or obtain the message to recover the identifier without possessing the encryption key. This design exposes medical metadata and enables messages belonging to the same patient to be correlated. It conflicts w ...[truncated 1634 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not include the real patient identifier in the public wire envelope. 2. Encrypt the patient identifier together with the clinical message: ```python payload = json.dumps({ "patient_id": patient_id, "message": plaintext, }).encode("utf-8") ct_with_tag = aesgcm.encrypt(nonce, payload, protocol_aad) ``` 3. If routing requires an external identifier, use a random, unlinkable conversation token that contains no patient information. 4. Rotate or scope routing tokens to prevent long-term correlation. 5. Use only non-sensitive protocol metadata, such as the protocol name and version, as public AAD. 6. Explicitly document all metadata that remains visible to Telegram, WhatsApp, group members, backups, notification services, and other intermediaries. 7. Add tests verifying that neither the patient identifier nor its common encodings appear in the generated wire message. 8. Revise compliance claims until a complete privacy, key-management, access-control, retention, and platform metadata assessment has been performed. ]]>
