Skip to lesson
Exit
AI & Agent Security Threat Model1 / 4

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

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

beforeShellExecution: register it in hooks.json under "beforeShellExecution": [{ "command": "./hooks/allowlist.js" }] and deploy it via MDM at the Enterprise level so developers can't override it. Hooks fail open on a crash or bad JSON unless the definition sets failClosed: true.ts
#!/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));
});