CVE-2024-28185 Overview
CVE-2024-28185 is a critical symlink attack vulnerability in Judge0, an open-source online code execution system. The application fails to properly account for symbolic links placed inside the sandbox directory, which can be leveraged by an attacker to write to arbitrary files and gain code execution outside of the sandbox environment.
When executing a submission, Judge0 writes a run_script to the sandbox directory. The security flaw allows an attacker to create a symbolic link (symlink) at the path run_script before this code is executed, resulting in the file write operation targeting an arbitrary file on the unsandboxed host system. An attacker can leverage this vulnerability to overwrite scripts on the system and gain remote code execution outside of the sandbox.
Critical Impact
This vulnerability allows complete sandbox escape with the ability to execute arbitrary code on the host system, potentially compromising any server running vulnerable Judge0 instances.
Affected Products
- Judge0 versions prior to the security patch (v1.13.0 and earlier)
- Self-hosted Judge0 installations
- Online code execution platforms utilizing Judge0
Discovery Timeline
- 2024-04-18 - CVE-2024-28185 published to NVD
- 2024-11-21 - Last updated in NVD database
Technical Details for CVE-2024-28185
Vulnerability Analysis
This vulnerability is classified as CWE-59 (Improper Link Resolution Before File Access), commonly known as a symlink attack. The flaw exists in the isolate_job.rb component of Judge0, specifically in the code responsible for writing the execution script to the sandbox directory.
The attack is network-accessible and requires no authentication or user interaction. The scope is changed, meaning an attacker can impact resources beyond the vulnerable component's security scope—in this case, escaping from the sandbox to the host system. This results in complete compromise of confidentiality, integrity, and availability of the host system.
Root Cause
The root cause is improper handling of symbolic links in the sandbox directory. The Judge0 application writes the run_script file to the sandbox directory without first verifying that the target path is not a symbolic link. This allows an attacker to pre-create a symlink at the expected run_script location, redirecting the write operation to any arbitrary file on the host filesystem that the Judge0 process has permission to write.
The vulnerable code can be found in app/jobs/isolate_job.rb at lines 197-201 in version 1.13.0.
Attack Vector
The attack vector is network-based, allowing remote exploitation through normal submission functionality. An attacker can:
- Submit code that creates a symbolic link at the expected run_script path within the sandbox
- Point the symlink to a sensitive file outside the sandbox (e.g., system scripts, configuration files)
- When Judge0 writes the run_script, the content is actually written to the attacker-controlled target file
- Execute the overwritten script to achieve code execution on the host system
The security patch addresses this by implementing proper user isolation and permission controls:
ENTRYPOINT ["/api/docker-entrypoint.sh"]
CMD ["/api/scripts/server"]
+RUN useradd -u 1000 -m -r judge0 && \
+ echo "judge0 ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers && \
+ chown -R judge0: /api
+
+USER judge0
+
ENV JUDGE0_VERSION "1.13.0"
LABEL version=$JUDGE0_VERSION
FROM production AS development
-ARG DEV_USER=judge0
-ARG DEV_USER_ID=1000
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- tmux \
- vim && \
- useradd -u $DEV_USER_ID -m -r $DEV_USER && \
- echo "$DEV_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
-
-USER $DEV_USER
-
CMD ["sleep", "infinity"]
Source: GitHub Commit Details
Detection Methods for CVE-2024-28185
Indicators of Compromise
- Unexpected symbolic links appearing in sandbox directories pointing to system files
- Modifications to system scripts or configuration files that coincide with code submission timestamps
- Unusual file access patterns showing writes to sensitive system paths from the Judge0 process
- Process execution anomalies indicating code running outside the expected sandbox context
Detection Strategies
- Monitor sandbox directories for the creation of symbolic links using file integrity monitoring tools
- Implement system call auditing to detect symlink() calls within sandbox environments
- Review Judge0 submission logs for suspicious payloads containing symlink creation commands
- Deploy container-level security monitoring to detect sandbox escape attempts
Monitoring Recommendations
- Enable audit logging for file system operations in sandbox directories
- Configure alerts for any writes to sensitive system paths by the Judge0 application user
- Implement runtime application self-protection (RASP) to detect exploitation attempts
- Monitor for unexpected process spawning outside the designated sandbox environment
How to Mitigate CVE-2024-28185
Immediate Actions Required
- Upgrade Judge0 to the latest patched version immediately
- Review existing Judge0 installations for signs of compromise
- Isolate Judge0 instances from production systems until patching is complete
- Audit system files for unauthorized modifications
Patch Information
The vulnerability has been addressed in a security patch available through the official Judge0 GitHub repository. The fix implements proper user isolation by creating a dedicated judge0 user and running the application with restricted permissions. Organizations should update their Judge0 deployments to incorporate this security fix.
For detailed information about the vulnerability and remediation, refer to the GitHub Security Advisory GHSA-h9g2-45c8-89cf.
Workarounds
- Run Judge0 in a containerized environment with strict volume mount restrictions
- Implement additional sandboxing layers using technologies like gVisor or Kata Containers
- Configure file system permissions to prevent symlink creation in sandbox directories
- Deploy network segmentation to limit the impact of potential sandbox escapes
# Example: Run Judge0 with restricted volume mounts
docker run --read-only \
--security-opt=no-new-privileges:true \
--cap-drop=ALL \
judge0/judge0:latest
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


