@securityreviewai/securityreview-kit 0.1.44 → 0.1.46
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.
- package/package.json +1 -1
- package/src/generators/rules/claude.test.js +2 -0
- package/src/generators/rules/codex.test.js +2 -0
- package/src/generators/rules/content.js +1 -1
- package/src/generators/rules/guardrails-init-profile.md +2 -2
- package/src/generators/rules/guardrails-profiler/SKILL.md +7 -29
- package/src/generators/rules/skill.md +4 -3
- package/src/generators/rules/vibereview-sync/SKILL.md +27 -7
- package/src/generators/rules/vscode.test.js +2 -0
- package/src/utils/profiler-agent.js +1 -1
- package/src/utils/profiler-agent.test.js +8 -0
package/package.json
CHANGED
|
@@ -39,6 +39,8 @@ test('Claude generator writes .claude/CLAUDE.md, threat skill, and profiling com
|
|
|
39
39
|
assert.match(vibereviewSkill, /Do not read other/i);
|
|
40
40
|
assert.match(vibereviewSkill, /sync_ai_ide_markdown/);
|
|
41
41
|
assert.match(vibereviewSkill, /Event Identity/);
|
|
42
|
+
assert.match(vibereviewSkill, /Practice 1/);
|
|
43
|
+
assert.match(vibereviewSkill, /practice_name:/);
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
test('Claude generator migrates the kit-managed root CLAUDE.md block into .claude/CLAUDE.md', () => {
|
|
@@ -46,6 +46,8 @@ test('Codex generator writes AGENTS, skills, hooks, and profiling command', () =
|
|
|
46
46
|
assert.match(vibereviewSkill, /sync_ai_ide_markdown/);
|
|
47
47
|
assert.match(vibereviewSkill, /Event Identity/);
|
|
48
48
|
assert.match(vibereviewSkill, /OWASP Top 10 2025 Mappings/);
|
|
49
|
+
assert.match(vibereviewSkill, /Practice 1/);
|
|
50
|
+
assert.match(vibereviewSkill, /practice_name:/);
|
|
49
51
|
|
|
50
52
|
const hooks = JSON.parse(readFileSync(join(cwd, '.codex/hooks.json'), 'utf8'));
|
|
51
53
|
assert.equal(hooks.hooks.SessionStart[0].hooks[0].type, 'command');
|
|
@@ -96,7 +96,7 @@ export function getGuardrailsRuleContent(options = {}) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Guardrails init profile command (repo scan + profile.json + SRAI upload).
|
|
99
|
+
* Guardrails init profile command (repo scan + .guardrails/profile.json + SRAI upload).
|
|
100
100
|
*/
|
|
101
101
|
export function getGuardrailsInitProfileContent(options = {}) {
|
|
102
102
|
return readTemplate('guardrails-init-profile.md', options);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: guardrails-init-profile
|
|
3
|
-
description: Run the Security Review Kit guardrails profiler — scan the repo, write profile.json
|
|
3
|
+
description: Run the Security Review Kit guardrails profiler — scan the repo, write `.guardrails/profile.json`, push the profile and default guardrail pack to SecurityReview.ai via MCP.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Guardrails init profile
|
|
@@ -12,7 +12,7 @@ Configured SRAI project name: `<SRAI_PROJECT_NAME>`
|
|
|
12
12
|
**You must:**
|
|
13
13
|
|
|
14
14
|
1. Read `{{GUARDRAILS_SKILL_DIR}}/SKILL.md` and follow every step (use the signal registry at `{{GUARDRAILS_SKILL_DIR}}/references/signal-registry.json`).
|
|
15
|
-
2. Write `.guardrails/profile.json`
|
|
15
|
+
2. Write `.guardrails/profile.json` as specified.
|
|
16
16
|
3. Call **`update_vibe_profile`** and **`write_default_pack`** on `security-review-mcp` after resolving `project_id` for `<SRAI_PROJECT_NAME>`.
|
|
17
17
|
|
|
18
18
|
Do not skip MCP upload when credentials and MCP are available.
|
|
@@ -5,7 +5,7 @@ description: Profile a codebase to detect its technology stack and generate a gu
|
|
|
5
5
|
|
|
6
6
|
# Guardrails Profiler
|
|
7
7
|
|
|
8
|
-
Profile a codebase's technology stack, write `.guardrails/profile.json`,
|
|
8
|
+
Profile a codebase's technology stack, write `.guardrails/profile.json`, and upload the detected profile and default guardrail pack to SRAI using `update_vibe_profile` and `write_default_pack`.
|
|
9
9
|
|
|
10
10
|
Configured SRAI project name: `<SRAI_PROJECT_NAME>`
|
|
11
11
|
|
|
@@ -14,7 +14,6 @@ Configured SRAI project name: `<SRAI_PROJECT_NAME>`
|
|
|
14
14
|
- **This skill & signal registry (read-only):** `<GUARDRAILS_SKILL_DIR>/` — e.g. `.cursor/skills/guardrails-profiler`, `.github/skills/guardrails-profiler`, `.claude/skills/guardrails-profiler`, or `.codex/skills/guardrails-profiler` for Codex depending on where this file was installed.
|
|
15
15
|
- **Signal registry file:** `<GUARDRAILS_SKILL_DIR>/references/signal-registry.json`
|
|
16
16
|
- **Local guardrails file:** `.guardrails/profile.json`
|
|
17
|
-
- **Combined manifest (project root):** `profile.json` — includes guardrails profile, vibe profile fields for MCP, and default pack payload
|
|
18
17
|
|
|
19
18
|
## When This Runs
|
|
20
19
|
|
|
@@ -102,40 +101,19 @@ Do **not** invent packs or signals; if the repo is empty, use universal baseline
|
|
|
102
101
|
|
|
103
102
|
Create `.guardrails/` if needed and write the profile file.
|
|
104
103
|
|
|
105
|
-
### Step 6:
|
|
106
|
-
|
|
107
|
-
Write **`profile.json`** at the project root with **only** these parts:
|
|
108
|
-
|
|
109
|
-
```json
|
|
110
|
-
{
|
|
111
|
-
"schema_version": "2.0",
|
|
112
|
-
"srai_project_name": "<SRAI_PROJECT_NAME>",
|
|
113
|
-
"guardrails_profile": {},
|
|
114
|
-
"default_guardrail_pack": {
|
|
115
|
-
"guardrail_packs": [],
|
|
116
|
-
"pack_count": 0
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
- Populate **`guardrails_profile`** with the **same object** written to `.guardrails/profile.json` (detection summary, packs, etc.).
|
|
122
|
-
- Populate **`default_guardrail_pack`** with the deduplicated `guardrail_packs` list (same ids as in `guardrails_profile`) and `pack_count`.
|
|
123
|
-
|
|
124
|
-
**Do not** add a separate `vibe_profile` block and do **not** populate narrative fields such as long `description`, `architecture_notes`, `tech_categories`, `user_groups`, `compliance_requirements`, or `language_stacks`. The server-facing “vibe” update is driven **only** from the technical **`guardrails_profile`** plus the default pack (see Step 7).
|
|
125
|
-
|
|
126
|
-
### Step 7: Upload to SecurityReview.ai (security-review-mcp)
|
|
104
|
+
### Step 6: Upload to SecurityReview.ai (security-review-mcp)
|
|
127
105
|
|
|
128
106
|
1. Resolve `project_id`: `find_project_by_name` with `name="<SRAI_PROJECT_NAME>"`. If missing, follow existing kit rules (`list_projects`, `create_project`).
|
|
129
107
|
|
|
130
|
-
2. Call **`update_vibe_profile`** with `project_id` and arguments mapped
|
|
108
|
+
2. Call **`update_vibe_profile`** with `project_id` and arguments mapped directly from the `.guardrails/profile.json` object (and any required `project_id` fields) per the MCP tool’s documented schema. Treat the guardrails detection object as the profile payload — **not** a separate prose vibe document.
|
|
131
109
|
|
|
132
|
-
3. Call **`write_default_pack`** with `project_id` and
|
|
110
|
+
3. Call **`write_default_pack`** with `project_id`, `guardrail_packs`, and `pack_count` derived from `.guardrails/profile.json` (match the MCP tool’s schema).
|
|
133
111
|
|
|
134
112
|
4. **MCP approval:** Do **not** ask the user to “approve MCP” or “say you approve” for `security-review-mcp`. Security Review Kit passes the configured MCP server and approval settings during init-time profiling where the CLI supports it (for example Cursor CLI permissions and Copilot CLI `--additional-mcp-config` / `--allow-all`). Invoke `find_project_by_name`, `update_vibe_profile`, and `write_default_pack` directly. If a call still fails with permissions, report the exact CLI permission error — not a conversational approval step.
|
|
135
113
|
|
|
136
|
-
5. Confirm success:
|
|
114
|
+
5. Confirm success: path written (`.guardrails/profile.json`) and whether both MCP calls succeeded, or the exact error.
|
|
137
115
|
|
|
138
|
-
### Step
|
|
116
|
+
### Step 7: Report
|
|
139
117
|
|
|
140
118
|
Give a concise summary of detected stack, pack count, and upload status.
|
|
141
119
|
|
|
@@ -145,7 +123,7 @@ If there are no signals:
|
|
|
145
123
|
|
|
146
124
|
1. Optionally read `.git/config` for hints.
|
|
147
125
|
2. Emit minimal profile: `owasp-asvs` only, empty summaries where appropriate.
|
|
148
|
-
3. Still write
|
|
126
|
+
3. Still write `.guardrails/profile.json` (minimal baseline profile) and attempt MCP calls.
|
|
149
127
|
|
|
150
128
|
## IDE-Specific Notes
|
|
151
129
|
|
|
@@ -212,7 +212,7 @@ When discussing designs before code exists:
|
|
|
212
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
|
-
- **Best practices achieved**:
|
|
215
|
+
- **Best practices achieved**: structured practice entries with `practice_name`, `description`, and `category`
|
|
216
216
|
- **Secure code snippets**: security-relevant code with explanations
|
|
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`
|
|
@@ -229,11 +229,12 @@ The main agent writes a structured `.md` artifact under `vibereview/` and upload
|
|
|
229
229
|
- `Guardrails Applied`
|
|
230
230
|
- `OWASP Top 10 2025 Mappings`
|
|
231
231
|
5. Validate that:
|
|
232
|
-
|
|
232
|
+
- every threat entry includes `threat_name`, `pwnisms_category`, `severity`, and `mitigation_applied`
|
|
233
|
+
- every best-practice entry includes `practice_name`, `description`, and `category`
|
|
233
234
|
- every guardrail includes `title`, `rule_type`, `source`, and `satisfied`
|
|
234
235
|
- OWASP mappings use exact IDs and names
|
|
235
236
|
- snippets are grounded in actual code, not invented text
|
|
236
|
-
|
|
237
|
+
- no sibling `.md` files in `vibereview/` were read just to infer format or content
|
|
237
238
|
6. Call `sync_ai_ide_markdown` directly with the finished markdown artifact.
|
|
238
239
|
7. If sync fails, leave the artifact in `vibereview/` and report the failure clearly.
|
|
239
240
|
|
|
@@ -197,17 +197,37 @@ if not chat_session_id:
|
|
|
197
197
|
|
|
198
198
|
## Best Practices Achieved Section
|
|
199
199
|
|
|
200
|
-
Use plain bullet
|
|
200
|
+
Use structured practice entries, not plain bullet-only lists.
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
````md
|
|
203
203
|
# Best Practices Achieved
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
|
|
205
|
+
## Practice 1
|
|
206
|
+
- practice_name: Stable workflow correlation
|
|
207
|
+
- description: Used a stable chat session identifier to ensure repeated syncs map to the same workflow.
|
|
208
|
+
- category: identity
|
|
209
|
+
|
|
210
|
+
## Practice 2
|
|
211
|
+
- practice_name: Server-side workflow orchestration
|
|
212
|
+
- description: Kept workflow and event creation on the server instead of relying on IDE-side orchestration.
|
|
213
|
+
- category: design
|
|
214
|
+
|
|
215
|
+
## Practice 3
|
|
216
|
+
- practice_name: Required field validation
|
|
217
|
+
- description: Validated required event identity fields before persisting security review data.
|
|
218
|
+
- category: validation
|
|
219
|
+
````
|
|
220
|
+
|
|
221
|
+
### Best practice rules
|
|
209
222
|
|
|
210
|
-
|
|
223
|
+
- Each entry should be introduced with a stable heading such as `## Practice 1`, `## Practice 2`, and so on.
|
|
224
|
+
- Each entry must include:
|
|
225
|
+
- `practice_name`
|
|
226
|
+
- `description`
|
|
227
|
+
- `category`
|
|
228
|
+
- Keep the values concise and grounded in the actual work completed.
|
|
229
|
+
- Do not turn this section into freeform paragraphs.
|
|
230
|
+
- Do not reduce this section to plain bullet statements without field names.
|
|
211
231
|
|
|
212
232
|
## Secure Code Snippets Section
|
|
213
233
|
|
|
@@ -43,6 +43,8 @@ test('VS Code Copilot generator writes instructions, skills, and hooks', () => {
|
|
|
43
43
|
assert.match(vibereviewSkill, /Do not read other/i);
|
|
44
44
|
assert.match(vibereviewSkill, /sync_ai_ide_markdown/);
|
|
45
45
|
assert.match(vibereviewSkill, /Guardrails Applied/);
|
|
46
|
+
assert.match(vibereviewSkill, /Practice 1/);
|
|
47
|
+
assert.match(vibereviewSkill, /practice_name:/);
|
|
46
48
|
|
|
47
49
|
const hooks = JSON.parse(readFileSync(join(cwd, '.github/hooks/srai-session-policy.json'), 'utf8'));
|
|
48
50
|
assert.equal(hooks.hooks.SessionStart[0].type, 'command');
|
|
@@ -65,7 +65,7 @@ export function buildProfilerAgentPrompt(projectName, agentTarget = 'cursor') {
|
|
|
65
65
|
`SRAI project name: "${p}".`,
|
|
66
66
|
`Open and follow every step in ${skillRoot}/SKILL.md.`,
|
|
67
67
|
`Use ${skillRoot}/references/signal-registry.json as the signal registry.`,
|
|
68
|
-
'Write .guardrails/profile.json
|
|
68
|
+
'Write .guardrails/profile.json as defined in the skill.',
|
|
69
69
|
`Resolve project_id with find_project_by_name for "${p}", then call update_vibe_profile and write_default_pack via security-review-mcp.`,
|
|
70
70
|
'Do not invent stack details, compliance, or user groups; ground everything in the repository.',
|
|
71
71
|
].join('\n');
|
|
@@ -6,6 +6,7 @@ import assert from 'node:assert/strict';
|
|
|
6
6
|
import {
|
|
7
7
|
buildCodexConfigOverrides,
|
|
8
8
|
buildCopilotAdditionalMcpConfig,
|
|
9
|
+
buildProfilerAgentPrompt,
|
|
9
10
|
pickProfilerAgentTarget,
|
|
10
11
|
} from './profiler-agent.js';
|
|
11
12
|
|
|
@@ -71,3 +72,10 @@ test('buildCodexConfigOverrides builds inline MCP config for profiling', () => {
|
|
|
71
72
|
'mcp_servers.security-review-mcp.env.SECURITY_REVIEW_API_TOKEN="token"',
|
|
72
73
|
]);
|
|
73
74
|
});
|
|
75
|
+
|
|
76
|
+
test('buildProfilerAgentPrompt only instructs writing the guardrails profile under .guardrails', () => {
|
|
77
|
+
const prompt = buildProfilerAgentPrompt('demo-project', 'codex');
|
|
78
|
+
|
|
79
|
+
assert.match(prompt, /Write \.guardrails\/profile\.json as defined in the skill\./);
|
|
80
|
+
assert.doesNotMatch(prompt, /profile\.json at the repository root/);
|
|
81
|
+
});
|