Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/codeql-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}

- name: Initialize CodeQL
id: init-codeql
continue-on-error: true
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

# Feature-enablement GET /code-scanning/codeql-action/features returns
# HTTP 503 "No server is currently available" during GitHub API outages.
- name: Wait before CodeQL init retry
if: steps.init-codeql.outcome == 'failure'
run: sleep 20

- name: Retry Initialize CodeQL after GitHub API outage
if: steps.init-codeql.outcome == 'failure'
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
Expand Down Expand Up @@ -197,6 +212,21 @@ jobs:
ref: ${{ format('refs/pull/{0}/merge', github.event.pull_request.number) }}

- name: Initialize CodeQL
id: init-codeql
continue-on-error: true
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

# Feature-enablement GET /code-scanning/codeql-action/features returns
# HTTP 503 "No server is currently available" during GitHub API outages.
- name: Wait before CodeQL init retry
if: steps.init-codeql.outcome == 'failure'
run: sleep 20

- name: Retry Initialize CodeQL after GitHub API outage
if: steps.init-codeql.outcome == 'failure'
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

Materialize accepts only exact SHA-256 pins or a bounded relative `-r` include (no `.`/`..`); a lone `--require-hashes` directive is not trust evidence. See [`docs/doctoring/hourly-nvidia-nim-autofix.md`](docs/doctoring/hourly-nvidia-nim-autofix.md).
Conflict-scope roots fail closed when the immediate parent directory is a symbolic link.
Cursor Cloud Agents cannot complete Figma MCP OAuth against `https://mcp.figma.com/mcp` (allowlisted-client catalog; Cloud unsupported). Desktop/CLI remain the MCP path. Cloud Agents that must read Figma files store `FIGMA_ACCESS_TOKEN`, run `python3 scripts/ci/figma_rest_auth.py`, then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>`. See [`docs/doctoring/figma-cloud-agent-mcp-auth.md`](docs/doctoring/figma-cloud-agent-mcp-auth.md).
29 changes: 29 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,33 @@ sequenceDiagram
- Rust remains the psychometric arithmetic owner. Repair never substitutes
Python for scoring math.

## Figma Cloud Agent REST fallback

```mermaid
flowchart TD
Need["Cloud Agent needs Figma"]
Mcp{"Figma MCP OAuth available?"}
Desktop["Desktop / CLI: Settings → Tools and MCP → Figma → Connect"]
Token{"FIGMA_ACCESS_TOKEN set?"}
Whoami["python3 scripts/ci/figma_rest_auth.py"]
File["python3 scripts/ci/figma_rest_file.py file-key-or-url"]
Mint["Mint a Figma PAT with file_content:read and store the secret"]

