To scan Cursor's agent edits as they happen, use Cursor hooks: skylos agent install-hooks --cursor writes .cursor/hooks.json, which checks file reads, shell installs, every edit and the final stop. Cursor reloads the file by itself; no account or API key is needed.
This is the file it writes (--dry-run --skylos-bin skylos output, Skylos 4.47.1):
{
"hooks": {
"beforeSubmitPrompt": [
{
"command": "skylos hook session-start --client cursor || echo '{\"continue\":true}'",
"timeout": 30
}
],
"beforeReadFile": [
{
"command": "skylos hook pre-read --client cursor || echo '{\"permission\":\"allow\"}'",
"timeout": 15
}
],
"beforeShellExecution": [
{
"command": "skylos hook pre-bash --client cursor || echo '{\"permission\":\"allow\"}'",
"timeout": 30
}
],
"afterFileEdit": [
{
"command": "skylos hook post-edit --client cursor || exit 0",
"timeout": 120
}
],
"stop": [
{
"command": "skylos hook stop --client cursor || echo '{}'",
"timeout": 5460,
"loop_limit": 10
}
]
},
"version": 1
}
The installer merges these entries into an existing hooks.json and keeps your other hooks. If Skylos isn't installed or crashes, each hook falls back to an explicit allow, so a broken scanner never blocks Cursor.
What Cursor gets back
We fed each hook the JSON Cursor sends, in a scratch repository where we made the agent's edits by hand.
beforeShellExecution, for pip install skylos-c2-demo-pkg-does-not-exist-4b7e:
{
"permission": "deny",
"user_message": "Skylos blocked this install: 1 package looks hallucinated or typosquatted.\n- PyPI package 'skylos-c2-demo-pkg-does-not-exist-4b7e' does not exist on PyPI (likely hallucinated; an attacker can register it).\nCheck the real package name (docs, registry search) and retry. If the package is internal, install it with your private index/registry flag so Skylos skips the public-registry check. If this package is correct, add it to [tool.skylos] hooks_allow_packages in pyproject.toml.",
"agent_message": "Skylos blocked this install: 1 package looks hallucinated or typosquatted.\n- PyPI package 'skylos-c2-demo-pkg-does-not-exist-4b7e' does not exist on PyPI (likely hallucinated; an attacker can register it).\nCheck the real package name (docs, registry search) and retry. If the package is internal, install it with your private index/registry flag so Skylos skips the public-registry check. If this package is correct, add it to [tool.skylos] hooks_allow_packages in pyproject.toml."
}
For ls -la it answered {"permission": "allow"} without a registry lookup.
beforeReadFile, for a settings file with a GitHub token on line 3:
{
"permission": "deny",
"user_message": "Skylos blocked reading pkg/settings_local.py: it contains 2 likely secret(s) (generic secret; github secret) on line(s) 3. Reading it would send the credential to the model provider. Read only the lines you need with offset/limit that skip those lines, or ask the user to move the secret into the environment or a secret manager."
}
afterFileEdit, after the agent wrote os.system('echo hi ' + name): no output. Cursor gives this event no way to send feedback to the agent, so Skylos records the finding for later.
stop:
{
"followup_message": "Skylos: 1 issue(s) you introduced in this session are still open. Fix them (or explain why they are false positives) before finishing:\n- pkg/tool.py:8 SKY-D203/SKY-D212 Use of os.system() -> Remove the unsafe sink or validate, escape, or parameterize the untrusted input.\nCheck again with: skylos hook recheck pkg/tool.py"
}
On the next stop with nothing changed (loop_count 1), it answered {} and let the agent finish. The installer also sets loop_limit on the stop hook.
Where this sits next to Cursor's own controls
Run modes. In Cursor 3.6 and later the agent runs in Auto-review (the default), Allowlist or Run Everything mode. Auto-review runs allowlisted calls directly, sandboxes shell commands where it can, and sends the rest to a classifier. That decides whether a command may run. It doesn't check what an edit does to your code, and hooks run in every mode.
Bugbot. Bugbot reviews pull requests with AI and reads project rules from .cursor/BUGBOT.md (rules in .cursor/rules/ don't apply to it). By default its check reports findings without failing. Keep it as a reviewer; put the Skylos job in branch protection as the gate.
MCP. Allowlisted tools run without a prompt, so keep sensitive MCP tools off the allowlist.
Before you merge
The hooks only run on machines where someone installed them, and they only judge lines the agent added. On the branch, run:
skylos done --base origin/main # deleted, skipped or weakened tests
skylos . --diff-base origin/main --danger --quality # removed auth, CSRF, rate-limit checks
They answer different questions. skylos done doesn't look at security controls: a branch that only deleted @login_required passed it. The --diff-base scan reported that deletion as SKY-L021 (details).
For commits, a Git pre-commit hook that runs skylos agent pre-commit checks staged files and refused a commit that dropped @login_required in our test. git commit --no-verify skips it, so keep the CI check.
Gate the pull request
skylos cicd init --no-upload
This writes a GitHub Actions workflow with a changed-line scan and, when Skylos finds a pytest project, a "Skylos Done" job. It needs no Skylos account or API key. The generated scan uses --diff, which in 4.47.1 does not report a removed decorator, so also add the removed-controls job. Make the jobs required status checks.
What the Cursor hooks don't do
- No feedback per edit. Findings arrive at stop as a follow-up message.
- No check on
cat .envthrough the shell. OnlybeforeReadFilereads are guarded. - No check on installs from manifests or URLs (
pip install -r,npm ci,git+https://...). - Not a sandbox. Commands, files and network access are Cursor's run mode's job.
- The agent can edit
.cursor/hooks.json.skylos donereports that as SKY-A114 on the branch; the required CI check is out of the agent's reach.
Where to go next
- Claude Code, Codex and Cursor hooks examples for security
- Detect hallucinated packages in AI-generated code
- Verify AI-generated code: check the agent didn't delete or skip tests
- Claude Code security review with hooks
- How to secure an MCP server before you trust it with your code
References
Running this across a team? These checks are free in the CLI. Skylos Cloud keeps the results in one place: the Free plan adds a pass/fail check on pull requests and scan history for one project, and the Workspace plan adds up to 10 projects, approvals for findings you decide not to fix, pull request comments, and audit exports.