@securityreviewai/securityreview-kit 0.1.42 → 0.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -229,4 +229,4 @@ Likely threat families:
229
229
  - Shortlist for exploit chains, not isolated weaknesses.
230
230
  - Logging often matters because poor auditability can turn spoofing, tampering, or privilege abuse into repudiation.
231
231
  - Client-side logic often needs server-side guardrails even if the visible change is in the UI.
232
- - If no existing guardrail covers a realistic recurring threat, create an `ide_generated` guardrail and carry it into `ctm_sync`.
232
+ - If no existing guardrail covers a realistic recurring threat, create an `ide_generated` guardrail and carry it into the final VibeReview markdown sync.
@@ -34,7 +34,7 @@ That skill is mandatory because the IDE must not leave guardrail selection to ch
34
34
  - **Load the broad catalog** — call `get_guardrails` with `project_id`.
35
35
  - **Shortlist intentionally** — choose only the guardrails that mitigate the categories and likely threats for the current task.
36
36
  - **Hydrate the exact shortlist** — call `get_guardrail_by_id` for the shortlisted guardrail ids so implementation uses the exact selected guardrails, not a vague reading of the full catalog.
37
- - **Preserve the shortlist** — keep the selected existing guardrails in context so `ctm_sync` can include the same guardrails later without re-querying.
37
+ - **Preserve the shortlist** — keep the selected existing guardrails in context so the final VibeReview markdown can include the same guardrails later without re-querying.
38
38
 
39
39
  The broad `get_guardrails` result is only the candidate catalog. The active implementation guardrails must come from the shortlisted `get_guardrail_by_id` result.
40
40
 
@@ -63,7 +63,7 @@ Guardrails and PWNISMS are complementary:
63
63
 
64
64
  - Guardrails provide **project-specific, concrete rules** derived from prior threat reviews, compliance requirements, and team decisions.
65
65
  - PWNISMS provides **universal threat-category coverage** to catch gaps that guardrails may not yet cover.
66
- - When PWNISMS analysis reveals a gap not covered by any existing guardrail, **create a new guardrail on the fly** and apply it immediately (marked `source: "ide_generated"` in CTM sync).
66
+ - When PWNISMS analysis reveals a gap not covered by any existing guardrail, **create a new guardrail on the fly** and apply it immediately (marked `source: "ide_generated"` in the VibeReview markdown).
67
67
 
68
68
  ### 4. Report guardrail compliance
69
69
 
@@ -71,7 +71,7 @@ After code generation, include a brief guardrails compliance summary:
71
71
 
72
72
  - List which guardrails were applied (by title), distinguishing existing vs IDE-generated.
73
73
  - Flag any guardrails that could not be fully satisfied and explain why.
74
- - Do not drop shortlisted existing guardrails from session context. `ctm_sync` must receive the same shortlist, including any unsatisfied items with notes.
74
+ - Do not drop shortlisted existing guardrails from session context. The final VibeReview markdown must include the same shortlist, including any unsatisfied items with notes.
75
75
 
76
76
  ---
77
77
 
@@ -79,9 +79,9 @@ After code generation, include a brief guardrails compliance summary:
79
79
 
80
80
  Guardrails are living artifacts. The IDE agent can create, apply, and update them:
81
81
 
82
- - **New guardrail**: When threat modeling or code review reveals a recurring security pattern not yet captured, the IDE agent creates and applies a new guardrail on the fly. These are reported to SRAI via CTM sync with `source: "ide_generated"`.
82
+ - **New guardrail**: When threat modeling or code review reveals a recurring security pattern not yet captured, the IDE agent creates and applies a new guardrail on the fly. These are reported to SRAI in the final VibeReview markdown with `source: "ide_generated"`.
83
83
  - **Edit suggestion**: When an existing guardrail is too broad, too narrow, or outdated, suggest an update to the user.
84
- - All guardrails — existing and IDE-generated — must be preserved in the CTM sync markdown under a single `Guardrails Applied` section that the server can normalize into `guardrails_applied`.
84
+ - All guardrails — existing and IDE-generated — must be preserved in the VibeReview markdown under a single `Guardrails Applied` section that the server can normalize into `guardrails_applied`.
85
85
 
86
86
  ---
87
87
 
