2 min lesson
Cursor enterprise controls, mapped to the threat model
Explain the order in "Cursor enterprise controls, mapped to the threat model", then say how you would verify the result.
Step 1 of 4
Everything so far has been principle: assume the injection succeeds, bound the blast radiusHow much breaks if a change goes wrong; the scope of potential damage. Press Enter for the full definition. in code, starve the exit channels. This section names the actual Cursor enterprise controls that implement those principles, so when an interviewer asks "how would you enforce that?" you answer with a real mechanism, not a wish.
Four controls do most of the work: hooks, the model and MCPModel Context Protocol. A standard that lets an AI agent pull in context from outside the repo, like Jira tickets or internal docs. Press Enter for the full definition. allowlist, Sandbox ModeAn agent execution mode in which terminal commands run in a restricted environment that blocks unauthorized file access and network activity, with network limited to the sandbox allowlist; admins enable it org-wide through the Run Mode policy. Press Enter for the full definition. and the network egress allowlist. Each one is a hard control. It lives in the code or the org config around the agent, where an attacker who only controls text can't reach.
Learn more
Full explanation
Enterprise hooks outrank user hooks
Hooks deployed through enterprise MDM take precedence over hooks a user configures locally. Priority runs Enterprise → Team → Project → User, so an org hook outranks anything a developer sets locally. That ordering is the whole point for a security engineer: a developer can't disable or weaken the org's allowlist or audit hook by editing their own config, so the control survives a curious or compromised user. When you propose a hook-based control in an interview, say it's MDM-enforced. That is what makes it a hard control rather than a suggestion.
Learn more
Full explanation
beforeShellExecution
#!/usr/bin/env node // hooks/allowlist.js: Cursor passes the hook input as JSON on stdin and reads JSON from stdout. const { appendFileSync } = require("node:fs"); const ALLOWED = new Set(["npm test", "npm run build", "git status", "git diff"]); const ESCALATE = new Set(["git push", "npm publish"]); let raw = ""; process.stdin.on("data", (chunk) => (raw += chunk)); process.stdin.on("end", () => { const input = JSON.parse(raw); // { command, cwd, sandbox } const command = input.command.trim(); // The logger runs first, so every proposal is recorded whatever the verdict. appendFileSync("hooks/audit.log", JSON.stringify({ event: "shell.proposed", command, cwd: input.cwd }) + "\n"); let out; if (ALLOWED.has(command)) { out = { permission: "allow" }; } else if (ESCALATE.has(command)) { // "ask" is the human gate: the person decides, not the model. out = { permission: "ask", user_message: "Release command. Approve only if you meant it." }; } else { out = { permission: "deny", user_message: "Command not on the allowlist. Open a PR or ask an admin." }; } process.stdout.write(JSON.stringify(out)); });