Skip to content

Restore legacy JSXGraph rendering by removing the frontend semantic DSL allowlist #293

@brianlan

Description

@brianlan

Summary

Restore rendering of existing JSXGraph problems by removing the frontend's incompatible semantic JavaScript allowlist after the GraphSandbox iframe has been hardened, while retaining lightweight input limits and syntax/error reporting.

Background / Context

On June 14, 2026, commit bc5b113 replaced the previous lightweight frontend validation with a hand-written strict parser in GraphSandbox.tsx. The parser permits only:

  • Selected board.create(...) calls.
  • Single-variable declarations directly assigned from board.create(...).
  • board.setBoundingBox(...) with exactly one array argument containing four numeric literals.

The authenticated problem page below now displays:

Rendering Error: board.setBoundingBox must use four numeric literals

Reproduction:

http://localhost:8080/problems/6a17020044f95e79a52c15ca

Its stored DSL starts with:

board.setBoundingBox([-2, 2, 4, -3], true);

JSXGraph officially supports setBoundingBox(bbox, keepaspectratio, setZoom), so the boolean second argument is valid. Both active problems with non-empty graph DSL use this valid two-argument form.

The same historical DSL also uses arithmetic, assignments, Math.sqrt, point X()/Y() calls, and multi-variable declarations. Therefore, merely widening the bounding-box regular expression would expose the next validation failure and would not restore compatibility.

The validator rejects the DSL before it is posted to the iframe; JSXGraph itself loads successfully and the browser console shows no JSXGraph runtime error.

Problem

The frontend validator is functioning as a second, incomplete JavaScript parser rather than validating JSXGraph correctness. It rejects valid previously stored graphs and creates an undocumented DSL compatibility boundary that differs from historical ingestion behavior and JSXGraph's actual API.

Existing tests only use simplified one-argument bounding boxes and do not include representative stored graph DSL, so the regression was not detected.

Goal / Expected Behavior

After the sandbox-hardening dependency is complete:

  • Existing stored graph DSL renders again on problem detail, practice, exam, ingestion preview, and coaching surfaces.
  • The frontend does not attempt to semantically parse or allowlist JSXGraph JavaScript.
  • Empty input, excessive input size, JavaScript syntax errors, iframe runtime errors, and render timeouts remain handled and reported.
  • Security isolation is provided by the hardened iframe rather than a divergent hand-written JavaScript grammar.
  • Backend validation for newly generated coaching whiteboard_dsl remains unchanged.

Scope

This issue should cover:

  • Remove the frontend semantic allowlists for element types, option keys, statement forms, and blocked JavaScript tokens.
  • Replace validateDsl with lightweight checks limited to input size and JavaScript syntax compilation, or remove it if equivalent syntax/error handling is performed safely inside the hardened iframe.
  • Add regression fixtures based on the currently stored graph DSL.
  • Verify all GraphSandbox consumers continue to render and report errors correctly.
  • Update stale comments that claim the frontend is enforcing a strict DSL allowlist.

Out of Scope

This issue should not cover:

  • Weakening iframe sandbox flags or CSP.
  • Modifying stored MongoDB graph data to fit the current parser.
  • Building or maintaining a fuller JavaScript parser.
  • Changing the backend _is_allowed_graph_dsl sanitizer used for VLM-generated coaching whiteboards.
  • Adding unrelated JSXGraph features or refactoring consumer pages.
  • Migrating graph DSL to another representation.

Chosen Implementation Approach

Do not extend the hand-written parser. Remove frontend semantic authorization and rely on the hardened opaque-origin iframe plus CSP for security containment.

Retain only:

  • A clear maximum DSL length.
  • JavaScript syntax validation where useful for immediate user-facing errors.
  • Existing iframe runtime exception reporting.
  • Existing timeout/reset behavior.

The historical problem DSL must be treated as a compatibility fixture and rendered without rewriting it.

Implementation Plan

