๐ The Academic Knowledge Management Dilemma
Modern higher education and enterprise training programs rely almost universally on Learning Management Systems (LMS) like Instructure Canvas to distribute coursework, lecture modules, assignments, student discussions, and grading rubrics.
Yet for technical students, researchers, and security practitioners who build their intellectual workflows inside personal knowledge management (PKM) tools like Obsidian, Canvas represents an isolated, walled-off data silo:
- Ephemerality & Term Expiration: Once an academic semester concludes, student access to Canvas courses is routinely archived or revoked. Syllabi, instructor annotations, curated reading lists, and assignment rubrics vanish behind institutional access gates.
- Disconnected Knowledge Silos: Course notes authored in Obsidian remain disconnected from source materials, grading criteria, and module pacing guides living inside the web browser.
- Administrative Token Gating: Canvas exposes an extensive REST API, but institutional administrators frequently disable personal access tokens (
Account > Settings > + New Access Token) for student roles due to enterprise compliance policies. - Third-Party Cloud Aggregation Risks: Existing third-party scrapers and web integrations require routing student session credentials, course documents, and peer discussions through external SaaS servers. For students handling proprietary lab code or education records governed by FERPA and GDPR, third-party cloud aggregation is an unacceptable privacy compromise.
Third-Party Cloud Scraper (High Risk):
[Canvas LMS] ----(Credentials/Course Data)----> [Cloud Relay / SaaS] ----> [Obsidian Vault]
โฒ
โโโ Attack Surface & Data Leakage Risk
Canvas to Obsidian Sync (Hybrid Local-First Architecture):
[Canvas LMS REST API] โโโโ(Direct Token / requestUrl)โโโโโโโโโโโโโโโโโโโโ
โผ
[Canvas LMS Web Tab] โโโโ(Session Cookies)โโโโ> [Browser Ext] โโ(127.0.0.1)โโ> [Obsidian Vault]
To bridge this divide while respecting strict privacy boundaries, I designed and open-sourced Canvas to Obsidian Sync (v0.3.1)โa hybrid, local-first ecosystem that provides two flexible ingestion pathways converging on a unified rendering engine.
๐๏ธ Hybrid Ingestion Architecture
obsidian-canvas-sync employs a hybrid architecture that adapts to both institutional API policies and platform constraints:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CANVAS LMS CLOUD โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Canvas REST API (/api/v1/...) โ โ
โ โ - Courses, Modules, Pages, Syllabus โ โ
โ โ - Assignments, Rubrics & Student Submissions โ โ
โ โ - Discussions & Complete Nested Reply Trees โ โ
โ โ - Calendar Events & Due Date Milestones โ โ
โ โ - Course Files & Static Asset Downloads โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
Mode A: Direct API โ HTTPS โ Mode B: Session-Based
(Obsidian requestUrl) โ (Bearer Token) โ (Browser Session Cookies)
โ โผ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Companion Web Extension โ
โ โ (Chrome / Firefox) โ
โ โ - Session Extractor โ
โ โ - Extraction Toggles โ
โ โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ โ Loopback POST (127.0.0.1:27125)
โ โ (Opt-in / Disabled by default)
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OBSIDIAN PLUGIN RUNTIME โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ CanvasApiClient โ โ Loopback Bridge Server โ โ
โ โ (Direct API Connection) โ โ (conditionally active) โ โ
โ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Canonical Course Payloadโ โ
โ โ (CanvasCoursePayload) โ โ
โ โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Markdown & Link Engine โ โ
โ โ - GFM Converter (Turndown)โ โ
โ โ - Wikilink Transformer โ โ
โ โ - Table Pipe Escaper โ โ
โ โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Asset & File Downloader โ โ
โ โ - Binary Streamer โ โ
โ โ - Size/Extension Filters โ โ
โ โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Vault Note Generator โ โ
โ โ - Path Sanitization โ โ
โ โ - Templated Course Vault โ โ
โ โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OBSIDIAN VAULT STORAGE โ
โ โโโ Canvas/CS101 - Intro to CS/ โ
โ โโโ Course.md, Home.md, Syllabus.md, Grades.md โ
โ โโโ Tasks.md, Discussions.md, Calendar.md โ
โ โโโ Modules/01 - Week 1/01 - Page - Lecture.md โ
โ โโโ Files/ (PDF, DOCX, XLSX, etc.) โ
โ โโโ Attachments/ (Images, Banners) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Two Ingestion Modes
| Ingestion Mode | Primary Mechanism | Best For | Platform Support |
|---|---|---|---|
| Mode A: Direct REST API | Obsidian native requestUrl using Canvas Bearer Token | Standard users, automated multi-course batch syncing, historical/concluded course archiving | Obsidian Desktop & Mobile |
| Mode B: Companion Web Extension | Manifest V3 background script extracting active tab session cookies | Locked-down universities where student API keys are disabled | Chrome, Firefox, Brave, Edge, Arc |
๐ Threat Modeling & Security Hardening
Operating an open HTTP listener within an Electron desktop application introduces potential Cross-Site Port Scanning and CSRF risks if an attacker attempts to transmit payloads to 127.0.0.1.
In obsidian-canvas-sync v0.3.1, the loopback bridge implements strict defense-in-depth controls:
1. Opt-In Loopback Server (Closed by Default)
The local HTTP server on 127.0.0.1:27125 is disabled by default. Users relying on the Direct REST API mode never expose a local TCP port. The bridge only initializes when the user explicitly enables browser extension sync in plugin settings.
2. Mandatory Origin & Client Header Guards
Preflight OPTIONS and POST requests must present:
- An approved extension scheme (
chrome-extension://ormoz-extension://). - The mandatory custom header:
X-Canvas-Sync-Client: Obsidian-Canvas-Sync-Extension.
Browsers prohibit arbitrary websites from setting custom request headers across origins without triggering CORS preflight rejections, isolating the endpoint from drive-by web scripts.
3. Path Traversal & Filename Sanitization
Canvas module names and assignment titles often contain characters that are illegal across POSIX/NTFS file systems or represent directory traversal sequences (../../).
All paths pass through deterministic sanitization:
| |
๐ Comprehensive Synchronization Capabilities
Both ingestion modes stream data into a unified canonical payload (CanvasCoursePayload), producing complete, interconnected course vaults:
1. Grades & Submissions (Grades.md)
Syncs active grade standing, current course scores, submission status (Submitted, Graded, Missing), points earned vs points possible, submitted file links, and instructor feedback comments.
| |
2. Discussions with Nested Reply Trees (Discussions.md)
Preserves instructor discussion prompts along with complete multi-tier nested student replies, formatted as hierarchical callouts with author timestamps and direct link anchors.
3. Assignments & Rubric Table Normalization (Tasks.md)
Canvas rubrics use complex, nested HTML tables. The engine converts these into clean GitHub Flavored Markdown (GFM) tables, capturing rating descriptions, point distributions, and grading criteria:
| |
4. Local File & Asset Downloader (Files/ & Attachments/)
Directly downloads referenced course documents (.pdf, .docx, .pptx, .xlsx, .zip) and embedded images into dedicated vault folders. Includes configurable maximum file size limits (default: 50MB) and extension allowlists.
5. Wikilink Engine with Table Pipe Escaping
All internal module items and syllabus links are resolved to Obsidian [[wikilinks]]. Table-embedded links use strict pipe escaping ([[path\|alias]]) to ensure markdown tables render without broken column boundaries.
๐๏ธ Generated Vault Structure
Synced courses generate a structured, navigable directory hierarchy:
| |
๐ Installation & Getting Started
1. Install the Obsidian Plugin
Method A: Community Plugins (Recommended)
- Open Obsidian Settings > Community Plugins.
- Disable Restricted mode if prompted.
- Search for Canvas Sync Bridge, click Install, and Enable.
Method B: Obsidian BRAT (Beta Builds)
- Install the BRAT Plugin in Obsidian.
- Under BRAT settings, click Add Beta plugin and enter:
https://github.com/SixFiveMil/obsidian-canvas-sync
Method C: Manual Release
Download main.js, manifest.json, and styles.css from the Latest GitHub Release and place them in <Vault>/.obsidian/plugins/canvas-sync-bridge/.
2. Choose Your Sync Method
Option A: Direct REST API (Recommended)
- In Canvas, navigate to Account > Settings > Approved Integrations > + New Access Token.
- Copy your generated access token.
- In Obsidian Settings under Canvas Sync, enter your Canvas Base URL (
https://canvas.instructure.comor your institution domain) and API Token. - Press
Ctrl/Cmd + Pand runCanvas Sync: Select & sync courses(or click the๐ribbon icon) to launch the interactive course selector.
Option B: Browser Extension Bridge (Zero-Token Mode)
- In Obsidian Settings under Canvas Sync, toggle on Enable browser bridge listener.
- Install the companion extension:
- ๐ Chrome Web Store (Chrome, Edge, Brave, Arc, Opera)
- ๐ฆ Firefox Add-ons (Mozilla)
- Open any Canvas course tab in your browser, click the extension icon, test the bridge connection, and click Sync Active Course.
๐ค Open Source & Community RFC
obsidian-canvas-sync is distributed under the MIT License and developed publicly at SixFiveMil/obsidian-canvas-sync.
We welcome feedback, issues, and contributions from students, researchers, and educators. Join the architectural discussion on GitHub Discussions!