Skip to content

CLI-620 beforePromptSubmit hook for Cursor#436

Merged
sophio-japharidze-sonarsource merged 1 commit into
masterfrom
CLI-620_cursor_promptSubmit_hook
Jun 15, 2026
Merged

CLI-620 beforePromptSubmit hook for Cursor#436
sophio-japharidze-sonarsource merged 1 commit into
masterfrom
CLI-620_cursor_promptSubmit_hook

Conversation

@sophio-japharidze-sonarsource

Copy link
Copy Markdown
Contributor

Add a new feature to sonar integrate cursor - scanning prompts for secrets

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Jun 10, 2026

Copy link
Copy Markdown

CLI-620

Comment thread src/cli/commands/integrate/cursor/declaration.ts
Comment thread src/cli/commands/hook/cursor-prompt-submit.ts
@netlify

netlify Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploy Preview for sonarqube-cli canceled.

Name Link
🔨 Latest commit a31f8aa
🔍 Latest deploy log https://app.netlify.com/projects/sonarqube-cli/deploys/6a29756b86e40b00083a3dfc

@netlify

netlify Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploy Preview for sonarqube-cli canceled.

Name Link
🔨 Latest commit 9f18527
🔍 Latest deploy log https://app.netlify.com/projects/sonarqube-cli/deploys/6a2ff8cb46735f000840435b

@sonarqubecloud

sonarqubecloud Bot commented Jun 11, 2026

Copy link
Copy Markdown

Agentic Analysis: Early Results

Agentic Analysis and Context Augmentation are available on your project. Here are some issues that could have been prevented. Follow the links to learn how to put them into action.

1 issue(s) found across 1 file(s):

Rule File Line Message
typescript:S109 tests/integration/specs/hook/hook-cursor-prompt-submit.test.ts 168 No magic number: 0o644.

Analyzed by SonarQube Agentic Analysis in 3.5 s

@sophio-japharidze-sonarsource sophio-japharidze-sonarsource marked this pull request as ready for review June 11, 2026 15:03
@sophio-japharidze-sonarsource sophio-japharidze-sonarsource force-pushed the CLI-620_cursor_promptSubmit_hook branch from 660161d to c245507 Compare June 15, 2026 09:47
Comment thread src/cli/commands/integrate/cursor/hooks.ts Outdated
@vnaskos-sonar vnaskos-sonar force-pushed the CLI-620_cursor_promptSubmit_hook branch from a94341b to 8fe56b5 Compare June 15, 2026 12:10
Comment thread src/cli/commands/integrate/cursor/hooks.ts Outdated
@sophio-japharidze-sonarsource sophio-japharidze-sonarsource force-pushed the CLI-620_cursor_promptSubmit_hook branch from 6f3a9ab to 9f18527 Compare June 15, 2026 13:06
@sonarqubecloud

Copy link
Copy Markdown

@sophio-japharidze-sonarsource sophio-japharidze-sonarsource merged commit 6359649 into master Jun 15, 2026
19 checks passed
@sophio-japharidze-sonarsource sophio-japharidze-sonarsource deleted the CLI-620_cursor_promptSubmit_hook branch June 15, 2026 13:55
@gitar-bot

gitar-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 resolved / 4 findings

Implements the beforePromptSubmit hook for Cursor secret scanning and adds robust validation to prevent crashes from malformed hook entries or non-array event values.

✅ 4 resolved
Edge Case: ownsCursorHookEntry can crash on malformed hooks.json entries

📄 src/cli/commands/integrate/cursor/hooks.ts:55-57 📄 src/cli/commands/integrate/cursor/hooks.ts:73-77 📄 src/cli/commands/integrate/cursor/hooks.ts:92-98
ownsCursorHookEntry calls entry.command.includes(marker) without verifying command is a string (src/cli/commands/integrate/cursor/hooks.ts:55-57). toCursorHooksDocument casts the parsed document straight to CursorHooksDocument and never validates that each event array contains well-formed { command: string } entries. If a user's existing .cursor/hooks.json has an entry where command is missing or non-string (e.g. beforeSubmitPrompt: [{}] or [{ "command": 123 }]), both upsertCursorHook and removeCursorHook will throw a TypeError, aborting sonar integrate cursor. Since these helpers operate on a user-editable file, a defensive guard avoids crashing on hand-edited or third-party-written configs.

Edge Case: Cursor hooks helpers crash if an event value isn't an array

📄 src/cli/commands/integrate/cursor/hooks.ts:76-78 📄 src/cli/commands/integrate/cursor/hooks.ts:96-97
hooks.json is user-editable, and the code already guards individual entries against malformed elements (ownsCursorHookEntry). However, it does not guard against an event value that is not an array. In upsertCursorHook, const existing = settings.hooks[eventType] ?? [] followed by existing.filter(...) will throw existing.filter is not a function if a user hand-edited hooks.json to {"hooks": {"beforeSubmitPrompt": {}}} (object) or "beforeSubmitPrompt": "foo" (string). The same applies in removeCursorHook where entries.filter(...) is called on each value from Object.entries(settings.hooks). Because these run during sonar integrate cursor (patch) and sonar system reset (removePatch), a malformed but valid-JSON hooks file would crash the whole command rather than being tolerated like the malformed-element case the tests cover. Suggest normalizing each event value to an array (treat non-arrays as empty) before filtering.

Quality: cursor command advertises SQAA/CAG it doesn't install

📄 src/cli/commands/integrate/cursor/declaration.ts:64-78
The integrate cursor command description states it "will configure the SonarQube MCP Server, install secrets scanning hooks, and configure SonarQube Agentic Analysis", and it declares a --skip-context option ("Skip the sonar-context-augmentation install/init/skill step"). However, cursorIntegration.features in src/cli/commands/integrate/cursor/declaration.ts only contains the sonar-secrets-prompt-hook and mcp-server features — there is no Context Augmentation (CAG) or SQAA feature (unlike Claude/Codex which call createContextAugmentationFeature). As a result --skip-context is a no-op and the description over-promises.

The test file comment confirms this is intentional staging ("Hook and CAG tests are added in subsequent PRs") and the command is hidden until GA, so impact is low. Consider trimming the description to mention only what is actually configured (MCP server + secrets hook) and dropping/documenting --skip-context until CAG is wired up, to avoid confusing users who run the hidden command.

Bug: Verify Cursor block payload field name user_message

📄 src/cli/commands/hook/cursor-prompt-submit.ts:56-61
cursorPromptSubmit emits { "continue": false, "user_message": "Sonar detected secrets in prompt" } to block a prompt. The integration test only round-trips the CLI's own output (output.user_message), so it does not validate the field name against Cursor's actual hook contract. If Cursor expects camelCase (userMessage) rather than snake_case (user_message), the prompt would still be blocked (continue: false takes effect) but the explanatory message may not be surfaced to the user. Please verify the exact field name against Cursor's hooks schema (https://cursor.com/docs/agent/hooks) and adjust if needed.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

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