T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/token-scanner.mjs:16- Finding
Cross-Client Credential Discovery and Replication Exceeds Least Privilege
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Figma skill mostly does what it claims, but its setup reads tokens from other local apps and stores a bearer token in OpenClaw config with insufficient scoping and disclosure.
Install only if you are comfortable granting OpenClaw access to the Figma account found in other local MCP clients. Before running bootstrap-token.mjs, use --dry-run, check which credential file it selects, and prefer a duplicate or branch for write workflows. Review ~/.openclaw/openclaw.json permissions and remove or rotate the copied token if you no longer need the integration.
scripts/token-scanner.mjs:16Cross-Client Credential Discovery and Replication Exceeds Least Privilege
README.md:113Manual Installation Uses an Unpinned Mutable Repository Source
Referenced artifact was not completely inspected
node scripts/figma-mcp-cli.mjs get_screenshot \
Referenced artifact was not completely inspected
node scripts/figma-mcp-cli.mjs get_screenshot \
The skill instructs the agent/operator to read an OAuth token from ~/.claude/.credentials.json and copy it into another config file. This is credential handling and persistence of a sensitive token outside its original store, which increases exposure risk through accidental disclosure, weaker file protections, logging, backup leakage, or reuse by unintended processes.
node ~/.openclaw/skills/figma-agent/scripts/auth.mjs
Reads CC OAuth token from `~/.claude/.credentials.json`, writes it into `~/.openclaw/openclaw.json`. Then restart the OpenClaw gateway.
**Token check:** `node ~/.openclaw/skills/figma-agent/scripts/auth.mjs --check`
This code directly targets a credential file path and parses it to recover access tokens, refresh tokens, and client secrets. In the context of a Figma integration skill, intentional credential discovery from another tool's private auth store is especially dangerous because it enables credential access beyond the user’s likely expectations and broadens compromise scope to multiple services or sessions.
*/
export function scanForFigmaToken() {
// 1. Claude Code
const claudePath = join(HOME, '.claude', '.credentials.json');
if (existsSync(claudePath)) {
try {
const creds = JSON.parse(readFileSync(claudePath, 'utf8'));
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Figma Agent is not just a raw MCP wrapper. It is a structured OpenClaw skill for working with Figma in two modes:
- **Direct read / inspect** for screenshots, metadata, design context, variables, and Code Connect inspection
- **Structured write / edit workflows** for building screens, reviewing existing work, applying tokens, and iterating on designs through ACP coding sessions
Typical use cases:
The README promotes write/edit workflows that can modify live Figma content but does not clearly instruct users to confirm target files/nodes, verify edit intent, or warn about unintended changes. In an agentic environment, ambiguous edit authority can lead to accidental modification of production design assets or propagation of unwanted changes across shared files.
The bootstrap instructions invoke a script that extracts or refreshes a Figma MCP token and writes server configuration into the user's OpenClaw config, but the README does not present this as a prominent security-sensitive action. Users may run it without understanding that credentials are being harvested from another client context and persisted locally, increasing the risk of secret exposure or unintended account linkage.
The skill exposes operational behaviors that involve code execution, filesystem access, and likely networked interactions, but it declares no explicit tool scope or allowed-tools boundary. In an agent environment, this increases the chance that the skill can invoke broader capabilities than intended, making misuse or unintended side effects harder to constrain and audit.
The example reply text is in German ("Hier ist der aktuelle Stand:") within mandatory delivery instructions, which signals a fixed output language. The file does not offer user opt-in, language selection, or a documented German-only regional justification, so this conflicts with the language/locale policy criteria.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
**Why `--out`?**
Without it, the Figma API returns base64-encoded JSON → renders as inline text in Telegram, not a photo. The `--out` flag decodes and writes a real PNG file that `MEDIA:` sends as an attachment.
**Screenshot directory:** `~/workspace-dev-botti/screenshots/` (create if missing)
**Validation pattern (every write operation):**
The reference documents multiple write-capable tools that can create files, generate designs, add mappings, and execute arbitrary JavaScript in the Figma plugin context, but it does not clearly warn that these operations mutate remote Figma state. In an agent skill, omission of mutation warnings increases the chance an agent or user will invoke destructive or unintended actions under the assumption the tools are informational like the read-only figma__* tools.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
| Anti-Pattern | Why It Fails |
|-------------|-------------|
| Editing colors/layout before fixing text auto-resize | Any write can trigger text reflow in unfixed nodes |
| Setting all text to `WIDTH_AND_HEIGHT` without checking context | Column-width text needs `HEIGHT` mode |
| Rounding dimensions on auto-layout parents | Can break child sizing — round leaf nodes first |
| Skipping font loading before text property changes | Silent failure or error — see [gotchas#promises](../plugin-api-gotchas.md#promises) |
| Doing cleanup and tokenization in the same pass | Separate concerns — fix structure first, then bind tokens |
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return null;
}
const metaRes = await fetch('https://api.figma.com/v1/oauth/token');
if (!metaRes.ok) {
console.error(`⚠️ Failed to fetch OAuth metadata: ${metaRes.status}`);
return null;
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return null;
}
const metaRes = await fetch('https://api.figma.com/v1/oauth/token');
if (!metaRes.ok) {
console.error(`⚠️ Failed to fetch OAuth metadata: ${metaRes.status}`);
return null;
The client accepts an arbitrary URL while always attaching the Figma authorization token, so a caller can direct credentials to a non-Figma endpoint. In an agent/skill context where configuration may be influenced by users or other components, this creates a realistic secret-exfiltration path if the URL is overridden maliciously or mistakenly.
The function name, signature, and documentation promise a pre-write safety checkpoint, but the implementation performs a normal write and explicitly skips the checkpoint. In a design-editing skill, this can mislead callers into believing destructive changes are recoverable when they are not, increasing the chance of irreversible modification or loss of design state.
The code silently falls back to a plain write for a function intended to provide a recovery checkpoint, so safety-sensitive behavior is degraded without notifying the caller. In a write-capable Figma skill, that increases the risk of unrecoverable or hard-to-revert changes because automation may proceed under a false assumption of rollback protection.
The code enumerates and reads credential stores belonging to other local AI tools (Claude Code, Codex, Windsurf) to extract Figma access tokens, refresh tokens, client IDs, and client secrets. Even though it is limited to local file I/O, this is still credential harvesting behavior outside the immediate scope of a normal Figma integration and creates a high-risk path for unauthorized access to secrets from unrelated applications.
The scanner accesses highly sensitive tokens and even client secrets from local credential files without any visible user notice, prompt, or consent in this code path. Secret access without transparency increases the chance of silent credential misuse and makes it difficult for users to understand that installing a Figma skill grants access to authentication material from other tools.
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.
- Very thin font weights (<300) at small sizes
- Text over images without overlay/scrim
Report these as "flagged for manual contrast check" — automated WCAG scoring is beyond the scope of a quick audit.
---
This code conditionally decodes API-returned image data and writes it directly to the path supplied via --out. While the write is part of the documented feature, there is no pre-action user warning or confirmation that an existing file may be overwritten or that binary output will be saved to disk; the only disclosure appears after the write completes.
The manifest focuses on interacting with Figma designs, tokens, variables, and Code Connect. Reading OpenClaw configuration from the user's home directory is ancillary local configuration access that is not described in the manifest and is not inherently part of Figma design operations.
No suspicious patterns detected.