diff --git a/Dockerfile b/Dockerfile index 036c487d..2ae2d744 100644 --- a/Dockerfile +++ b/Dockerfile @@ -113,6 +113,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libxrender1 \ && rm -rf /var/lib/apt/lists/* +# Create non-root user for security +RUN groupadd -r deeptutor && useradd -r -g deeptutor -s /bin/bash -m deeptutor + # Copy Node.js from frontend-builder stage (avoids re-downloading from NodeSource) COPY --from=frontend-builder /usr/local/bin/node /usr/local/bin/node COPY --from=frontend-builder /usr/local/lib/node_modules /usr/local/lib/node_modules @@ -138,6 +141,9 @@ COPY scripts/ ./scripts/ COPY pyproject.toml ./ COPY requirements.txt ./ +# Change ownership of /app directory to non-root user +RUN chown -R deeptutor:deeptutor /app + # Create necessary directories (these will be overwritten by volume mounts) RUN mkdir -p \ data/user/solve \ @@ -310,6 +316,9 @@ EXPOSE 8001 3782 HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD curl -f http://localhost:${BACKEND_PORT:-8001}/ || exit 1 +# Switch to non-root user for security +USER deeptutor + # Set entrypoint ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/src/tools/code_executor.py b/src/tools/code_executor.py index b1338df9..477b07f7 100644 --- a/src/tools/code_executor.py +++ b/src/tools/code_executor.py @@ -286,8 +286,12 @@ def run_python( timeout: int, assets_dir: Path | None, ) -> tuple[str, str, int, float]: - env = os.environ.copy() - env["PYTHONIOENCODING"] = "utf-8" + # Security fix: Prevent environment variable leaks that could expose credentials + safe_env = { + "PATH": os.environ.get("PATH", ""), + "PYTHONPATH": os.environ.get("PYTHONPATH", ""), + "PYTHONIOENCODING": "utf-8" + } with self.workspace.create_temp_dir() as temp_dir: code_file = temp_dir / "code.py" @@ -305,7 +309,7 @@ def run_python( errors="replace", timeout=timeout, cwd=str(work_dir), - env=env, + env=safe_env, ) elapsed_ms = (time.time() - start_time) * 1000