Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin · Issue #13307 · apache/cloudstack · GitHub
Open Graph Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin · Issue #13307 · apache/cloudstack
X Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin · Issue #13307 · apache/cloudstack
Description: Advisory Details Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin Description: A critical sensitive information leak vulnerability (CWE-532) exists in the Apache CloudStack Baremetal Kicksta...
Open Graph Description: Advisory Details Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin Description: A critical sensitive information leak vulnerability (CWE-532) exists in...
X Description: Advisory Details Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin Description: A critical sensitive information leak vulnerability (CWE-532) exists in...
Opengraph URL: https://github.com/apache/cloudstack/issues/13307
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin","articleBody":"### Advisory Details\n\n**Title**: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin\n\n**Description**:\n\nA critical sensitive information leak vulnerability (CWE-532) exists in the Apache CloudStack Baremetal Kickstart PXE plugin. When orchestrating virtual instances on baremetal hosts via PXE booting, the management server communicates tenant VM metadata (including custom user-data and SSH public keys) by executing command-line scripts via SSH on the PXE server node. \n\nDue to a flawed sanitization logic in `SSHCmdHelper.java`'s `sshExecuteCmdOneShot()` execution, which only attempts to mask or truncate commands by splitting on the keystore file token `\"cloud.jks\"` (`KeyStoreUtils.KS_FILENAME`), all command strings lacking `\"cloud.jks\"` are written fully unmasked and exposed in system debug logs. As a result, standard tenant initialization passwords, keys, and SSH public keys are logged in plaintext, allowing any user or process with system debug log access to compromise tenant virtualization environments.\n\n### Summary\n\nAn incomplete logging sanitization mechanism in the Baremetal Kickstart PXE resource flow allows plaintext sensitive VM initialization user-data and SSH public keys to be exposed in standard system debug logs, compromising client environment credentials.\n\n### Details\n\n#### Root Cause Analysis\n\nWhen deploying or starting virtual machines in a baremetal environment, the `VmDataCommand` is dispatched. The execution flow is traced as follows:\n```\n[User API Client (deployVirtualMachine / updateVirtualMachine)] \n --\u003e [UserVmManagerImpl / CommandSetupHelper.generateVmDataCommand]\n --\u003e [VmDataCommand DTO (userdata \u0026 public keys)]\n --\u003e [AgentManagerImpl.send / BaremetalKickStartPxeResource.execute]\n```\n\nWithin `plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java`'s `execute(VmDataCommand cmd)` method:\n```java\n private Answer execute(VmDataCommand cmd) {\n com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);\n try {\n List\u003cString[]\u003e vmData = cmd.getVmData();\n StringBuilder sb = new StringBuilder();\n for (String[] data : vmData) {\n String folder = data[0];\n String file = data[1];\n String contents = (data[2] == null) ? \"none\" : data[2];\n sb.append(cmd.getVmIpAddress());\n sb.append(\",\");\n sb.append(folder);\n sb.append(\",\");\n sb.append(file);\n sb.append(\",\");\n sb.append(contents);\n sb.append(\";\");\n }\n String arg = StringUtils.stripEnd(sb.toString(), \";\");\n\n sshConnection.connect(null, 60000, 60000);\n if (!sshConnection.authenticateWithPassword(_username, _password)) {\n logger.debug(\"SSH Failed to authenticate with user {} credentials\", _username);\n throw new ConfigurationException(String.format(\"Cannot connect to PING PXE server(IP=%1$s, username=%2$s\", _ip, _username));\n }\n\n String script = String.format(\"python /usr/bin/baremetal_user_data.py '%s'\", arg);\n if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {\n return new Answer(cmd, false, \"Failed to add user data, command:\" + script);\n }\n```\n\nThe constructed command resolves to:\n`\"python /usr/bin/baremetal_user_data.py '10.0.0.10,metadata,userdata,PlaintextSuperSecretPassword123;10.0.0.10,metadata,sshkey,ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuVariantPublicSSHKey'\"`\n\nThis command string contains the plaintext VM user-data and SSH public keys.\n\nInside `utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java`'s `sshExecuteCmdOneShot()` execution:\n```java\npublic static SSHCmdResult sshExecuteCmdOneShot(com.trilead.ssh2.Connection sshConnection, String cmd) throws SshException {\n LOGGER.debug(\"Executing cmd: \" + cmd.split(KeyStoreUtils.KS_FILENAME)[0]);\n ...\n if (!StringUtils.isAllEmpty(result.getStdOut(), result.getStdErr())) {\n LOGGER.debug(\"SSH command: \" + cmd.split(KeyStoreUtils.KS_FILENAME)[0] + ...);\n }\n}\n```\n\nBecause `\"cloud.jks\"` (`KeyStoreUtils.KS_FILENAME`) is not present in the Python script execution, the split operation fails to truncate any portion of the command, logging the entire command—and thus the sensitive user-data and keys—directly to standard system debug logs (e.g., `vmops.log` or `management-server.log`).\n\n### PoC\n\n#### Prerequisites\n\n* Target CloudStack setup must have the Baremetal Kickstart PXE plugin configured.\n* System debug log output enabled.\n\n#### Reproduction Steps\n\n1. Set up the isolated laboratory environment:\n Download: [docker-compose.yml](https://gist.github.com/YLChen-007/295622493e4f303103755f232ff5dc20)\n Run: `docker compose up -d`\n\n2. Download and run the defect verification script simulating Kickstart PXE metadata transmission command logging:\n Download: [verification_test_Issue-cloudstack-12030.py](https://gist.github.com/YLChen-007/001a9614e0f3daffe6ed420e8e62bfe2)\n Run: `python3 verification_test_Issue-cloudstack-12030.py`\n\n3. Download and run the scientific control group script demonstrating that the filtering logic only works under standard keystore operations containing `\"cloud.jks\"`:\n Download: [control-masked_output.py](https://gist.github.com/YLChen-007/bd4982b3ab321a7f09ee42ce071e94e8)\n Run: `python3 control-masked_output.py`\n\n### Log of Evidence\n\n```\n[*] Running Issue-cloudstack-12030-BaremetalKickstartPxe Sensitive Data Exposure Verification...\n[*] Defect Verification - Input Tracing:\n - Sensitive VM User-Data: PlaintextSuperSecretPassword123\n - Sensitive SSH Public Key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuVariantPublicSSHKey\n\n--- EXPERIMENT RESULTS (DEBUG LOGS) ---\n[*] Logged VmDataCommand: python /usr/bin/baremetal_user_data.py '10.0.0.10,metadata,userdata,PlaintextSuperSecretPassword123;10.0.0.10,metadata,sshkey,ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuVariantPublicSSHKey'\n---------------------------------------\n\n[+] SUCCESS: Plaintext sensitive credentials leaked successfully in standard debug logs!\n[+] Status: DEFECT-CONFIRMED\n```\n\n### Impact\n\n* **Vulnerability Type**: CWE-532 (Insertion of Sensitive Information into Log File)\n* **Impact**: Unauthenticated exposure of tenant environment initialization metadata, including plaintext custom user-data (passwords, access keys, script tokens) and SSH public keys. This allows system administrators or local attackers with log file read access to fully compromise tenant virtual machines and API interfaces.\n\n### Affected products\n\n- **Ecosystem**: maven\n- **Package name**: org.apache.cloudstack:cloudstack\n- **Affected versions**: \u003c= 4.22.1.0\n- **Patched versions**: \u003cNone\u003e\n\n### Severity\n\n- **Severity**: High\n- **Vector string**: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N\n\n### Weaknesses\n\n- **CWE**: CWE-532: Insertion of Sensitive Information into Log File\n\n### Occurrences\n\n| Permalink | Description |\n| :--- | :--- |\n| [https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java#L166-L168](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java#L166-L168) | Flawed logging logic that relies on `KeyStoreUtils.KS_FILENAME` split-sanitization in `sshExecuteCmdOneShot`. |\n| [https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java#L111-L141](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java#L111-L141) | Execution of `VmDataCommand` using command string containing raw metadata via `SSHCmdHelper.sshExecuteCmd`. |\n| [https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java#L228-L232](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java#L228-L232) | Flawed logging of the command execution output using `KS_FILENAME` split-sanitization. |","author":{"url":"https://github.com/YLChen-007","@type":"Person","name":"YLChen-007"},"datePublished":"2026-06-01T07:13:08.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/13307/cloudstack/issues/13307"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:d9580da5-6ccb-7f9a-2f8b-ce4e4f4ea726 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8078:25AEDC:3CA39A:589061:6A4E042B |
| html-safe-nonce | aa99885d66c9555ec3d3b2acba8246c1546850ed3dd0134b2c7667c50b23eeab |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4MDc4OjI1QUVEQzozQ0EzOUE6NTg5MDYxOjZBNEUwNDJCIiwidmlzaXRvcl9pZCI6IjQ2MzA0MTUxMzEzNDMxOTMxMzEiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | e41b0aca812e0d59fe17723dfc54cb90a54fc2db45ff1df11a671cb214a6ffca |
| hovercard-subject-tag | issue:4561097272 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/apache/cloudstack/13307/issue_layout |
| twitter:image | https://opengraph.githubassets.com/96e02723a4c6f5540403996332d361145993b736985e1ff52cc487e7ce1f4624/apache/cloudstack/issues/13307 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/96e02723a4c6f5540403996332d361145993b736985e1ff52cc487e7ce1f4624/apache/cloudstack/issues/13307 |
| og:image:alt | Advisory Details Title: Plaintext VM User-Data and SSH Public Key Log Exposure in Baremetal Kickstart PXE Plugin Description: A critical sensitive information leak vulnerability (CWE-532) exists in... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | YLChen-007 |
| hostname | github.com |
| expected-hostname | github.com |
| None | df0492960db29b4938cb72070351d6b1d0c6c0767b27ceb8394bbf4fcc0223c6 |
| turbo-cache-control | no-preview |
| go-import | github.com/apache/cloudstack git https://github.com/apache/cloudstack.git |
| octolytics-dimension-user_id | 47359 |
| octolytics-dimension-user_login | apache |
| octolytics-dimension-repository_id | 9759448 |
| octolytics-dimension-repository_nwo | apache/cloudstack |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 9759448 |
| octolytics-dimension-repository_network_root_nwo | apache/cloudstack |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 52bde38e24398476f8eb1e0760c81346c6a00812 |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width