@@ -3,7 +3,7 @@
3
3
  "hooks": {
4
4
  "sessionStart": [
5
5
  {
6
- "command": "printf '%s\\n' '{\"additional_context\":\"## MANDATORY SECURITY GATE (Session Policy)\\n\\nFor ANY user request that has security impact (auth, crypto, input handling, secrets, network, data storage, dependencies, new APIs/endpoints, or any code handling untrusted data):\\n\\n**Plan order:**\\n1. **Fetch Vibe Guardrails (first)** - Use .cursor/skills/guardrails-selection/SKILL.md. Analyze the task, call get_guardrails from security-review-mcp to load the broad catalog, shortlist the relevant guardrails, then call get_guardrail_by_id for the shortlist. These exact shortlisted guardrails are the hard constraints on generated code.\\n2. **PWNISMS threat modeling (second)** - Run threat modeling as a guide before writing code. Use .cursor/skills/threat-modelling/SKILL.md. Cross-reference guardrails with PWNISMS findings to identify gaps. Document findings to inform secure implementation.\\n3. **Implement secure code (third)** - Use the threat model findings AND shortlisted guardrails as guides to create secure code. Every must guardrail must be satisfied; no must_not guardrail may be violated.\\n4. **ctm_sync (last)** - Write a structured `.md` sync artifact and push it to SRAI only after implementation is done. Invoke ctm_sync agent (Task tool, subagent_type=ctm_sync) as the final step. Include the exact shortlisted guardrails from earlier plus any IDE-generated guardrails in the markdown; do not query again during ctm_sync. See .cursor/agents/ctm_sync.md and .cursor/rules/ctm_sync_rule.mdc.\\n\\nNo blocking. No deferral. Guardrails enforce secure code; threat modeling guides the design; ctm_sync runs last to sync the markdown artifact to SRAI. Both ctm_sync and guardrail compliance are mandatory and should be part of your to-do.\"}'",
6
+ "command": "printf '%s\\n' '{\"additional_context\":\"## MANDATORY SECURITY GATE (Session Policy)\\n\\nFor ANY user request that has security impact (auth, crypto, input handling, secrets, network, data storage, dependencies, new APIs/endpoints, or any code handling untrusted data):\\n\\n**Plan order:**\\n1. **Fetch Vibe Guardrails (first)** - Use .cursor/skills/guardrails-selection/SKILL.md. Analyze the task, call get_guardrails from security-review-mcp to load the broad catalog, shortlist the relevant guardrails, then call get_guardrail_by_id for the shortlist. These exact shortlisted guardrails are the hard constraints on generated code.\\n2. **PWNISMS threat modeling (second)** - Run threat modeling as a guide before writing code. Use .cursor/skills/threat-modelling/SKILL.md. Cross-reference guardrails with PWNISMS findings to identify gaps. Document findings to inform secure implementation.\\n3. **Implement secure code (third)** - Use the threat model findings AND shortlisted guardrails as guides to create secure code. Every must guardrail must be satisfied; no must_not guardrail may be violated.\\n4. **VibeReview sync (last)** - Read .cursor/skills/vibereview-sync/SKILL.md. The main agent must write a structured `.md` artifact under `vibereview/`, must not read sibling markdown files there just to infer format, must validate that all required metadata and sections are present, and must call `sync_ai_ide_markdown` directly after implementation is done. Include the exact shortlisted guardrails from earlier plus any IDE-generated guardrails in the markdown; do not query guardrails again during sync.\\n\\nNo blocking. No deferral. Guardrails enforce secure code; threat modeling guides the design; the main agent owns the final markdown sync to SRAI. Both sync and guardrail compliance are mandatory and should be part of your to-do.\"}'",
7
7
  "timeout": 5
8
8
  }
9
9
  ]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: PWNISMS Threat Modelling
3
- description: Security-first threat modelling workflow for code and architecture tasks. Walks all 7 PWNISMS categories, enforces vibe guardrails (secure by code), and synchronizes findings via CTM sync. Use before, during, and after implementation.
3
+ description: Security-first threat modelling workflow for code and architecture tasks. Walks all 7 PWNISMS categories, enforces vibe guardrails (secure by code), and synchronizes findings via a direct VibeReview markdown sync. Use before, during, and after implementation.
4
4
  ---
5
5
 
6
6
  # PWNISMS — Security-First Threat Modelling
@@ -21,7 +21,7 @@ Before deep analysis, ensure the project-specific guardrail shortlist exists:
21
21
  1. Use `{{GUARDRAILS_SELECTION_SKILL_DIR}}/SKILL.md`.
22
22
  2. Resolve the project with `find_project_by_name` using `name="<SRAI_PROJECT_NAME>"`.
23
23
  3. Call `get_guardrails`, shortlist intentionally for this task, then hydrate the exact shortlist with `get_guardrail_by_id`.
24
- 4. Keep the shortlisted existing guardrails in context for implementation and `ctm_sync`.
24
+ 4. Keep the shortlisted existing guardrails in context for implementation and the final VibeReview markdown sync.
25
25
 
26
26
  Do not perform project-profile exploration as part of PWNISMS. The old profile tools are not part of this workflow. Ground the threat model in the user request, repository code, diffs, architecture docs the user provides, and the shortlisted guardrails.
27
27
 
@@ -160,7 +160,7 @@ After completing the PWNISMS analysis and before writing code:
160
160
  - `must` rules → mandatory implementation requirements. Every applicable `must` guardrail must be satisfied.
161
161
  - `must_not` rules → hard prohibitions. Code must never violate an applicable `must_not` guardrail.
162
162
  4. **Flag conflicts** — If a guardrail conflicts with the user's explicit instruction, flag it and ask for confirmation.
163
- 5. **Create new guardrails on the fly** — When PWNISMS analysis or code review reveals a recurring security pattern not captured by existing guardrails, create and apply it as a new guardrail (marked `source: "ide_generated"` in CTM sync). Include `title`, `rule_type` (must/must_not), `category`, `instruction`, and rationale in the notes.
163
+ 5. **Create new guardrails on the fly** — When PWNISMS analysis or code review reveals a recurring security pattern not captured by existing guardrails, create and apply it as a new guardrail (marked `source: "ide_generated"` in the VibeReview markdown). Include `title`, `rule_type` (must/must_not), `category`, `instruction`, and rationale in the notes.
164
164
 
165
165
  ---
166
166
 
@@ -197,19 +197,19 @@ When discussing designs before code exists:
197
197
 
198
198
  ---
199
199
 
200
- ## Phase 5 — CTM Sync (Post Threat Modelling)
200
+ ## Phase 5 — VibeReview Sync (Post Threat Modelling)
201
201
 
202
- **MANDATORY:** After every threat modeling step that produces or modifies threat content, synchronize via `ctm_sync`.
202
+ **MANDATORY:** After every threat modeling step that produces or modifies threat content, the main agent must update the `vibereview/*.md` artifact and call `sync_ai_ide_markdown` directly.
203
203
 
204
- ### What triggers CTM sync
204
+ ### What triggers the VibeReview sync
205
205
 
206
206
  - New threat model generated (any form: scenarios, data flows, attack trees, PWNISMS analysis)
207
207
  - Existing threat model updated or extended (new threats, refined mitigations, additional components)
208
208
  - Guardrails applied during a code-generation task (existing or IDE-generated)
209
209
 
210
- ### What CTM sync uploads
210
+ ### What the VibeReview markdown must contain
211
211
 
212
- The `ctm_sync` agent writes a structured `.md` artifact and uploads it through `sync_ai_ide_markdown`. That markdown should contain:
212
+ The main agent writes a structured `.md` artifact under `vibereview/` and uploads it through `sync_ai_ide_markdown`. That markdown should contain:
213
213
 
214
214
  - **Threat model findings**: threats mitigated, PWNISMS categories, severities, mitigations applied
215
215
  - **Best practices achieved**: security patterns followed during implementation
@@ -217,14 +217,25 @@ The `ctm_sync` agent writes a structured `.md` artifact and uploads it through `
217
217
  - **Guardrails applied**: all guardrails enforced during this session — both existing ones shortlisted earlier via `get_guardrails` + `get_guardrail_by_id` (`source: "existing"`) and new ones the IDE agent created on the fly (`source: "ide_generated"`), each with satisfaction status
218
218
  - **Workflow metadata**: `chat_session_id`, `event_name` or `title`, required `summary`, and optional `workflow_name` / `workflow_description`
219
219
 
220
- ### How to invoke
221
-
222
- Use the host's `ctm_sync` agent/workflow with:
223
- - A clear description of what was threat-modeled
224
- - The `chat_session_id` for workflow routing
225
- - Whether this is a new threat model or an update
226
-
227
- See `{{CTM_SYNC_AGENT_PATH}}` for the full workflow and markdown schema.
220
+ ### How to sync
221
+
222
+ 1. Read and follow `{{VIBEREVIEW_SYNC_SKILL_DIR}}/SKILL.md`.
223
+ 2. Write or update a file under `vibereview/`, ideally `vibereview/<chat_session_id>-<slugified-title-or-event-name>.md`.
224
+ 3. Put `chat_session_id`, `summary`, and either `title` or `event_name` in frontmatter.
225
+ 4. Include the required sections:
226
+ - `Best Practices Achieved`
227
+ - `Threats Mitigated`
228
+ - `Secure Code Snippets`
229
+ - `Guardrails Applied`
230
+ - `OWASP Top 10 2025 Mappings`
231
+ 5. Validate that:
232
+ - every threat entry includes `threat_name`, `pwnisms_category`, `severity`, and `mitigation_applied`
233
+ - every guardrail includes `title`, `rule_type`, `source`, and `satisfied`
234
+ - OWASP mappings use exact IDs and names
235
+ - snippets are grounded in actual code, not invented text
236
+ - no sibling `.md` files in `vibereview/` were read just to infer format or content
237
+ 6. Call `sync_ai_ide_markdown` directly with the finished markdown artifact.
238
+ 7. If sync fails, leave the artifact in `vibereview/` and report the failure clearly.
228
239
 
229
240
  ---
230
241
 
@@ -239,6 +250,6 @@ Before finalizing output, confirm:
239
250
  - [ ] Residual risk and follow-up actions are stated.
240
251
  - [ ] Vibe guardrails were fetched and enforced (all applicable `must`/`must_not` rules satisfied).
241
252
  - [ ] Guardrail compliance summary is included in the response (existing + IDE-generated).
242
- - [ ] CTM sync was invoked to upload threat model and guardrail data.
253
+ - [ ] The VibeReview markdown was written under `vibereview/` and `sync_ai_ide_markdown` was called successfully.
243
254
 
244
255
  If ANY box cannot be checked, you MUST flag the gap to the user with a specific remediation recommendation before finalizing the code.
@@ -0,0 +1,358 @@
1
+ ---
2
+ name: vibereview-sync
3
+ description: Write and synchronize a structured VibeReview markdown artifact under vibereview/ for the current security-relevant session. Use after threat modelling or guardrail-enforced implementation.
4
+ ---
5
+
6
+ # VibeReview Markdown Sync
7
+
8
+ Configured SRAI project name: `<SRAI_PROJECT_NAME>`
9
+
10
+ Use this skill whenever threat modelling output exists or security guardrail compliance must be synchronized to SRAI.
11
+
12
+ This skill exists to make the markdown deterministic, grounded, and parseable without depending on a separate subagent. The same agent that performed the work should author the markdown and call `sync_ai_ide_markdown` directly.
13
+
14
+ ## Core Rules
15
+
16
+ 1. Write the artifact under `vibereview/`.
17
+ 2. Author the markdown from the current task context only.
18
+ 3. Do not read other `.md` files in `vibereview/` to infer structure, copy content, or merge state.
19
+ 4. If the current session file path is already known, update that one file directly.
20
+ 5. If the current session file does not exist yet, create a new file using a stable name such as:
21
+
22
+ ```text
23
+ vibereview/<chat_session_id>-<slugified-title-or-event-name>.md
24
+ ```
25
+
26
+ 6. Validate the markdown before calling `sync_ai_ide_markdown`.
27
+ 7. If sync fails, leave the file on disk and report the failure clearly.
28
+
29
+ ## Why You Must Not Read Sibling Files
30
+
31
+ Other markdown files in `vibereview/` may belong to different sessions, different workflows, or partially complete work. Reading them introduces drift and causes downstream extraction failures.
32
+
33
+ Treat each VibeReview artifact as self-contained. The current artifact must be fully authorable from:
34
+
35
+ - the current user request
36
+ - the current session context
37
+ - the threat model produced in this task
38
+ - the exact guardrail shortlist preserved in context
39
+ - the real code snippets touched in this task
40
+
41
+ ## Required Authoring Workflow
42
+
43
+ ### Step 1: Collect the required inputs
44
+
45
+ Before writing the markdown, confirm you have:
46
+
47
+ - a stable `chat_session_id`
48
+ - a concise `summary`
49
+ - either `title` or `event_name`
50
+ - the exact existing guardrails shortlisted earlier
51
+ - any `ide_generated` guardrails created during this task
52
+ - grounded threat entries
53
+ - grounded code snippets from actual files
54
+ - exact OWASP Top 10 2025 mappings when applicable
55
+
56
+ If any required field is missing, resolve it from current context before writing. Do not invent data.
57
+
58
+ ### Step 2: Write YAML frontmatter
59
+
60
+ The frontmatter should use this shape:
61
+
62
+ ```yaml
63
+ ---
64
+ chat_session_id: "cursor-chat-7f3b2f44-8c4d-4d4a-9f1e-2b6a4c91b201"
65
+ workflow_name: "User Auth Hardening"
66
+ workflow_description: "Security improvements for auth flow handling in the current IDE session"
67
+ event_name: "Hardened AI IDE sync ingestion and workflow reuse"
68
+ summary: "This change moved AI IDE sync handling to the server so workflow resolution and event creation happen deterministically after markdown upload. We enforced stable session identity, validated required event fields, and added structured extraction for threats, guardrails, secure code snippets, and OWASP mappings. The endpoint now accepts markdown, returns immediately, and continues processing in the background."
69
+ external_id: "ai-ide-sync-2026-04-21-001"
70
+ ---
71
+ ```
72
+
73
+ ### Frontmatter rules
74
+
75
+ - `chat_session_id` is required.
76
+ - `summary` is required.
77
+ - At least one of `event_name` or `title` is required.
78
+ - `workflow_name` is optional.
79
+ - `workflow_description` is optional.
80
+ - `external_id` is optional.
81
+ - If `workflow_name` is omitted, the server may derive it from the title.
82
+ - Do not rely on `developer_name` or `developer_email` in markdown. The server ignores them when authenticated API identity exists.
83
+
84
+ ## Required Markdown Structure
85
+
86
+ Use this top-level shape:
87
+
88
+ ```md
89
+ # AI IDE Sync Event
90
+
91
+ ## Event Identity
92
+ ...
93
+
94
+ ## Summary
95
+ ...
96
+
97
+ # Threats Mitigated
98
+ ...
99
+
100
+ # Best Practices Achieved
101
+ ...
102
+
103
+ # Secure Code Snippets
104
+ ...
105
+
106
+ # Guardrails Applied
107
+ ...
108
+
109
+ # OWASP Top 10 2025 Mappings
110
+ ...
111
+ ```
112
+
113
+ The exact heading levels may vary slightly, but the section names should stay stable and obvious.
114
+
115
+ ## Event Identity Section
116
+
117
+ Preferred structure:
118
+
119
+ ```md
120
+ ## Event Identity
121
+
122
+ - chat_session_id: `cursor-chat-7f3b2f44-8c4d-4d4a-9f1e-2b6a4c91b201`
123
+ - workflow_name: `User Auth Hardening`
124
+ - event_name: `Hardened AI IDE sync ingestion and workflow reuse`
125
+ - external_id: `ai-ide-sync-2026-04-21-001`
126
+ ```
127
+
128
+ ## Summary Section
129
+
130
+ Repeat the summary in prose under `## Summary`.
131
+
132
+ ## Threats Mitigated Section
133
+
134
+ Each threat entry must include:
135
+
136
+ - `threat_name`
137
+ - `pwnisms_category`
138
+ - `severity`
139
+ - `mitigation_applied`
140
+
141
+ When code exists, include a `### Code Snippet` subsection with:
142
+
143
+ - `file_path`
144
+ - `language`
145
+ - `explanation`
146
+ - a fenced code block containing real code
147
+
148
+ Preferred example:
149
+
150
+ ````md
151
+ # Threats Mitigated
152
+
153
+ ## Threat 1
154
+
155
+ - threat_name: Missing session identity can attach events to the wrong workflow
156
+ - pwnisms_category: IAM
157
+ - severity: High
158
+ - mitigation_applied: The server now requires a stable `chat_session_id` and uses it to resolve or create the workflow before persisting the event.
159
+
160
+ ### Code Snippet
161
+
162
+ - file_path: `app/api/external_ai_ide.py`
163
+ - language: `python`
164
+ - explanation: This prevents ambiguous workflow association and ensures repeated syncs from the same IDE chat session map to the same workflow.
165
+
166
+ ```python
167
+ chat_session_id = str(
168
+ frontmatter.get("chat_session_id")
169
+ or extracted.chat_session_id
170
+ or ""
171
+ ).strip()
172
+
173
+ if not chat_session_id:
174
+ raise ValueError("chat_session_id could not be resolved from markdown content")
175
+ ```
176
+ ````
177
+
178
+ ### Threat authoring rules
179
+
180
+ - Keep each threat clearly separated.
181
+ - Do not collapse multiple threats into one malformed block.
182
+ - Always close fenced code blocks.
183
+ - Never let prose spill into the next threat entry.
184
+ - PWNISMS categories must be one of:
185
+ - `Product`
186
+ - `Workload`
187
+ - `Network`
188
+ - `IAM`
189
+ - `Secrets`
190
+ - `Monitoring`
191
+ - `Supply Chain`
192
+ - Severity should be one of:
193
+ - `Critical`
194
+ - `High`
195
+ - `Medium`
196
+ - `Low`
197
+
198
+ ## Best Practices Achieved Section
199
+
200
+ Use plain bullet items only:
201
+
202
+ ```md
203
+ # Best Practices Achieved
204
+
205
+ - Used a stable chat_session_id to deterministically reuse or create workflows.
206
+ - Kept workflow and event creation on the server instead of relying on IDE-side orchestration.
207
+ - Validated required event identity fields before persisting security review data.
208
+ ```
209
+
210
+ Do not turn this into freeform paragraphs.
211
+
212
+ ## Secure Code Snippets Section
213
+
214
+ Each snippet entry should include:
215
+
216
+ - `file_path`
217
+ - `language`
218
+ - `explanation`
219
+ - a fenced code block with real code
220
+
221
+ Preferred example:
222
+
223
+ ````md
224
+ # Secure Code Snippets
225
+
226
+ ## Snippet 1
227
+
228
+ - file_path: `app/api/external_ai_ide.py`
229
+ - language: `python`
230
+ - explanation: This is security-relevant because it isolates background processing from the request lifecycle and ensures the authenticated developer identity is propagated server-side.
231
+
232
+ ```python
233
+ async def _process_ai_ide_markdown_ingestion(
234
+ *,
235
+ project_id: int,
236
+ ingestion_id: str,
237
+ filename: str,
238
+ markdown_text: str,
239
+ developer_name: str,
240
+ developer_email: str,
241
+ ) -> None:
242
+ logger.info(
243
+ "Starting AI IDE markdown ingestion %s for project %s",
244
+ ingestion_id,
245
+ project_id,
246
+ )
247
+ ```
248
+ ````
249
+
250
+ ### Secure snippet rules
251
+
252
+ - Snippets must be real code, not invented examples.
253
+ - Prefer snippets already cited in threat mitigations when they are strongly relevant.
254
+ - Use fenced code blocks.
255
+ - Keep snippets focused and bounded.
256
+
257
+ ## Guardrails Applied Section
258
+
259
+ Each guardrail entry must include:
260
+
261
+ - `title`
262
+ - `rule_type`
263
+ - `category`
264
+ - `instruction`
265
+ - `source`
266
+ - `satisfied`
267
+ - `notes`
268
+
269
+ Preferred example:
270
+
271
+ ```md
272
+ # Guardrails Applied
273
+
274
+ ## Guardrail 1
275
+
276
+ - title: Require stable AI IDE session identity
277
+ - rule_type: must
278
+ - category: Identity
279
+ - instruction: Every AI IDE sync markdown must include a stable chat_session_id so workflow association is deterministic.
280
+ - source: existing
281
+ - satisfied: true
282
+ - notes: Enforced during markdown ingestion before workflow lookup or workflow creation.
283
+ ```
284
+
285
+ ### Guardrail rules
286
+
287
+ - `rule_type` must be `must` or `must_not`.
288
+ - `source` must be `existing` or `ide_generated`.
289
+ - `satisfied` must be `true` or `false`.
290
+ - Do not drop shortlisted existing guardrails even when unsatisfied.
291
+ - If a guardrail was not fully satisfied, keep it and explain why in `notes`.
292
+
293
+ ## OWASP Top 10 2025 Mappings Section
294
+
295
+ Use exact IDs and names. Preferred structures:
296
+
297
+ ```md
298
+ # OWASP Top 10 2025 Mappings
299
+
300
+ - A07: Authentication Failures
301
+ - A06: Insecure Design
302
+ - A10: Mishandling of Exceptional Conditions
303
+ ```
304
+
305
+ or
306
+
307
+ ```md
308
+ # OWASP Top 10 2025 Mappings
309
+
310
+ - category_id: A07
311
+ category_name: Authentication Failures
312
+ - category_id: A06
313
+ category_name: Insecure Design
314
+ ```
315
+
316
+ Allowed values:
317
+
318
+ - `A01` Broken Access Control
319
+ - `A02` Security Misconfiguration
320
+ - `A03` Software Supply Chain Failures
321
+ - `A04` Cryptographic Failures
322
+ - `A05` Injection
323
+ - `A06` Insecure Design
324
+ - `A07` Authentication Failures
325
+ - `A08` Software or Data Integrity Failures
326
+ - `A09` Security Logging and Alerting Failures
327
+ - `A10` Mishandling of Exceptional Conditions
328
+
329
+ ## Validation Checklist Before Sync
330
+
331
+ Before calling `sync_ai_ide_markdown`, verify all of the following:
332
+
333
+ - The file is under `vibereview/`.
334
+ - You did not read sibling markdown files in `vibereview/`.
335
+ - `chat_session_id` exists in frontmatter.
336
+ - `summary` exists in frontmatter.
337
+ - `event_name` or `title` exists in frontmatter.
338
+ - The `Event Identity` section exists.
339
+ - The `Summary` section exists.
340
+ - The `Threats Mitigated` section exists.
341
+ - The `Best Practices Achieved` section exists.
342
+ - The `Secure Code Snippets` section exists.
343
+ - The `Guardrails Applied` section exists.
344
+ - The `OWASP Top 10 2025 Mappings` section exists.
345
+ - Every threat entry is structurally complete.
346
+ - Every code fence is closed.
347
+ - Every snippet is grounded in real code.
348
+ - Every guardrail entry is structurally complete.
349
+ - OWASP IDs and names are exact.
350
+
351
+ ## Final Step
352
+
353
+ After validation:
354
+
355
+ 1. Save the markdown artifact under `vibereview/`.
356
+ 2. Call `sync_ai_ide_markdown` directly with that file's contents or path, depending on the tool interface exposed by the host.
357
+ 3. If sync succeeds, report success briefly.
358
+ 4. If sync fails, report failure clearly and leave the markdown artifact intact for retry.
@@ -1,12 +1,12 @@
1
- import { existsSync } from 'node:fs';
1
+ import { existsSync, unlinkSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import {
4
- CTM_SYNC_AGENT_REL_PATH,
5
4
  GUARDRAILS_SELECTION_SKILL_REL_DIR,
6
5
  THREAT_MODELLING_SKILL_REL_DIR,
6
+ VIBEREVIEW_SYNC_SKILL_REL_DIR,
7
7
  } from '../../utils/constants.js';
8
8
  import { upsertSentinelBlock, writeText } from '../../utils/fs-helpers.js';
9
- import { getCtmSyncWorkflowContent, getRuleContent, getThreatModellingSkillContent } from './content.js';
9
+ import { getRuleContent, getThreatModellingSkillContent, getVibeReviewSyncSkillContent } from './content.js';
10
10
 
11
11
  function writeGeneratedText(filePath, content) {
12
12
  const action = existsSync(filePath) ? 'updated' : 'created';
@@ -14,6 +14,14 @@ function writeGeneratedText(filePath, content) {
14
14
  return { filePath, action };
15
15
  }
16
16
 
17
+ function removeGeneratedText(filePath) {
18
+ if (existsSync(filePath)) {
19
+ unlinkSync(filePath);
20
+ return { filePath, action: 'deleted' };
21
+ }
22
+ return null;
23
+ }
24
+
17
25
  function getCopilotSessionHookContent() {
18
26
  const additionalContext = [
19
27
  '## MANDATORY SECURITY GATE (Session Policy)',
@@ -23,9 +31,9 @@ function getCopilotSessionHookContent() {
23
31
  '1. Fetch Vibe Guardrails first using .github/skills/guardrails-selection/SKILL.md. Resolve the project, call get_guardrails, shortlist relevant guardrails, then call get_guardrail_by_id for the shortlist.',
24
32
  '2. Run PWNISMS threat modelling using .github/skills/threat-modelling/SKILL.md. Explicitly walk Product, Workload, Network, IAM, Secrets, Monitoring, and Supply Chain.',
25
33
  '3. Implement secure code using both the hydrated guardrails and PWNISMS findings.',
26
- '4. Run the ctm_sync custom agent using .github/agents/ctm_sync.agent.md after threat modelling or guardrail enforcement. Reuse the exact guardrail shortlist; do not re-query guardrails during CTM sync. The agent should write a structured .md sync artifact and upload it with sync_ai_ide_markdown.',
34
+ '4. Read .github/skills/vibereview-sync/SKILL.md. Write a structured .md artifact under vibereview/, do not read sibling markdown files there just to infer format, validate it, and call sync_ai_ide_markdown directly after threat modelling or guardrail enforcement. Reuse the exact guardrail shortlist; do not re-query guardrails during the final sync.',
27
35
  '',
28
- 'Do not use project-profile exploration tools during normal coding tasks. No blocking and no deferral: guardrails first, PWNISMS second, implementation third, ctm_sync last.',
36
+ 'Do not use project-profile exploration tools during normal coding tasks. No blocking and no deferral: guardrails first, PWNISMS second, implementation third, VibeReview sync last.',
29
37
  ].join('\n');
30
38
 
31
39
  const commandPayload = JSON.stringify({
@@ -60,7 +68,7 @@ export function generate(cwd, options = {}) {
60
68
  ...options,
61
69
  guardrailsSelectionSkillDir: GUARDRAILS_SELECTION_SKILL_REL_DIR.vscode,
62
70
  threatModellingSkillDir: THREAT_MODELLING_SKILL_REL_DIR.vscode,
63
- ctmSyncAgentPath: CTM_SYNC_AGENT_REL_PATH.vscode,
71
+ vibereviewSyncSkillDir: VIBEREVIEW_SYNC_SKILL_REL_DIR.vscode,
64
72
  };
65
73
  const filePath = join(cwd, '.github', 'copilot-instructions.md');
66
74
  const content = getRuleContent(optionsWithSkillDirs);
@@ -72,19 +80,22 @@ export function generate(cwd, options = {}) {
72
80
  getThreatModellingSkillContent(optionsWithSkillDirs),
73
81
  );
74
82
 
75
- const ctmSyncAgentPath = join(cwd, CTM_SYNC_AGENT_REL_PATH.vscode);
76
- const ctmSyncAgent = writeGeneratedText(
77
- ctmSyncAgentPath,
78
- getCtmSyncWorkflowContent(optionsWithSkillDirs),
83
+ const vibereviewSyncSkillPath = join(cwd, VIBEREVIEW_SYNC_SKILL_REL_DIR.vscode, 'SKILL.md');
84
+ const vibereviewSyncSkill = writeGeneratedText(
85
+ vibereviewSyncSkillPath,
86
+ getVibeReviewSyncSkillContent(optionsWithSkillDirs),
79
87
  );
80
88
 
89
+ const deletedLegacyAgent = removeGeneratedText(join(cwd, '.github', 'agents', 'ctm_sync.agent.md'));
90
+
81
91
  const hooksPath = join(cwd, '.github', 'hooks', 'srai-session-policy.json');
82
92
  const hooks = writeGeneratedText(hooksPath, getCopilotSessionHookContent());
83
93
 
84
94
  return [
85
95
  { filePath, action, kind: 'rule' },
86
96
  { ...threatSkill, kind: 'skill' },
87
- { ...ctmSyncAgent, kind: 'agent' },
97
+ { ...vibereviewSyncSkill, kind: 'skill' },
88
98
  { ...hooks, kind: 'hooks' },
99
+ ...(deletedLegacyAgent ? [{ ...deletedLegacyAgent, kind: 'cleanup' }] : []),
89
100
  ];
90
101
  }
@@ -5,7 +5,7 @@ import { test } from 'node:test';
5
5
  import assert from 'node:assert/strict';
6
6
  import { generate } from './vscode.js';
7
7
 
8
- test('VS Code Copilot generator writes instructions, skills, agent, and hooks', () => {
8
+ test('VS Code Copilot generator writes instructions, skills, and hooks', () => {
9
9
  const cwd = mkdtempSync(join(tmpdir(), 'securityreview-kit-vscode-'));
10
10
 
11
11
  const results = generate(cwd, { projectName: 'SmokeProject' });
@@ -13,7 +13,7 @@ test('VS Code Copilot generator writes instructions, skills, agent, and hooks',
13
13
  const expectedPaths = [
14
14
  '.github/copilot-instructions.md',
15
15
  '.github/skills/threat-modelling/SKILL.md',
16
- '.github/agents/ctm_sync.agent.md',
16
+ '.github/skills/vibereview-sync/SKILL.md',
17
17
  '.github/hooks/srai-session-policy.json',
18
18
  ];
19
19
 
@@ -21,29 +21,32 @@ test('VS Code Copilot generator writes instructions, skills, agent, and hooks',
21
21
  assert.equal(existsSync(join(cwd, relPath)), true, `${relPath} should exist`);
22
22
  }
23
23
 
24
- assert.deepEqual(results.map((entry) => entry.kind), ['rule', 'skill', 'agent', 'hooks']);
24
+ assert.deepEqual(results.map((entry) => entry.kind), ['rule', 'skill', 'skill', 'hooks']);
25
25
 
26
26
  const instructions = readFileSync(join(cwd, '.github/copilot-instructions.md'), 'utf8');
27
27
  assert.match(instructions, /\.github\/skills\/guardrails-selection\/SKILL\.md/);
28
28
  assert.match(instructions, /\.github\/skills\/threat-modelling\/SKILL\.md/);
29
- assert.match(instructions, /\.github\/agents\/ctm_sync\.agent\.md/);
29
+ assert.match(instructions, /\.github\/skills\/vibereview-sync\/SKILL\.md/);
30
+ assert.match(instructions, /sync_ai_ide_markdown/);
31
+ assert.match(instructions, /vibereview\//);
30
32
  assert.doesNotMatch(instructions, /\.cursor/);
31
33
 
32
34
  const threatSkill = readFileSync(join(cwd, '.github/skills/threat-modelling/SKILL.md'), 'utf8');
33
35
  for (const heading of ['Product', 'Workload', 'Network', 'IAM', 'Secrets', 'Monitoring', 'Supply Chain']) {
34
36
  assert.match(threatSkill, new RegExp(heading));
35
37
  }
36
- assert.match(threatSkill, /\.github\/agents\/ctm_sync\.agent\.md/);
38
+ assert.match(threatSkill, /sync_ai_ide_markdown/);
39
+ assert.match(threatSkill, /vibereview\//);
37
40
  assert.doesNotMatch(threatSkill, /get_project_profile_description/);
38
41
 
39
- const agent = readFileSync(join(cwd, '.github/agents/ctm_sync.agent.md'), 'utf8');
40
- assert.match(agent, /Configured SRAI project name: `SmokeProject`/);
41
- assert.match(agent, /sync_ai_ide_markdown/);
42
- assert.match(agent, /structured markdown artifact/i);
43
- assert.match(agent, /OWASP Top 10 2025 Mappings/);
44
- assert.match(agent, /vibereview\//);
45
- assert.doesNotMatch(agent, /Call `create_ai_ide_event` with/i);
42
+ const vibereviewSkill = readFileSync(join(cwd, '.github/skills/vibereview-sync/SKILL.md'), 'utf8');
43
+ assert.match(vibereviewSkill, /Do not read other/i);
44
+ assert.match(vibereviewSkill, /sync_ai_ide_markdown/);
45
+ assert.match(vibereviewSkill, /Guardrails Applied/);
46
46
 
47
47
  const hooks = JSON.parse(readFileSync(join(cwd, '.github/hooks/srai-session-policy.json'), 'utf8'));
48
48
  assert.equal(hooks.hooks.SessionStart[0].type, 'command');
49
+ assert.match(hooks.hooks.SessionStart[0].command, /vibereview/);
50
+ assert.match(hooks.hooks.SessionStart[0].command, /sync_ai_ide_markdown/);
51
+ assert.match(hooks.hooks.SessionStart[0].command, /vibereview-sync\/SKILL\.md/);
49
52
  });