You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reconcile the file-upload feature with main's security refactor, GCS plot
backend, and nsjail sandboxing.
- evaluation.py / preview.py: use the shared check_code_safety() from the
new security.py; evaluation_function runs it as a pre-execution gate on
the resolved student code (post _resolve_submission).
- security.py: keep `open` and `pathlib` allowed (main's version blocked
them) — student code needs them to read files from params["files"] / the
response payload; runtime _safe_open still blocks writes into the files
dir. security_test.py updated to match.
- Dockerfile: take main's python:3.12 base (bundles shimmy + nsjail).
- CLAUDE.md: merged pipeline/env docs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VSE4TC3eTVreuQhADdtDaj
|`s3_files.py`| Downloads `params["files"]` objects from S3 into the per-request working directory |
15
15
|`dev.py`| CLI wrapper for local manual testing |
@@ -22,7 +22,7 @@ All source lives in `evaluation_function/`:
22
22
-**`demo`**: execute code with no stdin; return stdout/plots as `output` feedback (no pass/fail)
23
23
-**`io_test`**: for each test in `params["tests"]`, execute with `test["input"]` as stdin and compare stdout against `test["expected_output"]`; upload matplotlib plots on pass or fail
4. Upload any captured matplotlib figures to S3 (`_UPLOAD_FOLDER = "evaluatePython"`)
25
+
4. Upload any captured matplotlib figures via `lf_toolkit``upload_image`(`_UPLOAD_FOLDER = "evaluatePython"`); backend is GCS or S3 per `IMAGE_UPLOAD_BACKEND`
26
26
5. Return a `Result` with feedback tags: `pass`, `fail`, `hidden_fail`, `error`, `output`, `summary`
-`evaluation_function/security_test.py` — unit tests for `check_code_safety` (the shared AST blocklist used by both `preview_function` and `evaluation_function`)
169
172
170
173
CI runs on Python 3.12 and uploads JUnit XML results (`.github/workflows/test-lint.yml`).
171
174
@@ -177,14 +180,20 @@ CI runs on Python 3.12 and uploads JUnit XML results (`.github/workflows/test-li
177
180
|`MPLBACKEND`|`Agg`| Set at subprocess runtime to suppress GUI |
|`FUNCTION_RPC_TRANSPORT`|`ipc`|lf_toolkit transport |
183
+
|`FUNCTION_RPC_TRANSPORT`|`stdio`|shimmy↔worker transport (stdio so it survives the sandbox mount namespace)|
181
184
|`LOG_LEVEL`|`debug`| Logging verbosity |
182
-
|`AWS_*` / boto3 credentials | Runtime env | Required for S3 plot uploads. Not needed for `params["files"]` downloads — those are fetched via plain HTTPS GET from a pre-signed/public URL |
185
+
|`IMAGE_UPLOAD_BACKEND`|`gcs`| Plot upload backend in lf_toolkit (`gcs` set in Dockerfile; override to `s3` on the service to use AWS) |
186
+
|`GCS_BUCKET`| Runtime env | Target bucket for matplotlib plot uploads; set per-environment on the Cloud Run service. Auth is via the runtime service account (ADC) — no keys |
187
+
|`AWS_*` / `S3_BUCKET_URI`| Runtime env | Only for the legacy S3 plot-upload backend (`IMAGE_UPLOAD_BACKEND=s3`). Not needed for `params["files"]` / response-payload file downloads — those are plain HTTPS GETs from a pre-signed/public URL |
188
+
|`SANDBOX_ENABLED`|`true`| Wrap the worker in shimmy's nsjail sandbox (needs `--privileged` at run time) |
Dependencies managed via Poetry; `.venv` is created in-project (`poetry.toml`).
185
194
186
195
## Deployment
187
196
188
197
- Push to `main` triggers GitHub Actions (`.github/workflows/`) which builds and deploys to Lambda Feedback automatically
189
198
- The function name is declared in `config.json` as `EvaluationFunctionName: "evaluatePython"` (lowerCamelCase)
190
-
- The base Docker image is `ghcr.io/lambda-feedback/evaluation-function-base/python:test-sandbox-3.12`
199
+
- The base Docker image is `ghcr.io/lambda-feedback/evaluation-function-base/python:3.12` (bundles shimmy + nsjail; sandboxing is enabled via the `SANDBOX_*` env vars in the Dockerfile, not by the base tag)
Copy file name to clipboardExpand all lines: README.md
+9-3Lines changed: 9 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,11 +12,13 @@ Push to `main` triggers GitHub Actions which automatically builds and deploys to
12
12
### Run the Docker Image
13
13
14
14
```bash
15
-
docker run -it --rm -p 8080:8080 ghcr.io/lambda-feedback/evaluatepython:latest
15
+
docker run -it --rm --privileged -p 8080:8080 ghcr.io/lambda-feedback/evaluatepython:latest
16
16
```
17
17
18
18
The image includes [Shimmy](https://github.com/lambda-feedback/shimmy), which listens for HTTP requests on port 8080 and forwards them to the evaluation function.
19
19
20
+
`--privileged` (or `--cap-add SYS_ADMIN`) is required: the image runs student code inside Shimmy's [nsjail](https://github.com/google/nsjail) sandbox (`SANDBOX_ENABLED=true`), and nsjail needs those privileges to create its namespaces. The sandbox runs the worker as `nobody` with a minimal bind-mounted filesystem and seccomp filtering; untrusted imports/builtins are additionally rejected before execution by the AST check in `evaluation_function/security.py`.
21
+
20
22
### Evaluation Modes
21
23
22
24
The function supports three modes, set via `params.mode`.
@@ -80,10 +82,12 @@ Add `"pep8_feedback": true` to any mode to append a style check to the feedback.
80
82
```
81
83
evaluation_function/main.py # IPC server entry point
82
84
evaluation_function/evaluation.py # core evaluation pipeline (all three modes)
docker run -it --rm --privileged -p 8080:8080 evaluatepython
148
152
```
149
153
154
+
`--privileged` is required for the nsjail sandbox (see [Run the Docker Image](#run-the-docker-image)). To run without it for local debugging, disable the sandbox: add `-e SANDBOX_ENABLED=false`.
155
+
150
156
## Deployment to Lambda Feedback
151
157
152
158
The function name is declared in [`config.json`](config.json) as `"evaluatePython"` (lowerCamelCase). Pushing to `main` triggers automated deployment via GitHub Actions.
0 commit comments