CVE-2025-53967 - Framelink Figma MCP curl command injection

Framelink Figma MCP Server before 0.6.3 exposed a command injection path in its HTTP-facing Figma fetch helper. When the normal fetch call failed, the fallback built a curl command string from request URL and header data and ran it through child_process.exec. Network-reachable MCP instances could let an unauthenticated caller place shell metacharacters into the fallback path and run commands as the MCP process.

This is not Figma’s official MCP server. It affects the third-party Framelink/GLips Figma MCP implementation and wrappers, images, desktop MCP configs, devcontainers, or hosted agent workspaces that start it.

When to use it

Use this recipe when a repository, desktop MCP profile, devcontainer, or hosted agent workspace starts the third-party Framelink/GLips Figma MCP server. It supports source-code remediation, command-injection review, HTTP tool exposure hardening, and audit evidence that Figma request data cannot reach shell-built curl fallbacks.

Inputs

  • Framelink Figma MCP version, MCP config, HTTP bind/auth settings, wrapper scripts, deployment manifests, and Figma token handling.
  • Source paths that fetch Figma URLs, build fallback commands, call child_process.exec, process headers, or serialize request errors/logs.
  • Regression fixtures for shell metacharacters in URLs/headers, fetch failure fallback, valid Figma requests, auth-required requests, and local binding.
  • Boundary evidence: Figma tokens, workspace files, network reach, logs, browser/agent profiles, and who can reach the MCP HTTP endpoint.

Affected versions

  • Vulnerable: figma-developer-mcp / Figma-Context-MCP <0.6.3
  • Fixed: 0.6.3+
  • Affected code shape: fetchWithRetry or equivalent fallback constructs a shell command string containing URL or header values and executes it with child_process.exec, shell: true, sh -c, cmd /c, or PowerShell.
  • Fixed code shape: no untrusted URL/header value reaches a shell string; the server validates input, binds its HTTP listener to localhost by default, and uses fetch, structured argv execution, or no curl fallback.

Indicator-of-exposure

  • The repository installs, vendors, builds, deploys, or documents figma-developer-mcp, Figma-Context-MCP, GLips/Figma-Context-MCP, framelink, or a Docker image/wrapper around the package.
  • MCP client config starts a Figma MCP server through npx, pnpm dlx, bunx, node, Docker, a devcontainer, or a hosted agent workspace.
  • The server’s HTTP endpoint is reachable beyond a single trusted local user: 0.0.0.0, forwarded devcontainer ports, Codespaces, tunnels, shared workstations, browser agents, CI services, or MCP gateways.
  • Figma API keys, file keys, OAuth tokens, design system data, generated source trees, or repository credentials are available to the MCP process.
  • Source or vendored code contains child_process.exec, execAsync, shell-built curl, formatHeadersForCurl, or log output containing full curl commands.

Quick checks:

rg -n "figma-developer-mcp|Figma-Context-MCP|GLips/Figma-Context-MCP|framelink|fetchWithRetry|formatHeadersForCurl|child_process\\.exec|execAsync|curl -s|0\\.0\\.0\\.0|localhost" .
npm ls figma-developer-mcp
pnpm why figma-developer-mcp
yarn why figma-developer-mcp

Windows:

rg -n "figma-developer-mcp|Figma-Context-MCP|GLips/Figma-Context-MCP|framelink|fetchWithRetry|formatHeadersForCurl|child_process\.exec|execAsync|curl -s|0\.0\.0\.0|localhost" .
npm ls figma-developer-mcp
pnpm why figma-developer-mcp
yarn why figma-developer-mcp

Do not validate exposure by sending shell metacharacters, command substitution, redirection, or destructive commands to a live MCP server.

Remediation strategy

  • Upgrade every controlled package, lockfile, image, devcontainer, and MCP server config to figma-developer-mcp 0.6.3+.
  • Remove external reachability. Bind the server to 127.0.0.1 or localhost by default, remove accidental ingress/tunnels, and require an explicit owner and approval before any hosted or shared MCP exposure.
  • If this repository owns a fork or wrapper, remove shell-built curl fallback code. Prefer native fetch; if curl is unavoidable, invoke a fixed executable with structured argv via execFile/spawn and validate URL, host, scheme, and headers before execution.
  • Redact Figma tokens, file keys, OAuth values, and header values from logs. Do not log reconstructed curl commands.
  • Run the MCP process with least privilege: no broad workspace mounts, no repository write token unless needed, no deployment credentials, no host network, and a dedicated low-scope Figma token.
  • Rotate Figma tokens, MCP tokens, repository tokens, and other secrets if an affected HTTP endpoint may have been reachable by untrusted users.

The prompt

Model context: this prompt was generated by GPT 5.5 Extra High reasoning.

You are remediating CVE-2025-53967, a command injection issue in Framelink
Figma MCP Server before 0.6.3 where a shell-built curl fallback can execute
attacker-controlled input. Produce exactly one output:

- A reviewer-ready PR/change request that upgrades or patches the affected
  Figma MCP server, removes shell-built curl fallback behavior, constrains HTTP
  exposure to localhost, adds safe regression tests, refreshes generated
  artifacts, and documents operator secret rotation, or
- TRIAGE.md if this repository does not control an affected Framelink Figma MCP
  package, wrapper, image, config, deployment, or safe containment path.

## Rules

- Scope only CVE-2025-53967 and directly related Framelink/Figma MCP command
  dispatch, HTTP exposure, logging, token, and runtime containment controls.
