{"id":"CVE-2025-55013","aliases":["GHSA-75jv-vfxf-3865","PYSEC-2026-1194"],"title":"Assemblyline 4 service client vulnerable to Arbitrary Write through path traversal in Client code ","summary":"Assemblyline 4 service client vulnerable to Arbitrary Write through path traversal in Client code ","severity":"medium","cvss":4.2,"cvssVector":"CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L","vendor":"assemblyline-service-client","product":"assemblyline-service-client","ecosystem":"pip","affected":["assemblyline-service-client < 4.6.0.stable11","assemblyline-service-client >= 4.6.1.dev0, < 4.6.1.dev138"],"patched":["assemblyline-service-client 4.6.0.stable11","assemblyline-service-client 4.6.1.dev138"],"published":"2025-07-25","updated":"2026-07-07","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-75jv-vfxf-3865","references":[{"url":"https://github.com/CybercentreCanada/assemblyline/security/advisories/GHSA-75jv-vfxf-3865"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-55013"},{"url":"https://github.com/CybercentreCanada/assemblyline-service-client/commit/351414e7e96cc1f5640ae71ae51b939e8ba30900"},{"url":"https://github.com/CybercentreCanada/assemblyline-service-client"}],"tags":["osv","pip"],"epss":0.00584,"epssPercentile":0.46617,"ingestedAt":"2026-07-08T18:25:46.773Z","slug":"CVE-2025-55013","body":"## Overview\n\n**Path-Traversal -> Arbitrary File Write in Assemblyline Service Client**\n\n**IMPORTANT**: This vulnerability is valid if you decide to use the assemblyline-service-client outside of the normal practice to using Assemblyline in a production environment. In practice, this code should always be executed within a containerized environment such as [assemblyline-v4-service](https://github.com/CybercentreCanada/assemblyline-v4-service) which ensures filesystem-level permissions of what the running user is allowed to access. Furthermore, there is fewer chances for a MiTM compromise when deployed properly in a Docker or Kubernetes deployment where the platform will assign the correct network policies to secure connections between containers instead of relying on the user to set this up manually.\n\nSee https://github.com/CybercentreCanada/assemblyline/issues/382 for further discussion.\n\n---\n\n## 1. Summary  \nThe Assemblyline 4 **service client** (`task_handler.py`) accepts a SHA-256 value returned by the service **server** and uses it directly as a local file name.  \n> No validation / sanitisation is performed.\n\nA **malicious or compromised server** (or any MITM that can speak to client) can return a path-traversal payload such as  \n`../../../etc/cron.d/evil`  \nand force the client to write the downloaded bytes to an arbitrary location on disk.\n\n---\n\n## 2. Affected Versions  \n| Item | Value |\n|---|---|\n| **Component** | `assemblyline-service-client` |\n| **Repository** | [CybercentreCanada/assemblyline-service-client](https://github.com/CybercentreCanada/assemblyline-service-client) |\n| **Affected** | **All releases up to master branch.**  |\n\n\n---\n\n## 3. CVSS 3.1 Vector & Score  \n```\nCVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L\n```\n\n\n---\n\n## 4. Technical Details\n\n| Field | Content |\n|---|---|\n| **Location** | `assemblyline_service_client/task_handler.py`, inside `download_file()` |\n| **Vulnerable Line** | `file_path = os.path.join(self.tasking_dir, sha256)` |\n| **Root Cause** | The `sha256` string is taken directly from the service-server JSON response and used as a file name without any validation or sanitisation. |\n| **Exploit Flow** | 1. Attacker (service server) returns HTTP 200 for `GET /api/v1/file/../../../etc/cron.d/evil`.<br>2. Client writes the response body to `/etc/cron.d/evil`.<br>3. Achieves arbitrary file write (code execution if file is executable). |\n\n---\n\n## 5. Impact  \n- **Integrity** – Overwrite any file writable by the service UID (often root).  \n- **Availability** – Corrupt critical files or exhaust disk space.  \n- **Code Execution** – Drop cron jobs, systemd units, or overwrite binaries.\n\n---\n\n## 6. Mitigation / Fix\n\n```python\nimport re\n\n_SHA256_RE = re.compile(r'^[0-9a-fA-F]{64}\\Z')\n\ndef download_file(self, sha256: str, sid: str) -> Optional[str]:\n    if not _SHA256_RE.fullmatch(sha256):\n        self.log.error(f\"[{sid}] Invalid SHA256: {sha256}\")\n        self.status = STATUSES.ERROR_FOUND\n        return None\n    # or your preferred way to check if a string is a shasum.\n```\n---\n\n## Affected packages\n\n- `assemblyline-service-client < 4.6.0.stable11`\n- `assemblyline-service-client >= 4.6.1.dev0, < 4.6.1.dev138`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `assemblyline-service-client 4.6.0.stable11`\n- `assemblyline-service-client 4.6.1.dev138`","depth":"sunlit","depthScore":23,"depthScoreParts":{"impact":23.1,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}