Skip to content

docs: attribute Cursor cloud agents from git author or the socket - #965

Merged
davidmytton merged 5 commits into
mainfrom
david/cursor/cloud-agent-identity-c2f1
Sep 26, 2026
Merged

davidmytton merged 5 commits into
mainfrom
david/cursor/cloud-agent-identity-c2f1

Conversation

@davidmytton

@davidmytton davidmytton commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

The Cursor install now matches the server wrapper in https://github.com/arcjet/arcjet/pull/9450 (2566fdcc4).

arcjet-hook asserts X-Arcjet-Principal from, in order: CURSOR_USER_EMAIL, ARCJET_PRINCIPAL, GIT_AUTHOR_EMAIL / GIT_AUTHOR_NAME, then the Cloud Agent socket (turn/user-email then owner/user-email). $USER / $USERNAME are used only when the value is not ubuntu. The Windows script uses the env fallbacks only.

Cloud agent VMs run as ubuntu and do not set CURSOR_USER_EMAIL. Some also leave the git author unset. The socket is what Activity should show in that case. ARCJET_PRINCIPAL remains the explicit override.

The hook expander, official event names, and allow-as-{} answers are unchanged.

Open in Web Open in Cursor 

Cloud agent VMs run as ubuntu and do not set CURSOR_USER_EMAIL. The
install template now falls through to GIT_AUTHOR_EMAIL and
GIT_AUTHOR_NAME, which Cursor already sets to the person who started
the run, so Activity shows that person instead of the VM user.

Co-authored-by: David Mytton <[email protected]>
@vercel

vercel Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
arcjet-docs Ready Ready Preview Sep 26, 2026 10:16pm UTC

Request Review

cursoragent and others added 2 commits September 26, 2026 22:02
Use ARCJET_PRINCIPAL, then GIT_AUTHOR_EMAIL / GIT_AUTHOR_NAME, then
the Cloud Agent socket (turn/user-email, then owner/user-email), then
$USER / $USERNAME. Drop CURSOR_USER_EMAIL. Windows stays env-only.

Co-authored-by: David Mytton <[email protected]>
@cursor cursor Bot changed the title docs: attribute Cursor cloud agents from git author docs: attribute Cursor cloud agents from git author or the socket Sep 26, 2026
Match the server wrapper at 2566fdcc4: CURSOR_USER_EMAIL, then
ARCJET_PRINCIPAL, then git author, then the Cloud Agent socket, then
$USER / $USERNAME when the value is not ubuntu.

Co-authored-by: David Mytton <[email protected]>
@davidmytton
davidmytton marked this pull request as ready for review September 26, 2026 23:29
@davidmytton
davidmytton added this pull request to the merge queue Sep 26, 2026

@arcjet-review arcjet-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arcjet Review — 🟢 Low Risk

Decision: Approved

Rationale: Documentation-only change to a single .mdx file describing the Cursor hook installation, plus regenerated screenshot baselines. The new shell/PowerShell samples add a documented principal-resolution chain (env vars → git author → Cloud Agent unix socket → OS user, skipping ubuntu) and defensively strip CR/LF to prevent header smuggling. No production code paths, no secrets, no dependency or infra changes. The script sample itself uses mktemp, curl --max-time 1 --unix-socket, and tr -d '\r\n' correctly.

Summary of Changes

Rewrites the Cursor coding-agents doc to expand the X-Arcjet-Principal resolution order: adds GIT_AUTHOR_EMAIL/GIT_AUTHOR_NAME fallback, queries the Cursor Cloud Agent unix socket (turn/user-email then owner/user-email) when set, and skips a bare ubuntu OS account. Windows PowerShell sample and the reference table are updated to match. Screenshot snapshots regenerated.

Review: 20b8304f | Model: anthropic/claude-opus-4-7 | Powered by Arcjet Review

# (where $USER is always ubuntu), then the OS account.
principal=${CURSOR_USER_EMAIL:-${ARCJET_PRINCIPAL:-${USER:-${USERNAME:-}}}}
# Prefer Cursor's signed-in email, then an explicit override, then
# the git author Cursor injects, then the Cloud Agent socket (turn

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor inconsistency: the outer fallbacks use :- (unset or empty) but GIT_AUTHOR_NAME- uses - (unset only). If GIT_AUTHOR_NAME is exported as an empty string, principal becomes empty and the subsequent socket/USER fallbacks still run — which is probably the intent, but worth confirming this asymmetry with GIT_AUTHOR_EMAIL:- is deliberate. If you want consistency, ${GIT_AUTHOR_NAME:-} would treat empty and unset alike.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to ${GIT_AUTHOR_NAME:-} so empty and unset both fall through, same as GIT_AUTHOR_EMAIL.

#965 is in the merge queue, so this landed on #966.

# env value cannot smuggle extra headers.
principal=${CURSOR_USER_EMAIL:-${ARCJET_PRINCIPAL:-${GIT_AUTHOR_EMAIL:-${GIT_AUTHOR_NAME-}}}}
if [ -z "${principal}" ] && [ -n "${CURSOR_AGENT_SOCKET-}" ] \
&& [ -S "${CURSOR_AGENT_SOCKET}" ]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mktemp with no template writes into $TMPDIR (or /tmp) with a predictable prefix. Since the response body may contain the user's email (mildly sensitive) and the file is removed on the happy path but not on set -e/signal interruption, consider trap 'rm -f "${_sock}"' EXIT so a killed hook doesn't leave the email lying around in /tmp.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added trap 'rm -f "${_sock}"' EXIT right after the socket mktemp, so a killed hook removes the email file.

#965 is in the merge queue, so this landed on #966.

_sock=$(mktemp) || _sock=""
if [ -n "${_sock}" ]; then
for _path in /v1/meta-data/turn/user-email \
/v1/meta-data/owner/user-email; do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -sS ... || printf '%s' "000" swallows curl's stderr because of -sS combined with redirect to ${_sock} — wait, -sS still prints errors to stderr, but the %{http_code} capture path means transport errors just yield 000 and the loop silently moves on. That's fine for a hook, but consider documenting (in the surrounding prose) that socket failures are silent by design so operators aren't surprised when a broken socket produces no Actor attribution.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documented in Attribute the developer: transport errors, non-200 responses, and empty bodies are silent, so a broken socket can leave Actor empty.

#965 is in the merge queue, so this landed on #966.

@arcjet-review arcjet-review Bot removed needs review Awaiting human review ai-review-in-progress labels Sep 26, 2026
Merged via the queue into main with commit de69eac Sep 26, 2026
11 checks passed
@davidmytton
davidmytton deleted the david/cursor/cloud-agent-identity-c2f1 branch September 26, 2026 23:39

This branch was successfully deployed

1 active deployment
Preview — 1ae5dd8c Deployed Sep 26, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants