docs: attribute Cursor cloud agents from git author or the socket - #965
Conversation
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]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: David Mytton <[email protected]>
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]>
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]>
Co-authored-by: David Mytton <[email protected]>
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
| # 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 |
There was a problem hiding this comment.
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.
| _sock=$(mktemp) || _sock="" | ||
| if [ -n "${_sock}" ]; then | ||
| for _path in /v1/meta-data/turn/user-email \ | ||
| /v1/meta-data/owner/user-email; do |
There was a problem hiding this comment.
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.
The Cursor install now matches the server wrapper in https://github.com/arcjet/arcjet/pull/9450 (
2566fdcc4).arcjet-hookassertsX-Arcjet-Principalfrom, in order:CURSOR_USER_EMAIL,ARCJET_PRINCIPAL,GIT_AUTHOR_EMAIL/GIT_AUTHOR_NAME, then the Cloud Agent socket (turn/user-emailthenowner/user-email).$USER/$USERNAMEare used only when the value is notubuntu. The Windows script uses the env fallbacks only.Cloud agent VMs run as
ubuntuand do not setCURSOR_USER_EMAIL. Some also leave the git author unset. The socket is what Activity should show in that case.ARCJET_PRINCIPALremains the explicit override.The hook expander, official event names, and allow-as-
{}answers are unchanged.