CVE-2026-47161 Overview
CVE-2026-47161 is an insecure deserialization vulnerability [CWE-502] in RELATE, a web-based courseware package used as a learning management system (LMS). Prior to commit d66ba5659b459bf1ba56b7109b5f9ecf197cbefb, RELATE configures its Celery workers to accept and deserialize untrusted pickle data from the message broker. An attacker who can reach the broker can execute arbitrary commands on the host server. Combined with missing network isolation in the code execution sandbox, an authenticated student can chain this flaw into full Remote Code Execution (RCE) on the host system.
Critical Impact
An authenticated student can pivot from the in-app code execution sandbox to the Celery broker and execute arbitrary commands on the RELATE host through unsafe pickle deserialization.
Affected Products
- RELATE LMS (inducer/relate) at commits prior to d66ba5659b459bf1ba56b7109b5f9ecf197cbefb
- Deployments using Celery workers with the default CELERY_ACCEPT_CONTENT configuration
- Instances where the code execution sandbox lacks network isolation from the message broker
Discovery Timeline
- 2026-05-27 - CVE-2026-47161 published to the National Vulnerability Database (NVD)
- 2026-05-27 - Last updated in NVD database
Technical Details for CVE-2026-47161
Vulnerability Analysis
RELATE uses Celery for asynchronous task execution and routes tasks through a message broker. The application sets CELERY_ACCEPT_CONTENT = ["pickle", "json"], instructing workers to deserialize incoming task payloads using Python's pickle module. Python pickle is not a safe serialization format because deserialization can instantiate arbitrary objects and invoke arbitrary callables. Any actor capable of publishing messages to the broker can therefore trigger code execution inside the worker process.
The second weakness is the lack of network isolation around RELATE's code execution sandbox, which is intended to grade student-submitted code. Because sandboxed code can reach the broker on the network, an authenticated student can craft a pickle payload from within the sandbox and submit it to the worker queue. The worker deserializes the payload and executes attacker-controlled commands with the privileges of the RELATE service account.
Root Cause
The root cause is the explicit acceptance of the pickle content type for Celery task messages in relate/settings.py. This is compounded by trusting broker-supplied messages and by an unisolated sandbox that allows authenticated users to reach the broker.
Attack Vector
The attack is network reachable and requires only low-privilege authenticated access. A student account submits Python code to the grading sandbox. That code opens a connection to the Celery broker (for example, AMQP) and publishes a task message with a malicious pickle payload. A worker consumes the message, deserializes the payload, and runs arbitrary commands on the RELATE host.
# Security patch in relate/settings.py - Celery: don't accept pickle tasks
CELERY_BROKER_URL = "amqp://"
-CELERY_ACCEPT_CONTENT = ["pickle", "json"]
+CELERY_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json"
# (pickle is buggy in django-celery-results 1.0.1)
# https://github.com/celery/django-celery-results/issues/50
Source: GitHub Commit d66ba5659b459bf1ba56b7109b5f9ecf197cbefb
Detection Methods for CVE-2026-47161
Indicators of Compromise
- Outbound connections from the RELATE code execution sandbox to the Celery broker port (default AMQP 5672)
- Celery worker processes spawning unexpected child processes such as sh, bash, python, or curl
- Broker messages with content-type: application/x-python-serialize originating from non-RELATE producers
- Unexpected modifications under the RELATE installation directory or service account home directory
Detection Strategies
- Inspect the running RELATE configuration for CELERY_ACCEPT_CONTENT and flag any value containing pickle
- Monitor Celery worker process trees for execution of shell utilities or interpreters outside the normal task graph
- Alert on inbound broker connections originating from sandbox network namespaces or container IPs
Monitoring Recommendations
- Enable broker-side authentication logging and audit which identities publish to Celery task queues
- Forward RELATE, Celery, and broker logs to a centralized analytics platform for correlation across grading events and worker activity
- Track the deployed RELATE git commit hash and alert when it lags behind d66ba5659b459bf1ba56b7109b5f9ecf197cbefb
How to Mitigate CVE-2026-47161
Immediate Actions Required
- Update RELATE to a revision that includes commit d66ba5659b459bf1ba56b7109b5f9ecf197cbefb
- Restrict the Celery broker to bind to localhost or a private management network only
- Block egress from the code execution sandbox to the broker host and port at the network layer
- Rotate credentials and review worker hosts for signs of prior exploitation before returning to production
Patch Information
The fix is included in RELATE commit d66ba5659b459bf1ba56b7109b5f9ecf197cbefb, which removes pickle from CELERY_ACCEPT_CONTENT so that workers accept only JSON-serialized tasks. See the GitHub Security Advisory GHSA-4mwh-mwv4-m252 for advisory details and the upstream commit for the code change.
Workarounds
- Override CELERY_ACCEPT_CONTENT in local settings to ["json"] and set CELERY_TASK_SERIALIZER = "json" until the patch can be deployed
- Place the Celery broker behind a firewall rule that only permits the RELATE web tier and worker hosts
- Run the grading sandbox in a network namespace or container with no route to the broker subnet
# Configuration example: enforce JSON-only Celery payloads in local_settings.py
CELERY_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json"
CELERY_RESULT_SERIALIZER = "json"
# Restrict broker exposure (RabbitMQ example)
# /etc/rabbitmq/rabbitmq.conf
listeners.tcp.local = 127.0.0.1:5672
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