- Treat Figma API keys, OAuth tokens, file keys, design data, MCP tokens,
  repository tokens, environment variables, command output, logs, generated
  source, and local files as sensitive.
- Do not send shell metacharacter probes, command substitution, redirection, or
  destructive commands to a live MCP server.
- Do not preserve public HTTP exposure, broad workspace mounts, full curl
  command logging, or long-lived high-scope Figma tokens to make the patch
  smaller.
- Do not auto-merge.

## Steps

1. Inventory every controlled reference to `figma-developer-mcp`,
   `Figma-Context-MCP`, `GLips/Figma-Context-MCP`, `framelink`,
   `fetchWithRetry`, `formatHeadersForCurl`, and Figma MCP Docker or npx/pnpm
   launch commands in source, package manifests, lockfiles, Dockerfiles,
   Compose files, devcontainers, CI, MCP client config, runbooks, generated
   SBOMs, and deployment docs.
2. Resolve every package, image, tag, digest, and vendored commit version. A
   target is vulnerable if it resolves to `figma-developer-mcp <0.6.3` or a
   vendored/forked commit that still builds a shell curl command from URL or
   header input.
3. Determine every transport and trust boundary: stdio-only local desktop,
   local HTTP, LAN/shared workstation, devcontainer forwarded port, tunnel,
   browser agent, CI job, hosted MCP gateway, or internet-facing service.
4. Determine which secrets and data the MCP runtime can reach: Figma token,
   OAuth token, file keys, repository checkout, generated code output, package
   tokens, cloud credentials, and mounted home directories.
5. If this repository only contains unrelated docs or only consumes an
   externally owned MCP service, stop with `TRIAGE.md` listing checked files,
   owner, observed version, trust boundary, required fixed version `0.6.3+`,
   and any token rotation recommendation.
6. Upgrade controlled dependencies and images to `0.6.3+`. Regenerate
   lockfiles, SBOMs, dependency reports, container digests, devcontainer
   metadata, and docs as this repo normally does.
7. For owned forks or wrappers, implement the fixed code shape:
   - remove `child_process.exec` or any shell string around URL/header input;
   - use native `fetch`, or `execFile`/`spawn` with a fixed `curl` executable
     and validated argv;
   - validate URL scheme and host before outbound requests;
   - validate and encode headers as data, not shell syntax;
   - remove full curl command logging and redact token-bearing fields.
8. Contain runtime exposure:
   - bind HTTP to `127.0.0.1` by default;
   - remove `0.0.0.0`, tunnel, preview, and forwarded-port defaults;
   - require explicit approval for hosted/shared MCP operation;
   - run with a dedicated low-scope Figma token;
   - remove unnecessary repository, home directory, Docker socket, and cloud
     credential mounts.
9. Add safe regression checks:
   - dependency resolution rejects versions below `0.6.3`;
   - static checks fail on `child_process.exec` or shell-built curl in the
     Figma fetch path;
   - unit tests assert URL/header values are passed as data or rejected before
     command construction;
   - config tests prove HTTP binds to localhost unless an explicit allow-list
     file exists;
   - logs never contain Figma tokens or reconstructed curl commands.
10. Add a PR body section named `CVE-2025-53967 operator actions` that states:
    - package/image/commit versions before and after;
    - whether HTTP was reachable beyond localhost;
    - which Figma tokens, MCP tokens, repository tokens, or generated artifacts
      may have been exposed;
    - whether tokens were rotated or why rotation is not required;
    - which validation commands passed.
11. Run available validation: package install, lockfile integrity, unit tests,
    lint/typecheck, MCP config lint, container build, SBOM refresh,
    dependency/security scans, and a non-secret local smoke test that does not
    execute shell-like input.
12. Use PR title:
    `fix(sec): remediate CVE-2025-53967 in Figma MCP`.

## Stop conditions

- No Framelink/Figma MCP package, wrapper, image, config, deployment, or
  credential path is controlled by this repository.
- A fixed upstream package cannot be consumed and the repository cannot carry a
  reviewed fork or disable the server.
- The only affected runtime is owned by another team or vendor; document owner,
  required fixed version, exposure, and token rotation need in `TRIAGE.md`.
- Verification would require live command-injection probes, command execution,
  production traffic, customer design files, or real secrets.
- Validation fails for unrelated pre-existing reasons; document those failures
  instead of broadening scope.

Output contract

  • A reviewer-ready PR or change request that upgrades Framelink Figma MCP, binds safely, removes shell-built curl fallbacks, adds regression tests, and documents Figma token cleanup.
  • Or a TRIAGE.md file that lists inspected files, owner, observed version, endpoint exposure, Figma token reach, required fix, and residual risk.
  • The output must include exact validation commands and must not run shell payloads, print Figma tokens, fetch customer designs, or use production logs.

Verification - what the reviewer looks for

  • No controlled manifest, lockfile, image, SBOM, or MCP config resolves figma-developer-mcp <0.6.3.
  • The fetch fallback no longer passes URL or header values through a shell command string.
  • HTTP listeners bind to localhost unless a documented exception exists.
  • Tests catch stale package pins, shell-built curl fallback, token-bearing logs, and accidental non-loopback exposure.
  • Operator notes cover Figma/MCP/repository token rotation if the server was reachable beyond a single trusted local user.

Watch for

  • Updating package.json while a global npx command, Docker image, devcontainer, or MCP desktop config still launches the old package.
  • Treating Framelink as Figma’s official MCP server and routing the fix to the wrong owner.
  • Removing curl fallback without testing corporate proxy behavior or documenting the changed failure mode.
  • Logging full request headers or curl commands while adding diagnostics.

References