Need --> Mcp
Mcp -->|"yes, Desktop/CLI"| Desktop
Mcp -->|"no, Cloud Agent"| Token
Token -->|"no"| Mint
Mint --> Whoami
Token -->|"yes"| Whoami
Whoami --> File
```

Cloud Agents never complete Figma MCP OAuth. Whoami alone is not file
read. The file helper allowlists the key and node ids, opens a
pinned `HTTPSConnection("api.figma.com")`, and prints a token-free JSON
outline. See
[`docs/doctoring/figma-cloud-agent-mcp-auth.md`](docs/doctoring/figma-cloud-agent-mcp-auth.md).

## Quality gates

`scripts/ci/` ships with 100% statement/branch coverage and 100% docstrings.
Expand All @@ -106,5 +133,7 @@ tests pin workflow structure and governance prose so drift fails closed.
contract.
- [`docs/doctoring/hourly-nvidia-nim-autofix.md`](docs/doctoring/hourly-nvidia-nim-autofix.md)
— current increment's repair-worker decision and APA 7th citations.
- [`docs/doctoring/figma-cloud-agent-mcp-auth.md`](docs/doctoring/figma-cloud-agent-mcp-auth.md)
— Cloud Agent Figma MCP boundary and REST file-read fallback.
- [`docs/doctoring/fast-mlsirm-hourly-review-caller.md`](docs/doctoring/fast-mlsirm-hourly-review-caller.md)
— product-specific psychometric repair heartbeat and scientific gates.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Semantic Versioning where the repository publishes a release.

### Added

- Added Cloud Agent Figma REST helpers `scripts/ci/figma_rest_auth.py` and `scripts/ci/figma_rest_file.py` that verify `FIGMA_ACCESS_TOKEN` against pinned `GET /v1/me` and then read an allowlisted `GET /v1/files/{key}` (optional `/nodes` or `/images`) so whoami is not treated as file read.
- Added a trusted pull-request comment router for `@cwl-noema-review` and review-only `@opencode-agent` dispatches, with an organization sweep, exact-head receipts, repository allowlisting, fixed runners, immutable checkout pins, and a permanent 100% statement/branch/docstring quality gate.
- Added exact-base `uv.lock` materialization that reconstructs standalone nested projects with a checksum-pinned official `uv` exporter, isolated frozen/offline execution, strict exact-pin and SHA-256 output validation, and complete Python 3.10/3.14 quality evidence.
- Added a permanent exact-head contract workflow for the hourly review-repair scheduler, immutable reusable-workflow source, NVIDIA NIM model boundary, credential isolation, and fail-closed unattended-agent permissions.
Expand All @@ -26,6 +27,7 @@ Semantic Versioning where the repository publishes a release.

### Fixed

- Retried CodeQL `init` after a GitHub feature-enablement API 503 (`No server is currently available`) so a partial GitHub outage does not fail the required compatibility analysis.
- Materialized base Python locks only when every package line is an exact SHA-256 pin or a bounded relative `-r`/`--requirement` include. A lone `--require-hashes` directive, a dotted include such as `./lock.txt`, or `-r other-hashes.txt` no longer enters the trusted build context.
- Refused a conflict-scope repository root whose immediate parent is a symbolic link, so a swapped parent cannot redirect the canonical worktree after the last-component check (CWE-367).
- Bounded the Strix quality self-test's deterministic timeout fixtures to 3-second process and 5-second fake-sleep budgets so exact-head policy evidence completes inside the existing job limit without changing production Strix scanner timeouts, providers, credentials, or review semantics.
Expand All @@ -39,6 +41,7 @@ Semantic Versioning where the repository publishes a release.

### Security

- Pin Figma REST calls to `http.client.HTTPSConnection("api.figma.com")`, allow only the `X-Figma-Token` header, allowlist file keys and node ids, and cap whoami/file bodies so `file://`, `Host` retargeting, and path traversal cannot leave the pinned origin.
- Reject `.github/` and `scripts/ci/` from review-thread-derived autofix path authority so an untrusted inline reviewer cannot authorize the write-capable repair agent to modify workflows, CODEOWNERS, actions, scheduler code, or CI helpers that govern its own control plane.
- Require the model-write snapshot and exact-path allowlist to remain outside the pull-request worktree, checking both absolute and resolved locations so repository-local controls and outside-looking symlinks resolving into the repository fail closed before they can authorize or verify model changes.
- Snapshot the complete pre-model worktree for ordinary and conflict repair and reject every model-caused created, deleted, modified, mode-changed, retargeted, ignored, dangling, directory-backed, external-link, metadata-race, or out-of-scope path before staging or push.
Expand All @@ -55,6 +58,7 @@ Semantic Versioning where the repository publishes a release.

### Documentation

