
Research
/Security News
Fake imToken Chrome Extension Steals Seed Phrases via Phishing Redirects
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.
@instructure/platform-canvas-fetch
Advanced tools
Canvas-aware fetch wrapper with TypeScript and Zod validation support.
Canvas-aware fetch wrapper with TypeScript and Zod validation support.
pnpm add @instructure/platform-canvas-fetch zod
import { canvasFetch } from '@instructure/platform-canvas-fetch'
import { z } from 'zod'
// Define your response schema
const SubmissionSchema = z.object({
id: z.string(),
user_id: z.string(),
assignment_id: z.string(),
sticker: z.string().nullable()
})
// Make a request
const { data, response, link } = await canvasFetch(
{
path: '/api/v1/courses/123/assignments/456/submissions/789',
method: 'GET'
},
SubmissionSchema
)
// data is fully typed and validated
console.log(data.sticker) // string | null
canvasFetch(options, schema)Main fetch function with Zod validation.
Options:
path (string, required) - API endpoint pathmethod ('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE') - HTTP method (default: 'GET')body (object | FormData | string) - Request bodyparams (object) - Query parameters (encoded with Canvas conventions)headers (object) - Additional headers to merge with defaultssignal (AbortSignal) - For request cancellationReturns: Promise<CanvasFetchResult<T>>
data - Validated response data (typed from Zod schema)response - Raw Response objectlink - Parsed Link headers (for pagination)Throws: CanvasFetchError on HTTP errors or validation failures
configureCanvasFetch(config)Configure global options.
import { configureCanvasFetch } from '@instructure/platform-canvas-fetch'
configureCanvasFetch({
baseUrl: 'https://canvas.instructure.com'
})
const NewSubmissionSchema = z.object({
id: z.string(),
workflow_state: z.string()
})
const { data } = await canvasFetch(
{
path: '/api/v1/courses/123/assignments/456/submissions',
method: 'POST',
body: {
submission: {
submission_type: 'online_text_entry',
body: 'My submission'
}
}
},
NewSubmissionSchema
)
const { data } = await canvasFetch(
{
path: '/api/v1/courses/123/assignments',
params: {
per_page: 50,
include: ['submission', 'score_statistics'], // Encoded as include[]=...
order_by: 'due_at'
}
},
AssignmentsSchema
)
// Request: /api/v1/courses/123/assignments?per_page=50&include[]=submission&include[]=score_statistics&order_by=due_at
import { useInfiniteQuery } from '@tanstack/react-query'
const AssignmentSchema = z.object({
id: z.string(),
name: z.string()
})
const AssignmentsSchema = z.array(AssignmentSchema)
function useAssignments(courseId: string) {
return useInfiniteQuery({
queryKey: ['assignments', courseId],
queryFn: async ({ pageParam }) => {
return canvasFetch(
{
path: pageParam || `/api/v1/courses/${courseId}/assignments`,
params: { per_page: 50 }
},
AssignmentsSchema
)
},
getNextPageParam: (lastPage) => lastPage.link?.next?.url,
initialPageParam: undefined
})
}
import { CanvasFetchError } from '@instructure/platform-canvas-fetch'
try {
const { data } = await canvasFetch({ path: '/api/v1/...' }, Schema)
} catch (error) {
if (error instanceof CanvasFetchError) {
console.error('HTTP Status:', error.status)
console.error('Response:', error.response)
console.error('Error Body:', error.json)
}
}
const { data } = await canvasFetch(
{
path: '/api/v1/courses',
headers: {
'Accept': 'application/json+canvas-string-ids', // Opt-in to string IDs
'X-Custom-Header': 'value'
}
},
CoursesSchema
)
const controller = new AbortController()
const request = canvasFetch(
{
path: '/api/v1/courses',
signal: controller.signal
},
CoursesSchema
)
// Cancel the request
controller.abort()
Automatically included on every request:
X-Requested-With: XMLHttpRequestX-CSRF-Token: [from _csrf_token cookie]Accept: application/jsoncredentials: same-originWhen CanvasFetchError is thrown, the error.json property contains the raw response body from the server. Do not render this data directly to the DOM without proper sanitization, as it may contain user-generated content or malicious payloads that could lead to XSS vulnerabilities.
Safe:
try {
await canvasFetch({ path: '/api/v1/...' }, Schema)
} catch (error) {
if (error instanceof CanvasFetchError) {
// Log for debugging - safe
console.error('API Error:', error.json)
// Display generic message - safe
showErrorToast('An error occurred. Please try again.')
}
}
Unsafe:
try {
await canvasFetch({ path: '/api/v1/...' }, Schema)
} catch (error) {
if (error instanceof CanvasFetchError) {
// ❌ DANGEROUS - could inject malicious HTML/scripts
element.innerHTML = error.json.message
}
}
Always sanitize user-facing error messages or use a framework's built-in XSS protection (e.g., React's JSX automatically escapes).
FAQs
Canvas-aware fetch wrapper with TypeScript and Zod validation support.
We found that @instructure/platform-canvas-fetch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.

Security News
Latio’s 2026 report recognizes Socket as a Supply Chain Innovator and highlights our work in 0-day malware detection, SCA, and auto-patching.

Company News
Join Socket for live demos, rooftop happy hours, and one-on-one meetings during BSidesSF and RSA 2026 in San Francisco.