The implementor should:

  1. Confirm the sandbox-hardening dependency has merged and its browser security tests pass.
  2. Add regression tests containing the full or representative stored DSL for problem IDs 6a17020044f95e79a52c15ca and 6a25846d7fc2a674734411f5.
  3. Demonstrate those tests fail under the current semantic validator.
  4. Remove the frontend element, option, token, statement, and literal allowlist parser from GraphSandbox.tsx.
  5. Preserve a size limit and useful syntax/runtime error reporting without rejecting valid JSXGraph/JavaScript semantics.
  6. Update GraphSandbox tests to distinguish syntax errors from iframe runtime/rendering errors.
  7. Verify problem detail, practice, exam, ingestion preview, and coaching GraphSandbox consumers still behave correctly.
  8. Manually confirm the cited problem renders instead of showing the validator error.

Relevant Files / Areas

Likely relevant areas:

  • frontend/src/components/GraphSandbox.tsx
  • frontend/src/components/GraphSandbox.test.tsx
  • frontend/src/pages/ProblemDetailPage.tsx
  • frontend/src/pages/ActivePracticePage.tsx
  • frontend/src/pages/ActiveExamPage.tsx
  • frontend/src/pages/ExamDetailPage.tsx
  • frontend/src/pages/CoachingPage.tsx
  • frontend/src/components/ingestion/EditingStep.tsx
  • frontend/src/components/ingestion/ConfirmingStep.tsx

Reference behavior:

  • JSXGraph Board#setBoundingBox: setBoundingBox(bbox, keepaspectratio, setZoom)
  • Regression URL: http://localhost:8080/problems/6a17020044f95e79a52c15ca

Tests Required

The implementor must add or update automated tests covering:

  • board.setBoundingBox([-2, 2, 4, -3], true) is accepted.
  • Representative historical DSL using arithmetic, assignments, Math.sqrt, point coordinate methods, and multi-variable declarations reaches the iframe and renders.
  • Oversized DSL is rejected with a clear error.
  • Invalid JavaScript syntax produces a clear error.
  • Runtime JSXGraph/JavaScript exceptions are surfaced through the existing iframe error protocol.
  • Reset, timeout, graph switching, and duplicate-render prevention still work.
  • Existing GraphSandbox consumers still render when graphDsl is present.

At minimum, tests should verify:

  • The exact current bug reproduction would fail before the fix and pass after it.
  • Both active stored graph shapes are represented by compatibility fixtures.
  • Security tests from the sandbox-hardening dependency continue to pass after semantic validation is removed.

Manual Verification / Self-Check

Before claiming this issue is done, the implementor must:

  1. Run the focused GraphSandbox tests.
  2. Run the relevant frontend unit and browser/smoke tests.
  3. Open http://localhost:8080/problems/6a17020044f95e79a52c15ca while authenticated and confirm the graph renders.
  4. Verify the other active graph problem renders.
  5. Verify graph rendering in at least one practice or exam flow.
  6. Confirm browser security tests still show blocked parent access and outbound requests.
  7. Record exact commands and results in the PR description.

Suggested verification commands:

cd frontend
npm test -- --run src/components/GraphSandbox.test.tsx
npm test
npm run build
npm run test:smoke:compose

Reviewer Acceptance Checklist

The reviewer should verify that:

  • The sandbox-hardening dependency is complete.
  • The hand-written semantic JavaScript/JSXGraph parser was removed rather than expanded.
  • Size, syntax, runtime-error, timeout, and reset handling remain.
  • Regression tests contain representative historical stored DSL.
  • The cited problem and the second active graph render without data rewriting.
  • Browser confinement tests still pass.
  • The backend coaching sanitizer was not changed.
  • No unrelated page or JSXGraph refactor is bundled into the PR.
  • The PR description includes exact test commands, results, and manual verification.

Dependencies

Depends on:

Follow-Up Work

Potential future work, not required here:

  • Replace JavaScript graph DSL with a structured declarative format if stronger semantic validation becomes a product requirement.
  • Add a larger persisted graph fixture corpus as more historical examples become available.

Definition of Done

This issue is done when:

  • Both active stored graph problems render successfully without modifying their stored DSL.
  • The frontend no longer rejects valid JSXGraph JavaScript through a custom semantic allowlist.
  • Lightweight size/syntax checks and iframe error/timeout behavior remain tested.
  • Sandbox security regression tests continue to pass.
  • The PR includes exact automated and manual verification results.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions