T09 · Insecure Skill Coding Practices
- Location
SKILL.md:560- Finding
Private signing keys are returned and stored as Base64-encoded plaintext
- Content
View full analysis
Tuple[str, str]: """Generate an Ed25519 keypair for a bot. Returns (public_key_b64, private_key_b64). """ signing_key = nacl.signing.SigningKey.generate() verify_key = signing_key.verify_key private_b64 = base64.b64encode( signing_key.encode() ).decode("utf-8") public_b64 = base64.b64encode( verify_key.encode() ).decode("utf-8") # Store private key securely -- in production, use a secrets manager key_path = os.path.join(self.key_store_path, f"{bot_name}.key") os.makedirs(os.path.dirname(key_path), exist_ok=True) with open(key_path, "w") as f: f.write(private_b64) os.chmod(key_path, 0o600) # Owner read/write only return public_b64, private_b64 ``` ### Technical Analysis Base64 is a reversible encoding and provides no confidentiality. The Ed25519 private key is therefore written to disk as plaintext-equivalent data. Although mode `0600` limits access to the owning account, it does not protect the key from privileged processes, compromise of that account, filesystem snapshots, backups, accidental file copying, or insecure container volume handling. The method also returns the private key to its caller. This unnecessarily expands the number of components that can access or accidentally log the key. The caller shown elsewhere in the guide does not require the private key value for registration, because only the public key is submitted to the remote identity service. The static pre-scan warning about encoding sensitive data is confirmed. However, this specific code does not transmit the encoded private key to an external endpoint, so a covert exfiltration channel was not established. The confirmed issue is i ...[truncated 1292 chars]- Remediation
View remediation
