Problem
The sandbox allowlist used by the plugin assistant is currently maintained by hand in two places:
canvas-plugin-assistant/sandbox-allowlist.md — human-facing reference
canvas-plugin-assistant/scripts/lint_sandbox.py — STDLIB_ALLOWED / THIRD_PARTY_ALLOWED dicts used by the pre-deploy linter
The actual source of truth is plugin_runner/sandbox.py in canvas-medical/canvas-plugins. The public docs page is also derived from that file and tends to lag.
Both of our local copies will silently drift from upstream — meaning the linter can either accept imports the runner rejects, or flag imports the runner now permits. There is currently no mechanism to detect or correct this drift.
Suggested fix
Add a scripts/sync_sandbox_allowlist.py that:
- Fetches
plugin_runner/sandbox.py from canvas-medical/canvas-plugins at a pinned ref (or main).
- Parses the
ALLOWED_MODULES / ALLOWED_GLOBALS (and related) structures out of its AST.
- Regenerates both
sandbox-allowlist.md and the allowlist dicts in lint_sandbox.py — or writes a shared JSON file both consume.
Run it in CI on a weekly cron (or on every push) and fail if the regenerated files differ from what's checked in. That surfaces drift as a PR rather than silently going stale.
Tradeoff
Parsing sandbox.py directly is slightly more brittle to upstream refactors of that one file than scraping the docs page would be, but it reflects actual runtime behavior — which is what we care about for the linter.
Context
Came up while reviewing #87 (better sandbox handling), which introduced the hand-maintained copies.
Problem
The sandbox allowlist used by the plugin assistant is currently maintained by hand in two places:
canvas-plugin-assistant/sandbox-allowlist.md— human-facing referencecanvas-plugin-assistant/scripts/lint_sandbox.py—STDLIB_ALLOWED/THIRD_PARTY_ALLOWEDdicts used by the pre-deploy linterThe actual source of truth is
plugin_runner/sandbox.pyincanvas-medical/canvas-plugins. The public docs page is also derived from that file and tends to lag.Both of our local copies will silently drift from upstream — meaning the linter can either accept imports the runner rejects, or flag imports the runner now permits. There is currently no mechanism to detect or correct this drift.
Suggested fix
Add a
scripts/sync_sandbox_allowlist.pythat:plugin_runner/sandbox.pyfromcanvas-medical/canvas-pluginsat a pinned ref (ormain).ALLOWED_MODULES/ALLOWED_GLOBALS(and related) structures out of its AST.sandbox-allowlist.mdand the allowlist dicts inlint_sandbox.py— or writes a shared JSON file both consume.Run it in CI on a weekly cron (or on every push) and fail if the regenerated files differ from what's checked in. That surfaces drift as a PR rather than silently going stale.
Tradeoff
Parsing
sandbox.pydirectly is slightly more brittle to upstream refactors of that one file than scraping the docs page would be, but it reflects actual runtime behavior — which is what we care about for the linter.Context
Came up while reviewing #87 (better sandbox handling), which introduced the hand-maintained copies.