- Added an APA 7 doctoring record for the Cloud Agent Figma MCP OAuth boundary, REST whoami and file-read helpers, operator next-action contract, and Figma file-endpoint citations.
- Added an APA 7 doctoring record for conflict-control evidence isolation, including the Strix-reported trust-boundary failure, test-first remediation, canonical-path rule, operator contract, rollback, MITRE CWE-22, and current GitHub Actions secure-use guidance.
- Added operator and APA 7 doctoring records for the hourly cadence, immutable source identity, NVIDIA NIM provider and secret boundary, high-reasoning Mistral Small 4 writer, model-process credential isolation, modular MSA ownership, product-specific caller activation, verification contract, and rollback.
- Added DiskSage operational documentation for the hourly RCA loop, bounded retry cadence, permission model, standalone and MSA reuse, verification, rollback, and APA 7 references.
Expand Down
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,8 @@ repeatable compile command.
cross-repo references as `owner/repo#num` or full URLs; durable knowledge in the repo/Project, not
private memory; one roadmap phase at a time) are defined in `docs/CWL-MASTER-CONTEXT.md` §7 and
apply here.
- **Figma on Cloud Agents is REST-only.** Do not retry MCP Connect against
`https://mcp.figma.com/mcp`. Store `FIGMA_ACCESS_TOKEN`, run
`python3 scripts/ci/figma_rest_auth.py`, then
`python3 scripts/ci/figma_rest_file.py <file-key-or-url>`. Desktop/CLI keep
the full MCP path. See `docs/doctoring/figma-cloud-agent-mcp-auth.md`.
1 change: 1 addition & 0 deletions docs/CWL-MASTER-CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ GitHub **Project #1** is the shared source of truth. Structure: real **Issues**
- **BLOCKER B1**: org GitHub Actions effectively HALTED (~86 queued, ~0 in_progress org-wide) — likely the Actions monthly SPENDING CAP. Blocks ALL PR checks/merges + the Cloudflare DNS run (nameservers). Fix (org-admin): raise the Actions spending limit OR add a self-hosted runner. Nothing merges until then.
- **Decisions pending**: (D1) Code Security enablement vs the CodeQL-only code_scanning ruleset (osv/trivy/scorecard SARIF upload) — a private repo needs GHAS seats; reconcile or make those checks non-required. (D2) trivy `limit-severities-for-sarif: true` (gate only CRITICAL/HIGH) — held pending the user's strict-security preference.
- **Built this session, PR-open, awaiting merge (B1)**: see Project #1 PRs (contextual-orchestrator cost/routing #46 + naruon#973; pg-llm-batch; keyverse Keycloak; inkspan; SBOM #361; opencode auto-retry #360; Strix neutral #349 + emit #358; appguardrail collector #254; auto-rebase #357; noema #359/naruon#970; PDF-DOM naruon#965/newsdom#300; SDP #11; fast-mlsirm GPGPU #109; scopeweave #284/naruon#971; fuzzing 10 PRs (found+fixed 2 real naruon bugs); Cloudflare DNS/Pages #362; this protocol #363; planning #974). Human step: report the mapasevo21 malware file (github user-attachments) to GitHub Abuse; rotate the xtrmLLMBatchPython-leaked keys; the org-admin runner/decisions above.
- **Figma MCP on Cloud Agents (2026-08-16)**: `https://mcp.figma.com/mcp` is OAuth-only and not supported in Cursor Cloud Agents / Automations. Desktop IDE and CLI remain the MCP path. Cloud Agents that must read Figma files store `FIGMA_ACCESS_TOKEN`, run `python3 scripts/ci/figma_rest_auth.py`, then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>`. See `docs/doctoring/figma-cloud-agent-mcp-auth.md`.

---
*Keep this current. Update Project #1 as the live tracker; this file is the narrative brief a fresh agent reads to reconstruct the whole picture.*
Expand Down
145 changes: 145 additions & 0 deletions docs/doctoring/figma-cloud-agent-mcp-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Figma MCP auth on Cursor Cloud Agents

## Incident

A Cursor Cloud Agent tasked with Figma work discovers the official Figma MCP
server (`https://mcp.figma.com/mcp`) in an `error` state: live tool discovery
fails and no Figma tools are available. Re-running Connect / OAuth from the
Cloud Agent cannot repair it. Desktop Cursor and the Cursor CLI remain able to
complete the same OAuth flow.

## Live evidence (2026-08-16)

Unauthenticated `initialize` against the remote MCP endpoint:

```http
POST https://mcp.figma.com/mcp
HTTP/2 401
WWW-Authenticate: Bearer resource_metadata="https://mcp.figma.com/.well-known/oauth-protected-resource",scope="mcp:connect",authorization_uri="https://api.figma.com/.well-known/oauth-authorization-server"
```

Body: `Unauthorized`.

The same environment can reach Figma (`HEAD`/`POST` complete; no egress block).
`GET https://api.figma.com/v1/me` without a token returns
`{"status":403,"err":"Invalid token"}`. No `FIGMA_*` environment variables are
present on the Cloud Agent VM.

Figma's remote MCP is OAuth 2.1 with PKCE and an allowlisted MCP client
catalog. Cursor Cloud Agents are not a supported client for that catalog.

## Decision

Do not treat Figma MCP as available inside Cloud Agents or Cloud Automations.
Cursor staff stated this explicitly: Figma MCP is not supported in Cloud agents;
it is fully supported in the IDE and the CLI (Neilson, 2026). There is no
estimated timeline; support is a joint Cursor/Figma change.

Use two disjoint auth paths:

| Surface | Auth | Capability |
|---|---|---|
| Cursor Desktop / CLI | Figma MCP OAuth (`Settings → Tools & MCP → Figma → Connect`) | Full MCP toolset (`get_design_context`, `use_figma`, write-to-canvas, …) |
| Cursor Cloud Agent | Figma personal or plan access token in `FIGMA_ACCESS_TOKEN` | REST only: `python3 scripts/ci/figma_rest_auth.py` then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>` (`X-Figma-Token` only, pinned `https://api.figma.com/v1/me` and `/v1/files/{key}`) |

A personal or plan access token does **not** unlock Figma MCP on Cloud Agents.
It only authorizes the REST API. Do not commit the token. Do not put it in
`environment.json`, workflow YAML, or chat output.

