{"record":{"id":"47420a1bd27c1c29","repo":"nautechsystems/nautilus_trader","slug":"protected-execution-transaction-contains-plaint-47420a","errorCode":null,"errorMessage":"Protected execution transaction {} contains plaintext","messagePattern":"Protected execution transaction (.+?) contains plaintext","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":3624,"sourceCode":"        current.next().is_none(),\n        \"Execution intent {intent_id} has more than one current hash\"\n    );\n    Ok(row)\n}\n\nfn open_execution_payload(\n    keys: &PayloadKeySet,\n    policy: PayloadPolicy,\n    intent: &ExecutionIntentRow,\n    hash: &ExecutionTransactionHashRow,\n    reason: &str,\n) -> anyhow::Result<Vec<u8>> {\n    anyhow::ensure!(\n        hash.payload_expected,\n        \"Execution transaction {} has no signed payload\",\n        hash.transaction_hash\n    );\n    anyhow::ensure!(\n        hash.raw_transaction.is_none(),\n        \"Protected execution transaction {} contains plaintext\",\n        hash.transaction_hash\n    );\n    let envelope = hash.sealed_transaction.as_deref().ok_or_else(|| {\n        anyhow::anyhow!(\n            \"Protected execution transaction {} has no sealed payload\",\n            hash.transaction_hash\n        )\n    })?;\n    let context = payload_context(intent, hash, keys.deployment_id())?;\n    let raw_transaction = keys.unseal(envelope, &context)?;\n    log::info!(\n        \"Unsealed execution payload for intent {} transaction {} during {reason}\",\n        intent.id,\n        hash.transaction_hash\n    );\n    authenticate_retained_payload(&raw_transaction, intent, hash, keys.deployment_id())?;","sourceCodeStart":3606,"sourceCodeEnd":3642,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L3606-L3642","documentation":"For payloads expected to be sealed (encrypted), the code enforces that `raw_transaction` is None — an unprotected plaintext transaction alongside sealed storage means confidentiality was violated. The library refuses to process a transaction that stores both a sealed envelope and a plaintext copy. This protects against accidentally broadcasting or logging sensitive signed transactions.","triggerScenarios":"Calling the payload-resolution function with a hash row where the protection policy requires sealing but `raw_transaction` is populated with plaintext bytes.","commonSituations":"A code path that writes raw_transaction for debug/testing and forgot to null it; an environment or policy downgrade (sealed mode intended but sealing disabled); a migration that copied raw payloads into a sealed deployment; mixed-version writers where an older component still stores plaintext.","solutions":["Remove the plaintext raw_transaction from the row (null it) and rely solely on the sealed envelope.","Find and fix the code path that populated raw_transaction under a sealed payload policy.","Verify the deployment's payload policy/environment is consistently sealed mode end to end.","Rotate any secrets that may have been exposed via the plaintext payload, and audit logs for leaked transactions."],"exampleFix":"// before\nrow.raw_transaction = Some(raw_signed_tx);\nrow.sealed_transaction = Some(seal(raw_signed_tx, &context)?);\n\n// after: never keep both\nrow.sealed_transaction = Some(seal(raw_signed_tx, &context)?);\nrow.raw_transaction = None;","handlingStrategy":"validation","validationCode":"if hash.sealed_transaction.is_some() && hash.raw_transaction.is_some() {\n    anyhow::bail!(\"tx {} stores plaintext alongside sealed envelope\", hash.transaction_hash);\n}","typeGuard":"fn is_protected_clean(hash: &ExecutionTransactionHashRow) -> bool {\n    hash.sealed_transaction.is_some() && hash.raw_transaction.is_none()\n}","tryCatchPattern":null,"preventionTips":["Never write raw_transaction in sealed-mode deployments; gate the field behind the payload policy type.","Scrub raw payloads from debug/test paths before merging.","Audit logs and storage for plaintext signed transactions; rotate keys if any leaked."],"tags":["security","encryption","plaintext-leak"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}