feat: add Cyber Essentials Plus (CE+) v3.3 Danzell framework plugin#59
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Reference-depth framework plugin for UK NCSC Cyber Essentials Plus (CE+) v3.3 Danzell, providing the standard command set (scope/evidence/assess) plus a framework expert SKILL to guide assessments using the SCF crosswalk.
Changes:
- Introduces
cyber-essentials-plusframework plugin metadata (plugin.json) and user-facing documentation (README.md). - Adds Reference-depth commands:
/cyber-essentials-plus:scope,/cyber-essentials-plus:evidence-checklist,/cyber-essentials-plus:assess. - Adds CE+ v3.3 Danzell expert SKILL content with scoping, evidence, cadence, and common misinterpretations.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/frameworks/cyber-essentials-plus/.claude-plugin/plugin.json | Declares the plugin and framework metadata (SCF ID, region/country, depth, mapped control counts). |
| plugins/frameworks/cyber-essentials-plus/README.md | Installation + usage docs and framework metadata summary. |
| plugins/frameworks/cyber-essentials-plus/commands/assess.md | Documents the assessment command and its delegation to /grc-engineer:gap-assessment. |
| plugins/frameworks/cyber-essentials-plus/commands/scope.md | Documents scope determination and boundary triggers for CE+. |
| plugins/frameworks/cyber-essentials-plus/commands/evidence-checklist.md | Provides a control-organized evidence checklist for CE+ verification. |
| plugins/frameworks/cyber-essentials-plus/skills/cyber-essentials-plus-expert/SKILL.md | Adds Reference-depth CE+ v3.3 Danzell domain guidance and command routing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…cklist.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
/review |
Code Review by Qodo
1.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Caution Review failedPull request was closed or merged during review Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Cyber Essentials Plus (CE+) v3.3 framework plugin with manifest and marketplace registration, plus documentation: README, command specs (scope/assess/evidence-checklist), and an expert skill doc mapping SCF controls to CE+ controls (Danzell v3.3, effective 27 Apr 2026). Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThis PR adds a Reference-depth CE+ v3.3 Danzell framework plugin with scope, evidence checklist, gap assessment commands, and an expert skill. The
Confidence Score: 4/5Safe to merge after fixing the SCF count contradiction across README.md and evidence-checklist.md. Two P1 findings remain: README.md shows both 26 and 30 SCF controls on the same page, and evidence-checklist.md independently states 30 while plugin.json and assess.md both say 26. These are data-integrity issues in user-facing docs that will cause confusion. The scope.md leaked implementation note is P2. No security or runtime issues; the marketplace entry and command delegation are correct. plugins/frameworks/cyber-essentials-plus/README.md (line 14) and plugins/frameworks/cyber-essentials-plus/commands/evidence-checklist.md (line 7) need the SCF count corrected to 26. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
U([User]) --> S[/cyber-essentials-plus:scope/]
U --> E[/cyber-essentials-plus:evidence-checklist/]
U --> A[/cyber-essentials-plus:assess/]
S --> OUT_S[Applicability verdict\nIn-scope / Out-of-scope / Partial]
E --> OUT_E[Evidence checklist\ngrouped by CE+ control]
A --> GAP[/grc-engineer:gap-assessment\nemea-gbr-ce-2021/]
GAP --> OUT_A[Compliance score\nControl-by-control gaps\nRemediation roadmap]
SKILL[cyber-essentials-plus-expert\nSKILL.md] -.->|informs| S
SKILL -.->|informs| E
SKILL -.->|informs| A
subgraph CE+ Five Controls
C1[Firewalls]
C2[Secure Configuration]
C3[User Access Control\nMFA mandatory v3.3]
C4[Malware Protection]
C5[Patch Management\n14-day critical window]
end
OUT_A --> C1 & C2 & C3 & C4 & C5
Reviews (6): Last reviewed commit: "fix: restore us-finra entry, normalize m..." | Re-trigger Greptile |
Reorganized the marketplace.json file by removing and re-adding the singapore-pdpa plugin with updated formatting.
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude-plugin/marketplace.json:
- Line 203: Update the JSON "description" value that currently reads "Personal
Data Protection Ac (PDPA)" to use the correct spelling "Personal Data Protection
Act (PDPA)"; edit the "description" field in the marketplace.json entry so the
string becomes "...Personal Data Protection Act (PDPA)..." to fix the typo.
In `@plugins/frameworks/cyber-essentials-plus/.claude-plugin/plugin.json`:
- Line 5: Update the plugin.json's author field from a string to an object to
match the other framework plugins: replace the existing "author": "GRC
Engineering Club Contributors" entry with an object-style entry such as
"author": {"name": "GRC Engineering Club Contributors"} so the author format
aligns with the rest of the plugins; edit the author property in plugin.json
accordingly.
In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md`:
- Around line 11-13: The two unlabeled fenced code blocks containing the command
examples "/cyber-essentials-plus:assess [--scope=<scope>]
[--sources=<connector-list>]" and "/grc-engineer:gap-assessment
\"emea-gbr-ce-2021\" [--sources=<connector-list>]" should be updated to specify
a code fence language (e.g., add "text" after the opening backticks) so the
markdown lint rule MD040 is satisfied; locate the two fenced blocks in assess.md
that wrap those exact command lines and change the opening fences from ``` to
```text for each example.
- Around line 33-37: The SCF framework ID "emea-gbr-ce-2021" is not registered
in the public SCF API registry, causing SCF client's _matchFrameworkId() to
return null and expand() to yield empty mappings; register this framework ID in
the SCF API registry (https://grcengclub.github.io/scf-api/) so the SCF client
can resolve it, then verify _matchFrameworkId() returns a non-null Framework
object and expand() produces the expected 30→5 CE+ control mappings for the
/grc-engineer:gap-assessment delegation that uses framework id emea-gbr-ce-2021.
In `@plugins/frameworks/cyber-essentials-plus/commands/evidence-checklist.md`:
- Around line 11-13: The unlabeled fenced code block in the
evidence-checklist.md usage example should be given a language label to satisfy
MD040; update the triple-backtick fence surrounding
"/cyber-essentials-plus:evidence-checklist [--control=<control-name>]" to
include a language identifier such as "text" (i.e., change ``` to ```text) so
the fenced block is labeled and linting passes.
In `@plugins/frameworks/cyber-essentials-plus/commands/scope.md`:
- Around line 11-13: The fenced usage block starting with ``` that contains the
snippet "/cyber-essentials-plus:scope" is missing a language tag (MD040); update
that fence to include a language identifier (e.g., use ```text) so the block
becomes a labeled fenced code block, ensuring the usage example is rendered and
linters accept it; locate the fenced block that contains
"/cyber-essentials-plus:scope" and add "text" after the opening backticks.
In
`@plugins/frameworks/cyber-essentials-plus/skills/cyber-essentials-plus-expert/SKILL.md`:
- Around line 67-72: The current routing wrongly delegates
/cyber-essentials-plus:scope and /cyber-essentials-plus:evidence-checklist to
/grc-engineer:gap-assessment; change the routing so only
/cyber-essentials-plus:assess invokes /grc-engineer:gap-assessment (with SCF id
emea-gbr-ce-2021), and implement/restore independent handlers for
/cyber-essentials-plus:scope and /cyber-essentials-plus:evidence-checklist that
compute certification boundary and enumerate evidence requirements without
relying on the connector findings cache or calling gap-assessment.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: fb24ca5d-c435-4191-b1a7-cebc79e38d89
📒 Files selected for processing (7)
.claude-plugin/marketplace.jsonplugins/frameworks/cyber-essentials-plus/.claude-plugin/plugin.jsonplugins/frameworks/cyber-essentials-plus/README.mdplugins/frameworks/cyber-essentials-plus/commands/assess.mdplugins/frameworks/cyber-essentials-plus/commands/evidence-checklist.mdplugins/frameworks/cyber-essentials-plus/commands/scope.mdplugins/frameworks/cyber-essentials-plus/skills/cyber-essentials-plus-expert/SKILL.md
| { | ||
| "name": "singapore-pdpa", | ||
| "source": "./plugins/frameworks/singapore-pdpa", | ||
| "description": "Singapore — Personal Data Protection Ac (PDPA) (2012) — reference-depth plugin backed by the SCF crosswalk (30 SCF = 14 framework controls).", |
There was a problem hiding this comment.
Fix typo in plugin description.
Line 203 says “Personal Data Protection Ac (PDPA)”; should be “Act”.
✏️ Proposed fix
- "description": "Singapore — Personal Data Protection Ac (PDPA) (2012) — reference-depth plugin backed by the SCF crosswalk (30 SCF = 14 framework controls).",
+ "description": "Singapore — Personal Data Protection Act (PDPA) (2012) — reference-depth plugin backed by the SCF crosswalk (30 SCF = 14 framework controls).",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "description": "Singapore — Personal Data Protection Ac (PDPA) (2012) — reference-depth plugin backed by the SCF crosswalk (30 SCF = 14 framework controls).", | |
| "description": "Singapore — Personal Data Protection Act (PDPA) (2012) — reference-depth plugin backed by the SCF crosswalk (30 SCF = 14 framework controls).", |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude-plugin/marketplace.json at line 203, Update the JSON "description"
value that currently reads "Personal Data Protection Ac (PDPA)" to use the
correct spelling "Personal Data Protection Act (PDPA)"; edit the "description"
field in the marketplace.json entry so the string becomes "...Personal Data
Protection Act (PDPA)..." to fix the typo.
| ``` | ||
| /cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>] | ||
| ``` |
There was a problem hiding this comment.
Specify fenced code block languages for both command examples.
Lines 11 and 32 start unlabeled fences, causing MD040.
🧹 Proposed fix
-```
+```text
/cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>]@@
- +text
/grc-engineer:gap-assessment "emea-gbr-ce-2021" [--sources=]
Also applies to: 32-34
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 11-11: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md` around lines 11
- 13, The two unlabeled fenced code blocks containing the command examples
"/cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>]"
and "/grc-engineer:gap-assessment \"emea-gbr-ce-2021\"
[--sources=<connector-list>]" should be updated to specify a code fence language
(e.g., add "text" after the opening backticks) so the markdown lint rule MD040
is satisfied; locate the two fenced blocks in assess.md that wrap those exact
command lines and change the opening fences from ``` to ```text for each
example.
| /grc-engineer:gap-assessment "emea-gbr-ce-2021" [--sources=<connector-list>] | ||
| ``` | ||
|
|
||
| The SCF crosswalk expands 30 SCF controls into the 5 Cyber Essentials Plus controls. | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Local references to emea-gbr-ce-2021 =="
rg -n --fixed-strings 'emea-gbr-ce-2021' \
plugins/grc-engineer/config/control-crosswalk.yaml \
plugins/grc-engineer/scripts/gap-assessment.js \
plugins/frameworks/cyber-essentials-plus || true
echo
echo "== SCF API framework registry check =="
curl -fsSL https://grcengclub.github.io/scf-api/api/crosswalks.json \
| jq -r '.frameworks[]?.framework_id' \
| rg -n --fixed-strings 'emea-gbr-ce-2021' || trueRepository: GRCEngClub/claude-grc-engineering
Length of output: 799
🏁 Script executed:
# Check if control-crosswalk.yaml contains the mapping
if [ -f "plugins/grc-engineer/config/control-crosswalk.yaml" ]; then
echo "=== control-crosswalk.yaml exists ==="
rg -n --context 3 'emea-gbr-ce-2021' plugins/grc-engineer/config/control-crosswalk.yaml || echo "No matches found"
else
echo "=== control-crosswalk.yaml NOT found, searching for crosswalk files ==="
fd -name '*crosswalk*' plugins/grc-engineer/
fi
echo
echo "=== Checking gap-assessment implementation ==="
if [ -f "plugins/grc-engineer/scripts/gap-assessment.js" ]; then
rg -n 'framework|emea' plugins/grc-engineer/scripts/gap-assessment.js | head -20
else
echo "gap-assessment.js not found, searching..."
fd -name '*gap-assessment*' plugins/grc-engineer/
fiRepository: GRCEngClub/claude-grc-engineering
Length of output: 1565
🏁 Script executed:
# Check how SCF is initialized in gap-assessment.js
echo "=== SCF initialization in gap-assessment.js ==="
rg -n 'scf\s*=|new.*SCF|require.*scf|import.*scf' plugins/grc-engineer/scripts/gap-assessment.js -A 5
echo
echo "=== Search for SCF class/module definition ==="
fd -name '*scf*' -o -name '*SCF*' plugins/grc-engineer/
echo
echo "=== Check for test fixtures or deployment configs with emea-gbr-ce-2021 ==="
fd -name '*.json' -o -name '*.yaml' -o -name '*.yml' plugins/ | xargs rg -l 'emea-gbr-ce-2021' 2>/dev/null || echo "No config files found with this ID"
echo
echo "=== Look for framework resolution/expansion error handling ==="
rg -n 'expand|resolve' plugins/grc-engineer/scripts/gap-assessment.js -A 3 -B 1 | head -40Repository: GRCEngClub/claude-grc-engineering
Length of output: 3475
🏁 Script executed:
echo "=== Finding and reading scf-client.js ==="
find plugins/grc-engineer -name 'scf-client.js' -type f
echo
echo "=== Read scf-client.js (first 100 lines) ==="
head -100 plugins/grc-engineer/scripts/scf-client.js
echo
echo "=== Check for framework registry URL or source ==="
rg -n 'https|http|framework|registry|crosswalk' plugins/grc-engineer/scripts/scf-client.js | head -30Repository: GRCEngClub/claude-grc-engineering
Length of output: 6099
🏁 Script executed:
echo "=== Read more of scf-client.js (lines 100-200) ==="
sed -n '100,200p' plugins/grc-engineer/scripts/scf-client.js
echo
echo "=== Check _matchFrameworkId and expand methods ==="
rg -n '_matchFrameworkId|async expand' plugins/grc-engineer/scripts/scf-client.js -A 15Repository: GRCEngClub/claude-grc-engineering
Length of output: 6786
🏁 Script executed:
rg -n 'cyber|essentials|ce-' plugins/grc-engineer/scripts/scf-client.js -iRepository: GRCEngClub/claude-grc-engineering
Length of output: 139
Register emea-gbr-ce-2021 in the SCF API registry before release.
The command delegates to /grc-engineer:gap-assessment with framework ID emea-gbr-ce-2021, but this ID is missing from the public SCF registry at https://grcengclub.github.io/scf-api/. When the SCF client attempts to resolve this framework, _matchFrameworkId() returns null, causing expand() to silently return empty control mappings. The CE+ assessment will complete without error but produce zero controls, degrading to a no-op evaluation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md` around lines 33
- 37, The SCF framework ID "emea-gbr-ce-2021" is not registered in the public
SCF API registry, causing SCF client's _matchFrameworkId() to return null and
expand() to yield empty mappings; register this framework ID in the SCF API
registry (https://grcengclub.github.io/scf-api/) so the SCF client can resolve
it, then verify _matchFrameworkId() returns a non-null Framework object and
expand() produces the expected 30→5 CE+ control mappings for the
/grc-engineer:gap-assessment delegation that uses framework id emea-gbr-ce-2021.
| ``` | ||
| /cyber-essentials-plus:evidence-checklist [--control=<control-name>] | ||
| ``` |
There was a problem hiding this comment.
Add language to the usage code fence.
Line 11 starts an unlabeled fenced block; label it to satisfy MD040.
🧹 Proposed fix
-```
+```text
/cyber-essentials-plus:evidence-checklist [--control=<control-name>]</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plugins/frameworks/cyber-essentials-plus/commands/evidence-checklist.md`
around lines 11 - 13, The unlabeled fenced code block in the
evidence-checklist.md usage example should be given a language label to satisfy
MD040; update the triple-backtick fence surrounding
"/cyber-essentials-plus:evidence-checklist [--control=<control-name>]" to
include a language identifier such as "text" (i.e., change ``` to ```text) so
the fenced block is labeled and linting passes.
| ``` | ||
| /cyber-essentials-plus:scope | ||
| ``` |
There was a problem hiding this comment.
Add a language tag to the fenced usage block.
Line 11 starts a fence without a language identifier, which triggers MD040.
🧹 Proposed fix
-```
+```text
/cyber-essentials-plus:scope</details>
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>
[warning] 11-11: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against the current code and only fix it if needed.
In @plugins/frameworks/cyber-essentials-plus/commands/scope.md around lines 11 -
13, The fenced usage block starting with that contains the snippet "/cyber-essentials-plus:scope" is missing a language tag (MD040); update that fence to include a language identifier (e.g., usetext) so the block becomes
a labeled fenced code block, ensuring the usage example is rendered and linters
accept it; locate the fenced block that contains "/cyber-essentials-plus:scope"
and add "text" after the opening backticks.
</details>
<!-- fingerprinting:phantom:poseidon:hawk:1c2a97b6-67e6-4feb-9cde-55bbe95ae5f9 -->
<!-- d98c2f50 -->
<!-- This is an auto-generated comment by CodeRabbit -->
| - `/cyber-essentials-plus:scope` — determine applicability and define certification boundary | ||
| - `/cyber-essentials-plus:assess` — run a gap assessment against all five controls | ||
| - `/cyber-essentials-plus:evidence-checklist` — enumerate evidence requirements by control | ||
|
|
||
| All three delegate to `/grc-engineer:gap-assessment` with SCF framework ID `emea-gbr-ce-2021` for the control-by-control mechanics, and wrap the results in CE+-specific terminology. | ||
|
|
There was a problem hiding this comment.
Do not route :scope and :evidence-checklist through gap-assessment.
Line 71 says all three commands delegate to /grc-engineer:gap-assessment. That couples scope/checklist flows to connector findings and can fail when no findings cache exists. Only :assess should delegate.
🛠️ Proposed fix
- `/cyber-essentials-plus:scope` — determine applicability and define certification boundary
-- `/cyber-essentials-plus:assess` — run a gap assessment against all five controls
-- `/cyber-essentials-plus:evidence-checklist` — enumerate evidence requirements by control
-
-All three delegate to `/grc-engineer:gap-assessment` with SCF framework ID `emea-gbr-ce-2021` for the control-by-control mechanics, and wrap the results in CE+-specific terminology.
+- `/cyber-essentials-plus:assess` — run a gap assessment against all five controls (delegates to `/grc-engineer:gap-assessment` with SCF framework ID `emea-gbr-ce-2021`)
+- `/cyber-essentials-plus:evidence-checklist` — enumerate evidence requirements by control
+
+Only `/cyber-essentials-plus:assess` delegates to `/grc-engineer:gap-assessment`; `:scope` and `:evidence-checklist` should run without requiring connector findings.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - `/cyber-essentials-plus:scope` — determine applicability and define certification boundary | |
| - `/cyber-essentials-plus:assess` — run a gap assessment against all five controls | |
| - `/cyber-essentials-plus:evidence-checklist` — enumerate evidence requirements by control | |
| All three delegate to `/grc-engineer:gap-assessment` with SCF framework ID `emea-gbr-ce-2021` for the control-by-control mechanics, and wrap the results in CE+-specific terminology. | |
| - `/cyber-essentials-plus:scope` — determine applicability and define certification boundary | |
| - `/cyber-essentials-plus:assess` — run a gap assessment against all five controls (delegates to `/grc-engineer:gap-assessment` with SCF framework ID `emea-gbr-ce-2021`) | |
| - `/cyber-essentials-plus:evidence-checklist` — enumerate evidence requirements by control | |
| Only `/cyber-essentials-plus:assess` delegates to `/grc-engineer:gap-assessment`; `:scope` and `:evidence-checklist` should run without requiring connector findings. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@plugins/frameworks/cyber-essentials-plus/skills/cyber-essentials-plus-expert/SKILL.md`
around lines 67 - 72, The current routing wrongly delegates
/cyber-essentials-plus:scope and /cyber-essentials-plus:evidence-checklist to
/grc-engineer:gap-assessment; change the routing so only
/cyber-essentials-plus:assess invokes /grc-engineer:gap-assessment (with SCF id
emea-gbr-ce-2021), and implement/restore independent handlers for
/cyber-essentials-plus:scope and /cyber-essentials-plus:evidence-checklist that
compute certification boundary and enumerate evidence requirements without
relying on the connector findings cache or calling gap-assessment.
|
Thanks for the substantive content here, @FunkeOmolere — Danzell v3.3 specifics (MFA-for-cloud, 14-day patch window, 27 Apr 2026 effective date, removal-not-risk-acceptance) are accurately captured and all five CE+ technical controls are covered. Once the items below are addressed this is in good shape to merge. Blockers
Nits (non-blocking)
Dismissals
Once #71 lands, the schema validator will catch (1) automatically going forward. Thanks again — strong content, just needs these fixes to land. |
| "region": "EMEA", | ||
| "country": "GB", | ||
| "depth": "reference", | ||
| "scf_controls_mapped": 26, |
There was a problem hiding this comment.
SCF control count contradicts all documentation
plugin.json declares scf_controls_mapped: 26, but the README, assess.md, evidence-checklist.md, and SKILL.md all state 30 SCF controls map to the 5 CE+ controls. Consumers of the plugin metadata (marketplace display, tooling) will see 26 while the human-readable docs say 30. One of these is the authoritative number and the other needs to be corrected.
| "scf_controls_mapped": 26, | |
| "scf_controls_mapped": 30, |
|
Closing and reopening to trigger new vouch gate workflow. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
plugins/frameworks/cyber-essentials-plus/commands/assess.md (2)
11-13:⚠️ Potential issue | 🟡 MinorAdd language identifiers to both fenced command blocks.
Line 11 and Line 32 still use unlabeled fences, which keeps MD040 failing.
🧹 Proposed fix
-``` +```text /cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>]@@
-+text
/grc-engineer:gap-assessment "emea-gbr-ce-2021" [--sources=]Also applies to: 32-34
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md` around lines 11 - 13, The two fenced code blocks that currently show the commands "/cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>]" and "/grc-engineer:gap-assessment \"emea-gbr-ce-2021\" [--sources=<connector-list>]" need explicit language identifiers to satisfy MD040; update each opening triple-backtick to include "text" (e.g., change ``` to ```text) so both fenced blocks are labeled.
33-37:⚠️ Potential issue | 🟠 MajorUse the canonical SCF framework ID in delegation.
Line 33 still references
emea-gbr-ce-2021; this conflicts with the required canonical ID for this plugin release and risks empty/incorrect crosswalk expansion.🔧 Proposed fix
-/grc-engineer:gap-assessment "emea-gbr-ce-2021" [--sources=<connector-list>] +/grc-engineer:gap-assessment "emea-gbr-cyber-essentials-requirements-3-3" [--sources=<connector-list>]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md` around lines 33 - 37, Update the delegation example that currently uses the framework string "/grc-engineer:gap-assessment \"emea-gbr-ce-2021\" [--sources=<connector-list>]" to reference the canonical SCF framework ID for this plugin release instead of "emea-gbr-ce-2021"; locate the example line in the assess.md content and replace the quoted framework token with the approved canonical SCF ID so the SCF-to-Cyber Essentials Plus crosswalk expands correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md`:
- Around line 12-18: The docs advertise a --scope option for
/cyber-essentials-plus:assess that is never forwarded to or supported by
/grc-engineer:gap-assessment; remove the --scope parameter from the
/cyber-essentials-plus:assess command signature and any descriptive bullets in
assess.md so the documented options match the actual delegation (only
--sources), and add a short note that scope-filtering is not currently supported
and should be requested or implemented later if desired.
---
Duplicate comments:
In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md`:
- Around line 11-13: The two fenced code blocks that currently show the commands
"/cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>]"
and "/grc-engineer:gap-assessment \"emea-gbr-ce-2021\"
[--sources=<connector-list>]" need explicit language identifiers to satisfy
MD040; update each opening triple-backtick to include "text" (e.g., change ```
to ```text) so both fenced blocks are labeled.
- Around line 33-37: Update the delegation example that currently uses the
framework string "/grc-engineer:gap-assessment \"emea-gbr-ce-2021\"
[--sources=<connector-list>]" to reference the canonical SCF framework ID for
this plugin release instead of "emea-gbr-ce-2021"; locate the example line in
the assess.md content and replace the quoted framework token with the approved
canonical SCF ID so the SCF-to-Cyber Essentials Plus crosswalk expands
correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 9376db5b-b440-47aa-b17b-6a70c2a385d6
📒 Files selected for processing (1)
plugins/frameworks/cyber-essentials-plus/commands/assess.md
| /cyber-essentials-plus:assess [--scope=<scope>] [--sources=<connector-list>] | ||
| ``` | ||
|
|
||
| ## Arguments | ||
|
|
||
| - `--scope=<scope>` (optional) — narrow the assessment to one of the five CE+ controls: `firewalls`, `secure-configuration`, `user-access-control`, `malware-protection`, `patch-management`. | ||
| - `--sources=<connector-list>` (optional) — comma-separated connector plugins (e.g. `aws-inspector,github-inspector`). |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Verify gap-assessment supported options in implementation =="
rg -n -C3 --fixed-strings '--scope' plugins/grc-engineer/scripts/gap-assessment.js || true
rg -n -C3 --fixed-strings 'Options:' plugins/grc-engineer/scripts/gap-assessment.js || true
echo
echo "== Verify documented options for /grc-engineer:gap-assessment =="
rg -n -C3 --fixed-strings '--scope' plugins/grc-engineer/commands/gap-assessment.md || true
rg -n -C3 --fixed-strings '--sources' plugins/grc-engineer/commands/gap-assessment.md || true
echo
echo "== Verify CE+ assess command advertises --scope =="
rg -n -C2 --fixed-strings '--scope=<scope>' plugins/frameworks/cyber-essentials-plus/commands/assess.mdRepository: GRCEngClub/claude-grc-engineering
Length of output: 2398
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Check CE+ assess.md for --scope documentation =="
if [ -f "plugins/frameworks/cyber-essentials-plus/commands/assess.md" ]; then
cat -n "plugins/frameworks/cyber-essentials-plus/commands/assess.md" | head -40
fi
echo
echo "== Check if gap-assessment.md exists and what it documents =="
if [ -f "plugins/grc-engineer/commands/gap-assessment.md" ]; then
cat "plugins/grc-engineer/commands/gap-assessment.md"
else
echo "File not found"
fi
echo
echo "== Check gap-assessment.js for --scope support =="
if [ -f "plugins/grc-engineer/scripts/gap-assessment.js" ]; then
cat -n "plugins/grc-engineer/scripts/gap-assessment.js" | head -50
fiRepository: GRCEngClub/claude-grc-engineering
Length of output: 10290
CE+ assess command documents --scope parameter that is not supported by the delegated gap-assessment command.
CE+ assess.md advertises --scope=<scope> in the command signature (line 12) and documents it as narrowing the assessment to one of five CE+ controls (line 17). However, the delegation section (lines 30–34) shows the actual call to /grc-engineer:gap-assessment passes only [--sources=<connector-list>]—--scope is never forwarded. The gap-assessment command itself does not support --scope in its documented options or implementation, so passing this parameter from the user will be silently ignored or cause an error, contradicting the documented behavior.
Decide whether CE+ should:
- Remove
--scopefrom its documented signature and option list, or - Implement scope filtering at the CE+ level before delegating to gap-assessment, or
- Add
--scopesupport to gap-assessment.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plugins/frameworks/cyber-essentials-plus/commands/assess.md` around lines 12
- 18, The docs advertise a --scope option for /cyber-essentials-plus:assess that
is never forwarded to or supported by /grc-engineer:gap-assessment; remove the
--scope parameter from the /cyber-essentials-plus:assess command signature and
any descriptive bullets in assess.md so the documented options match the actual
delegation (only --sources), and add a short note that scope-filtering is not
currently supported and should be requested or implemented later if desired.
Corrected the number of SCF controls from 30 to 26.
|
Hi, quick update from my side: |
|
One more thing:pushing the scf_controls_mapped update triggered the schema validation on my fork, and it's failing on the author field in cyber-essentials-plus/.claude-plugin/plugin.json. Schema wants object form ({"name": "..."}) but my file has it as a string, which I'd left alone based on your earlier note about the Qodo rule. Should I switch to object form to make the schema happy, or leave it? Happy either way. |
|
!vouch trusted contributor |
| "name": "cyber-essentials-plus", | ||
| "description": "UK NCSC Cyber Essentials Plus (CE+) v3.3 Danzell — Reference plugin with evidence checklist, scope determination, and SCF-backed gap assessment. Five core controls: Firewalls, Secure Configuration, User Access Control, Malware Protection, and Patch Management.", | ||
| "version": "0.1.0", | ||
| "author": "GRC Engineering Club Contributors", |
There was a problem hiding this comment.
Schema violation — CI will fail. schemas/plugin.schema.json requires author to be an object with a name field, not a bare string. This manifest will be rejected by the JSON Schema validator (and by claude plugin install at install time). Fix:
"author": {"name": "GRC Engineering Club Contributors"},Compare with plugins/frameworks/singapore-pdpa/.claude-plugin/plugin.json which uses the correct object form.
| "name": "cyber-essentials-plus", | ||
| "source": "./plugins/frameworks/cyber-essentials-plus", | ||
| "description": "UK NCSC Cyber Essentials Plus (CE+) v3.3 Danzell — gap assessments, evidence checklists, remediation plans, and cross-framework mapping to ISO 27001 and NIST CSF", | ||
| "version": "0.1.0" |
There was a problem hiding this comment.
Regression: the us-finra plugin entry has been deleted from the marketplace. It was added recently in PR #67 (commit bb1f7af) and lived between singapore-pdpa and the closing ] on main. The diff removes both singapore-pdpa and us-finra and only re-adds singapore-pdpa + the new cyber-essentials-plus — us-finra is silently dropped.
Please rebase this branch against main and re-add the us-finra entry:
{
"name": "us-finra",
"source": "./plugins/frameworks/us-finra",
"description": "FINRA Broker-Dealer Cybersecurity Guidance — stub-depth plugin backed by the SCF crosswalk (17 SCF → 39 framework controls).",
"version": "0.1.0"
}Otherwise merging this would break installs of us-finra for users who already added the marketplace.
| { | ||
| "name": "singapore-pdpa", | ||
| "source": "./plugins/frameworks/singapore-pdpa", | ||
| "description": "Singapore — Personal Data Protection Ac (PDPA) (2012) — reference-depth plugin backed by the SCF crosswalk (30 SCF = 14 framework controls).", |
There was a problem hiding this comment.
Two unintended changes to the existing singapore-pdpa entry:
- The em-dash separator was changed from ASCII hyphen
Singapore - Personal Data Protection Acto em-dashSingapore — Personal Data Protection Ac— this no longer matches thedisplay_nameinplugins/frameworks/singapore-pdpa/.claude-plugin/plugin.json. - The crosswalk arrow
30 SCF → 14 framework controlswas corrupted to30 SCF = 14 framework controls— semantically wrong (it should read "maps to", not "equals"); 30 SCF controls map to 14 framework controls, not equal to.
Please revert the singapore-pdpa description to the version on main so this PR only adds CE+ and does not regress an unrelated plugin.
| "source": "./plugins/frameworks/us-finra", | ||
| "description": "FINRA Broker-Dealer Cybersecurity Guidance — stub-depth plugin backed by the SCF crosswalk (17 SCF → 39 framework controls).", | ||
| "version": "0.1.0" | ||
| }, |
There was a problem hiding this comment.
Indentation/formatting damage to marketplace.json. This file uses 2-space indentation for the entire array; the new singapore-pdpa and cyber-essentials-plus blocks are pasted at 8-space indentation, and the } closing fedramp-ssp is broken at 3 spaces ( },). There is also a stray blank line of trailing whitespace after irap (line ~163 in the new file). Please reformat to match the surrounding 2-space style — easiest fix is to run the file through python3 -m json.tool (or jq .) and commit the normalized result. Otherwise this will produce noisy diffs against future plugin additions.
|
|
||
| - **Annual recertification**: CE+ lapses exactly 12 months after the certification date. There is no grace period. | ||
| - **Patch window**: Critical and high-severity patches must be applied within **14 days** of release. This is a hard requirement — patches overdue at the time of assessment will cause a failure. | ||
| - **Danzell v3.3 effective date**: 27 April 2026. All assessments submitted on or after this date must use the v3.3 question set. |
There was a problem hiding this comment.
Verify the "Danzell v3.3" question-set name and 27 April 2026 effective date with a primary source before merging. This is a load-bearing factual claim — the SKILL, README, plugin.json, and four commands all assert "Danzell v3.3 effective 27 April 2026" and that it "replaces Willow." IASME has historically named question sets after trees (Beech, Cypress, Evergreen, Montpellier, Willow), so "Danzell" doesn't match the convention and I cannot find it in IASME or NCSC publications dated to my knowledge cutoff.
If "Danzell" is real, please cite it directly in the README References (link to the IASME announcement that names the question set, not just the generic preview page). If it's an invented or rumoured name, this should ship as an unversioned plugin (drop "v3.3 Danzell" from display_name, plugin description, and SKILL) until the real successor is published. Inventing a name would mislead users running /grc-engineer:frameworks and produce confidently wrong assessment output.
…author - marketplace.json: reset to upstream main and re-apply cyber-essentials-plus entry cleanly. Restores the us-finra plugin entry (added in PR GRCEngClub#67) that was lost to a stale base, and removes the indentation drift + singapore-pdpa description corruption. - plugin.json: switch author from bare string to object form per schemas/plugin.schema.json (the description note explicitly says bare strings are rejected by `claude plugin install`). Both manifests now pass tests/validate-plugin-manifests.sh against the ajv schema (35/35 valid). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@FunkeOmolere — pushed the four blocker fixes directly to your fork's
All 35 manifests now pass Once CI is green I'll merge. |
|
Thank you @ethanolivertroy! I appreciate you taking on the four fixes directly. I was working through the contributor flow for the first time and the merge conflict caught me out (didn't realise "Accept current change" would silently drop us-finra), Thanks for handling the cleanup. Learned a lot from this PR. Thank you for the patience and the careful review |
Summary
Adds a Reference-depth framework plugin for UK NCSC Cyber Essentials Plus (CE+) v3.3 Danzell, effective 27 April 2026.
Type of change
What this includes
Key CE+ v3.3 specifics baked in
Summary by CodeRabbit
New Features
Documentation
Chores