Prefer a **plan access token** for organization Cloud Agent fleets
(admin-managed, expiry up to one year; Figma, 2026a). Use a personal access
token only when the operator is acting on their own account (maximum 90 days).
Both kinds are stored in the same secret name. Whoami and file bodies are
capped (64 KiB / 8 MiB). The opener refuses every header except
`X-Figma-Token` so a `Host` override cannot retarget TLS (CWE-22; MITRE, 2026).

## Operator procedure

1. **Desktop / CLI MCP (preferred for design-to-code).** In Cursor Desktop,
Settings → Tools & MCP → Figma → Connect, then Allow access in the Figma
browser window. Confirm with a Figma MCP `whoami` from a desktop agent.
2. **Cloud Agent REST fallback.** In Figma: account menu → Settings → Security
→ Personal access tokens → Generate new token. Name it for Cloud Agents.
Grant `file_content:read` (add comment scopes only if needed). Maximum
expiry is 90 days (Figma, 2025). Store the value as the Cursor environment
secret `FIGMA_ACCESS_TOKEN`.
3. **Verify the secret without printing it:**

```bash
python3 scripts/ci/figma_rest_auth.py
```

Success prints a handle/id/email line. Missing or rejected tokens exit
non-zero and never echo the secret. The helper opens a pinned
`http.client.HTTPSConnection("api.figma.com")` with
`ssl.create_default_context()` to `GET /v1/me` and refuses any other URL, so
Semgrep `dynamic-urllib-use-detected` does not apply
(`urllib.request.urlopen` is not used). The historical
`httpsconnection-detected` audit (pre-3.4.3 default-verify gap) is
suppressed only at that literal sink.
4. **Read the file the buyer asked for.** Whoami is not file read. After the
secret verifies, run:

```bash
python3 scripts/ci/figma_rest_file.py 'https://www.figma.com/design/<file_key>/<name>?node-id=12-34'
```

Or pass the file key and node id directly:

```bash
python3 scripts/ci/figma_rest_file.py '<file_key>' --node-id 12:34
python3 scripts/ci/figma_rest_file.py '<file_key>' --node-id 12:34 --images
```

The helper allowlists the file key (10-128 letters or digits) and node
ids before they enter the path, opens the same pinned
`api.figma.com` origin, and prints a token-free JSON outline (pages and
top-level frames at depth 2 by default). `--images` returns HTTPS PNG
URLs for those nodes. `file://`, `http://`, and `api.figma.com` locators
are refused. Use the outline or image URLs as the next design-to-code
input; do not retry MCP Connect.

## Why MCP Connect cannot be finished here

Figma only accepts MCP clients listed in its catalog (Figma, 2026b). The
Cloud Agent MCP client is not on that list, so the OAuth authorize endpoint
answers `Forbidden` / `401` before a browser grant can be created. Asking the
user to "click Connect" inside a Cloud Agent or Automation therefore cannot
succeed. The same Connect button works in the desktop IDE because that client
is allowlisted.

## APA 7th references

Figma. (2025). *Changelog*. Figma Developer Docs. Retrieved August 16, 2026,
from https://developers.figma.com/docs/rest-api/changelog/

Figma. (2026a). *Personal access tokens*. Figma Developer Docs. Retrieved
August 16, 2026, from
https://developers.figma.com/docs/rest-api/personal-access-tokens/

Figma. (2026b). *Set up the remote server (recommended)*. Figma Developer Docs.
Retrieved August 16, 2026, from
https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/

Figma. (2026c). *Endpoints*. Figma Developer Docs. Retrieved August 16, 2026,
from https://developers.figma.com/docs/rest-api/file-endpoints/

Fielding, R., Nottingham, M., & Reschke, J. (Eds.). (2022). *HTTP semantics*
(RFC 9110). Internet Engineering Task Force.
https://www.rfc-editor.org/rfc/rfc9110

Hardt, D., Parecki, A., & Lodderstedt, T. (Eds.). (2025). *The OAuth 2.1
authorization framework* (Internet-Draft draft-ietf-oauth-v2-1). Internet
Engineering Task Force. Retrieved August 16, 2026, from
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1

MITRE. (2026). *CWE-22: Improper limitation of a pathname to a restricted
directory ('Path Traversal')*. https://cwe.mitre.org/data/definitions/22.html

Neilson, K. (2026, June 10). Reply in *Figma MCP shows "Forbidden" in
Automations / Cloud Agents*. Cursor Forum. Retrieved August 16, 2026, from
https://forum.cursor.com/t/figma-mcp-shows-forbidden-in-automations-cloud-agents/162969

Sakimura, N., Bradley, J., & Agarwal, N. (2015). *Proof Key for Code Exchange
by OAuth public clients* (RFC 7636). RFC Editor.
https://doi.org/10.17487/RFC7636
Loading
Loading