registry  /  figma-claw  /  2.3.1

figma-claw@2.3.1

CLI tooling for Figma workflows.

AI Security Review

scanned 3h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No confirmed malicious install-time behavior was found. The main unresolved risk is explicit setup of package-owned Codex/Claude skills and a browser extension that rewrites Figma scripts for the tool's Figma workflow.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs figma-claw setup, auth/session/figma commands, or installs/enables the bundled extension
Impact
Could extend local AI-agent capabilities and modify Figma pages when deliberately invoked; no unconsented package install mutation or off-domain exfiltration found.
Mechanism
Explicit agent skill setup and Figma Playwright/browser-extension automation
Rationale
Static inspection supports a warning for explicit first-party agent extension setup and Figma script rewriting, but not a malicious block. There is no install-time mutation, non-Figma exfiltration endpoint, or hidden remote payload execution in the inspected package files.
Evidence
package.jsondist/cli.jsREADME.mddist/extension/chrome-mv3/manifest.jsondist/extension/chrome-mv3/rules/figma.jsondist/extension/chrome-mv3/figma.jsdist/extension/chrome-mv3/content-scripts/content.js~/.codex/skills~/.claude/skills~/.figma-claw/auth/default/storage-state.json~/.figma-claw/profiles
Network endpoints3
www.figma.com/api/user/statewww.figma.com/login*://*.figma.com/*

Decision evidence

public snapshot
AI called this Suspicious at 86.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • dist/cli.js setup command copies bundled skills into ~/.codex/skills and ~/.claude/skills after explicit user invocation
  • dist/cli.js can spawn pnpm exec playwright install chromium from setup
  • dist/extension/chrome-mv3 redirects Figma scripts to extension code and executes rewritten Figma script content with Function()
  • dist/cli.js reads Figma storage-state cookies and calls https://www.figma.com/api/user/state for auth checks
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle hooks
  • Agent skill installation is under explicit figma-claw setup, not install-time execution
  • Network use is aligned with Figma CLI/auth/browser automation functionality
  • Figma email/password options are used to fill Figma login in a headed browser and then persist Playwright storage state
  • No evidence of credential exfiltration to non-Figma endpoints or remote payload download
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkWebSocket
Supply chain
HighEntropyStringsMinifiedUrlStrings
Manifest
NoLicense
scanned 6 file(s), 535 KB of source, external domains: 127.0.0.1, github.com, goo.gl, placehold.co, www.figma.com

Source & flagged code

4 flagged · loading source
dist/cli.jsView file
1#!/usr/bin/env node L2: import{createRequire as e}from"node:module";import{existsSync as t,realpathSync as n}from"node:fs";import r,{resolve as i}from"node:path";import{fileURLToPath as a}from"node:url";i... L3: `)}displayWidth(e){return r(e).length}styleTitle(e){return e}styleUsage(e){return e.split(` `).map(e=>e===`[options]`?this.styleOptionText(e):e===`[command]`?this.styleSubcommandTe...
High
Child Process

Package source references child process execution.

dist/cli.jsView on unpkg · L1
10- too many long flags`):Error(`${n} L11: - unrecognised flag format`)}if(t===void 0&&n===void 0)throw Error(`option creation failed due to no flags found in '${e}'.`);return{shortFlag:t,longFlag:n}}e.Option=n,e.DualOption... L12: - specify the name in Command constructor or using .name()`);return t||={},t.isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerComman... ... L19: `),this.outputHelp({error:!0}));let n=t||{},r=n.exitCode||1,i=n.code||`commander.error`;this._exit(r,i,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in a.env... L20: Expecting one of '${n.join(`', '`)}'`);let r=`${e}Help`;return this.on(r,e=>{let n;n=typeof t==`function`?t({error:e.error,command:e.command}):t,n&&e.write(`${n}\n`)}),this}_output... L21: const state = $1.getState()
High
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution; review context before blocking.

dist/cli.jsView on unpkg · L10
1#!/usr/bin/env node L2: import{createRequire as e}from"node:module";import{existsSync as t,realpathSync as n}from"node:fs";import r,{resolve as i}from"node:path";import{fileURLToPath as a}from"node:url";i... L3: `)}displayWidth(e){return r(e).length}styleTitle(e){return e}styleUsage(e){return e.split(` `).map(e=>e===`[options]`?this.styleOptionText(e):e===`[command]`?this.styleSubcommandTe... ... L10: - too many long flags`):Error(`${n} L11: - unrecognised flag format`)}if(t===void 0&&n===void 0)throw Error(`option creation failed due to no flags found in '${e}'.`);return{shortFlag:t,longFlag:n}}e.Option=n,e.DualOption... L12: - specify the name in Command constructor or using .name()`);return t||={},t.isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerComman...
High
Command Output Exfiltration

Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.

dist/cli.jsView on unpkg · L1
1#!/usr/bin/env node L2: import{createRequire as e}from"node:module";import{existsSync as t,realpathSync as n}from"node:fs";import r,{resolve as i}from"node:path";import{fileURLToPath as a}from"node:url";i... L3: `)}displayWidth(e){return r(e).length}styleTitle(e){return e}styleUsage(e){return e.split(` `).map(e=>e===`[options]`?this.styleOptionText(e):e===`[command]`?this.styleSubcommandTe... ... L10: - too many long flags`):Error(`${n} L11: - unrecognised flag format`)}if(t===void 0&&n===void 0)throw Error(`option creation failed due to no flags found in '${e}'.`);return{shortFlag:t,longFlag:n}}e.Option=n,e.DualOption... L12: - specify the name in Command constructor or using .name()`);return t||={},t.isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerComman... ... L19: `),this.outputHelp({error:!0}));let n=t||{},r=n.exitCode||1,i=n.code||`commander.error`;this._exit(r,i,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in a.env... L20: Expecting one of '${n.join(`', '`)}'`);let r=`${e}Help`;return this.on(r,e=>{let n;n=typeof t==`function`?t({error:e.error,command:e.command}):t,n&&e.write(`${n}\n`)}),this}_outpu
Low
Weak Crypto

Package source references weak cryptographic algorithms.

dist/cli.jsView on unpkg · L1

Findings

3 High2 Medium6 Low
HighChild Processdist/cli.js
HighSame File Env Network Executiondist/cli.js
HighCommand Output Exfiltrationdist/cli.js
MediumNetwork
MediumEnvironment Vars
LowScripts Present
LowWeak Cryptodist/cli.js
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License