Figma Data HandlingSAFE
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Overview
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
4f83675ca38aOBSERVED · 2026-10-08Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
--- name: figma-data-handling description: 'Handle Figma API data correctly: comments, versions, user data, and privacy compliance. Use when working with Figma comments API, version history, or ensuring GDPR compliance for Figma user data. Trigger with phrases like "figma data", "figma comments", "figma versions", "figma GDPR", "figma user data". ' allowed-tools: Read, Write, Edit version: 1.6.0 license: MIT author: Jeremy Longshore <[email protected]> tags: - saas - figma compatibility: Designed for Claude Code --- # Figma Data Handling ## Overview Work with Figma's data APIs: comments, version history, and user information. Handle sensitive data correctly with redaction and privacy compliance. ## Prerequisites - `FIGMA_PAT` with appropriate scopes (`file_comments:read/write`, `file_versions:read`) - Understanding of GDPR/CCPA basics ## Instructions ### Step 1: Comments API ```typescript const PAT = process.env.FIGMA_PAT!; const FILE_KEY = process.env.FIGMA_FILE_KEY!; // GET /v1/files/:key/comments -- requires file_comments:read scope async function getComments(fileKey: string) { const res = await fetch( `https://api.figma.com/v1/files/${fileKey}/comments`, { headers: { 'X-Figma-Token': PAT } } ); const data = await res.json(); // data.comments is an array of: // { id, message, file_key, parent_id, user, client_meta, resolved_at, created_at, order_id } return data.comments; } // GET with as_md=true to get rich-text comments as markdown async function getCommentsAsMarkdown(fileKey: string) { const res = await fetch( `https://api.figma.com/v1/files/${fileKey}/comments?as_md=true`, { headers: { 'X-Figma-Token': PAT } } ); return (await res.json()).comments; } // POST /v1/files/:key/comments -- requires file_comments:write scope async function postComment(fileKey: string, message: string, nodeId?: string) { const body: any = { message }; if (nodeId) { body.client_meta = { node_id: nodeId }; } const res = await fetch( `https://api.figma.com/v1/files/${fileKey}/comments`, { method: 'POST', headers: { 'X-Figma-Token': PAT, 'Content-Type': 'application/json', }, body: JSON.stringify(body), } ); return res.json(); } // POST reactions to a comment -- requires file_comments:write async function reactToComment(fileKey: string, commentId: string, emoji: string) { return fetch( `https://api.figma.com/v1/files/${fileKey}/comments/${commentId}/reactions`, { method: 'POST', headers: { 'X-Figma-Token': PAT, 'Content-Type': 'application/json', }, body: JSON.stringify({ emoji }), } ).then(r => r.json()); } ``` ### Step 2: Version History API ```typescript // GET /v1/files/:key/versions -- requires file_versions:read scope async function getVersionHistory(fileKey: string) { const res = await fetch( `https://api.figma.com/v1/files/${fileKey}/versions`, { headers: { 'X-Figma-Token': PAT } } ); const data = await res.json(); // data.versions: array of { id, created_at, label, description, user } // Ordered by created_at (most recent first) return data.versions; } // Paginate through all versions async function getAllVersions(fileKey: string) { const versions: any[] = []; let url: string | null = `https://api.figma.com/v1/files/${fileKey}/versions`; while (url) { const res = await fetch(url, { headers: { 'X-Figma-Token': PAT } }); const data = await res.json(); versions.push(...data.versions); // Pagination uses cursor-based pagination url = data.pagination?.next_page ? `https://api.figma.com/v1/files/${fileKey}/versions?before=${data.pagination.next_page}` : null; } return versions; } ``` ### Step 3: User Data and Privacy ```typescript // GET /v1/me -- returns authenticated user interface FigmaUser { id: string; handle: string; img_url: string; email: string; // PII -- handle carefully } // Redact PII before logging or storing function redactFigmaUser(user: FigmaUser): Omit<FigmaUser, 'email'> & { email: string } { return { ...user, email: '[REDACTED]', img_url: '[REDACTED]', }; } // Data classification for Figma responses interface DataClassification { field: string; sensitivity: 'public' | 'internal' | 'pii'; handling: string; } const figmaDataClassification: DataClassification[] = [ { field: 'user.email', sensitivity: 'pii', handling: 'Encrypt at rest, redact in logs' }, { field: 'user.handle', sensitivity: 'internal', handling: 'Do not expose to unauthorized users' }, { field: 'user.img_url', sensitivity: 'pii', handling: 'Do not cache without consent' }, { field: 'file.name', sensitivity: 'internal', handling: 'Standard handling' }, { field: 'comment.message', sensitivity: 'internal', handling: 'May contain PII -- scan before storing' }, { field: 'PAT token', sensitivity: 'pii', handling: 'Never log, never store in code' }, ]; ``` ### Step 4: Data Retention ```typescript // Figma image export URLs expire after 30 days // Plan data retention accordingly interface CachedFigmaData { data: any; fetchedAt: Date; expiresAt: Date; } function createCacheEntry(data: any, ttlMs: number): CachedFigmaData { const now = new Date(); return { data, fetchedAt: now, expiresAt: new Date(now.getTime() + ttlMs), }; } // Cleanup expired entries async function cleanupExpiredData(db: any) { const now = new Date(); const deleted = await db.figmaCache.deleteMany({ expiresAt: { $lt: now }, }); console.log(`Cleaned up ${deleted.count} expired Figma cache entries`); } ``` ### Step 5: Safe Logging ```typescript // Never log these fields from Figma responses const REDACT_FIELDS = ['email', 'img_url', 'access_token', 'refresh_token']; function safeFigmaLog(label: string, data: any) { const safe = JSON.parse(JSON.stringify(data)); function redact(obj: any) { for (const key of
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
4f83675ca38afull audit observations/trust-audit/skill/jeremylongshore__figma-data-handling.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-08 | 4f83675ca38a | SAFE | B | 89 | first audit |
Questions
What does the Figma Data Handling skill do?
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Is Figma Data Handling safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Figma Data Handling access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does Figma Data Handling work with?
Its documentation mentions claude-code and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (4f83675ca38a), read on 2026-10-08. The repository is watched, and a new audit runs when it changes — this is the first audit.