Conversation
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
Review Summary by QodoAdd WP-CLI commands, Abilities API integration, and AI agent documentation
WalkthroughsDescription• Added WP-CLI commands for scripted Cookiebot configuration • Implemented WordPress Abilities API with six read/write abilities • Added audit logging for AI-driven configuration changes • Created agent-readable documentation (AGENTS.md, CLAUDE.md) • Updated plugin version to 4.7.0 Diagramflowchart LR
A["WP-CLI Commands"] -->|uses| B["Abilities API"]
C["REST/MCP Clients"] -->|uses| B
B -->|executes| D["Six Abilities"]
D -->|logs to| E["Audit Logger"]
E -->|stores in| F["cookiebot-ai-action-log"]
G["AGENTS.md<br/>CLAUDE.md"] -->|guides| C
File Changes1. src/cli/Cookiebot_CLI_Command.php
|
Code Review by Qodo
1. set-cbid docs show CBID
|
| 'old' => $old_value, | ||
| 'new' => $new_value, |
There was a problem hiding this comment.
Suggestion: Prevent sensitive value persistence by redacting or replacing old/new when the logged ability can carry a Domain Group ID (for example cookiebot/set-cbid) before writing the entry to the option. [custom_rule]
Severity Level: Minor
Why it matters? 🤔
The logger persists the raw $old_value and $new_value directly into the audit option for every ability. If an ability such as cookiebot/set-cbid carries a Domain Group ID or other sensitive identifier, this implementation would store it unredacted in persistent storage, which matches the reported privacy issue.
Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** src/abilities/Ability_Audit_Logger.php
**Line:** 39:40
**Comment:**
*Custom Rule: Prevent sensitive value persistence by redacting or replacing `old`/`new` when the logged ability can carry a Domain Group ID (for example `cookiebot/set-cbid`) before writing the entry to the option.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| ```bash | ||
| wp cookiebot status # show current config | ||
| wp cookiebot verify --format=json # check setup is complete | ||
| wp cookiebot compliance # show covered regulations | ||
| wp cookiebot set-cbid 12345678-1234-1234-1234-123456789abc # set Domain Group ID | ||
| wp cookiebot toggle-gcm --enabled=true # enable Google Consent Mode v2 | ||
| wp cookiebot install-ppg # install Privacy Policy Generator |
There was a problem hiding this comment.
1. set-cbid docs show cbid 📘 Rule violation ⛨ Security
New documentation includes full-form Domain Group ID (CBID) values in examples, which can be copied/pasted into shared outputs and inadvertently expose a user’s identifier. The compliance rule requires masking/redaction anywhere a CBID would appear in persisted or shareable artifacts (including docs).
Agent Prompt
## Issue description
Documentation added in this PR includes full-form CBID/Domain Group ID examples (UUID-looking strings). Compliance requires that CBIDs are treated as sensitive and must not appear in shareable/persisted artifacts; examples should be redacted/masked.
## Issue Context
Even if an example ID is a placeholder, publishing full-form identifiers in docs increases the risk of users pasting real CBIDs into logs, screenshots, tickets, or other externally shared contexts.
## Fix Focus Areas
- README.md[115-121]
- AGENTS.md[49-52]
- CLAUDE.md[49-52]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| $log = get_option( self::OPTION_NAME, array() ); | ||
| if ( ! is_array( $log ) ) { | ||
| $log = array(); | ||
| } | ||
| array_unshift( | ||
| $log, | ||
| array( | ||
| 'ts' => time(), | ||
| 'ability' => $ability_name, | ||
| 'user_id' => get_current_user_id(), | ||
| 'old' => $old_value, | ||
| 'new' => $new_value, | ||
| ) | ||
| ); | ||
| $log = array_slice( $log, 0, self::MAX_ENTRIES ); | ||
| update_option( self::OPTION_NAME, $log, false ); |
There was a problem hiding this comment.
Suggestion: This logger does a non-atomic read-modify-write (get_option → prepend → update_option), so concurrent ability executions can overwrite each other and silently drop audit entries. Use an append-only storage strategy (e.g., dedicated DB table) or implement locking/retry semantics so two simultaneous writes cannot lose one log record. [race condition]
Severity Level: Major ⚠️
- ⚠️ AI ability executions may be missing from audit trail.
- ⚠️ Compliance visibility reduced for concurrent configuration changes.
- ⚠️ Harder to investigate who changed GCM or CBID settings.Steps of Reproduction ✅
1. Activate the Cookiebot CMP plugin so that `Cookiebot_WP::cookiebot_init()` runs; this
method is wired from the constructor in `src/lib/Cookiebot_WP.php` and, via
`cookiebot_init()`, calls `( new Cookiebot_Abilities_Registrar() )->register_hooks();` at
`src/lib/Cookiebot_WP.php:116` (per Grep), which adds the `wp_abilities_api_init` hook to
`Cookiebot_Abilities_Registrar::register()`.
2. When WordPress fires `wp_abilities_api_init`,
`Cookiebot_Abilities_Registrar::register()` in
`src/abilities/Cookiebot_Abilities_Registrar.php:68-79` is executed, which constructs a
shared `Ability_Audit_Logger` and registers the `cookiebot/toggle-gcm` ability (among
others) via `wp_register_ability()`. The toggle ability is implemented in
`src/abilities/Toggle_Gcm_Ability.php`.
3. From two separate clients (e.g. two HTTP requests through the WP Abilities REST
endpoint invoking `cookiebot/toggle-gcm`), trigger the `cookiebot/toggle-gcm` ability
nearly simultaneously. Each request executes the `execute_callback` closure in
`Toggle_Gcm_Ability::get_args()` (`src/abilities/Toggle_Gcm_Ability.php`), which calls
`$logger->log( 'cookiebot/toggle-gcm', $old_value, $enabled );` after updating the
`cookiebot-gcm` option.
4. Both requests enter `Ability_Audit_Logger::log()` in
`src/abilities/Ability_Audit_Logger.php:28-45`. Each one performs `get_option(
self::OPTION_NAME, array() );` (line 29) to read the current log array, prepends its own
entry with `array_unshift()` (lines 33–41), and then calls `update_option(
self::OPTION_NAME, $log, false );` (line 44). Because these read–modify–write sequences
are independent, if both start from the same original log state, whichever
`update_option()` executes last will overwrite the other, and one of the two audit entries
will be missing when you later inspect `get_option( 'cookiebot-ai-action-log' )`.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** src/abilities/Ability_Audit_Logger.php
**Line:** 29:44
**Comment:**
*Race Condition: This logger does a non-atomic read-modify-write (`get_option` → prepend → `update_option`), so concurrent ability executions can overwrite each other and silently drop audit entries. Use an append-only storage strategy (e.g., dedicated DB table) or implement locking/retry semantics so two simultaneous writes cannot lose one log record.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| if ( is_array( $data ) && isset( $data['subscription']['plan'] ) ) { | ||
| $plan = strtolower( $data['subscription']['plan'] ); | ||
| if ( false !== strpos( $plan, 'free' ) ) { | ||
| $plan_type = 'free'; | ||
| } elseif ( false !== strpos( $plan, 'premium' ) || false !== strpos( $plan, 'pro' ) ) { | ||
| $plan_type = 'premium'; | ||
| } |
There was a problem hiding this comment.
Suggestion: The plan detection reads subscription.plan, but the plugin's stored account payload is handled elsewhere as subscriptions.active.price_plan, so real user data will often never match and plan_type will incorrectly stay unknown. Read the same structure used by existing subscription logic (or reuse the existing subscription helper) to avoid returning wrong compliance info. [logic error]
Severity Level: Major ⚠️
- ⚠️ `cookiebot/get-compliance-summary` returns incorrect `plan_type` field.
- ⚠️ `wp cookiebot compliance` misreports free vs premium status.
- ⚠️ AI/REST clients see degraded compliance context accuracy.Steps of Reproduction ✅
1. Connect the site to a Cookiebot/Usercentrics account so `cookiebot-user-data` is
populated with the new schema used elsewhere (see `src/lib/Cookiebot_WP.php:249-59`, where
`get_subscription_type()` reads `$data['subscriptions']['active']['price_plan']` from that
option).
2. Confirm the Cookiebot abilities are registered:
`Cookiebot_Abilities_Registrar::register()` in
`src/abilities/Cookiebot_Abilities_Registrar.php:68-79` instantiates
`Get_Compliance_Summary_Ability` and calls `wp_register_ability( $ability->get_name(),
$ability->get_args() )`.
3. From WP-CLI, run the documented command `wp cookiebot compliance` which maps to
`Cookiebot_CLI_Command::compliance()` in `src/cli/Cookiebot_CLI_Command.php:192-214`; this
calls `$ability = $this->get_ability( 'cookiebot/get-compliance-summary' );` and then
`$result = $ability->execute( null );`.
4. Inside `Get_Compliance_Summary_Ability::get_args()` at
`src/abilities/Get_Compliance_Summary_Ability.php:54-76`, the execute callback decodes
`$user_data` into `$data` and then checks `isset( $data['subscription']['plan'] )` (line
61). Because the real structure is `$data['subscriptions']['active']['price_plan']`, the
condition is false, `$plan_type` remains `'unknown'`, and the returned compliance summary
reports `plan_type = "unknown"` even though a valid subscription plan exists in the stored
payload.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** src/abilities/Get_Compliance_Summary_Ability.php
**Line:** 61:67
**Comment:**
*Logic Error: The plan detection reads `subscription.plan`, but the plugin's stored account payload is handled elsewhere as `subscriptions.active.price_plan`, so real user data will often never match and `plan_type` will incorrectly stay `unknown`. Read the same structure used by existing subscription logic (or reuse the existing subscription helper) to avoid returning wrong compliance info.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| $result = activate_plugin( PPG_Page::PPG_PLUGIN_SLUG ); | ||
| if ( is_wp_error( $result ) ) { | ||
| return new \WP_Error( 'cookiebot_ppg_install_failed', $result->get_error_message() ); |
There was a problem hiding this comment.
Suggestion: The permission gate allows users with install_plugins but not necessarily activate_plugins, yet the flow always calls activate_plugin, which can then fail at runtime for users that were authorized by this callback. Include activate_plugins in permission checks (or split install vs activate paths) to keep authorization consistent with performed actions. [logic error]
Severity Level: Major ⚠️
- ⚠️ `cookiebot/install-ppg` can fail for partially-privileged users.
- ⚠️ `wp cookiebot install-ppg` may error after passing permissions.
- ⚠️ Inconsistent capability checks complicate role design and auditing.Steps of Reproduction ✅
1. Create or configure a WordPress role/user that has `manage_options` and
`install_plugins` capabilities but deliberately lacks `activate_plugins` (a realistic
custom role configuration in multisite or hardened setups).
2. Ensure Cookiebot abilities are registered via
`Cookiebot_Abilities_Registrar::register()` in
`src/abilities/Cookiebot_Abilities_Registrar.php:68-79`, which includes `new
Install_Ppg_Ability( $logger )` and registers it under the name `cookiebot/install-ppg`.
3. Execute the ability as that user, for example via WP-CLI: `wp cookiebot install-ppg
--user=<role_user>`, which calls `Cookiebot_CLI_Command::install_ppg()` in
`src/cli/Cookiebot_CLI_Command.php:319-334`; this resolves the ability and calls `$result
= $ability->execute( null );`.
4. Inside `Install_Ppg_Ability::get_args()` execute callback at
`src/abilities/Install_Ppg_Ability.php:54-119`, the configured `permission_callback` only
checks `current_user_can( 'manage_options' ) && current_user_can( 'install_plugins' )`, so
it permits execution; when the branch for an installed-but-inactive PPG runs, it executes
`$result = activate_plugin( PPG_Page::PPG_PLUGIN_SLUG );` (line 72), which internally
enforces `activate_plugins` and returns a `WP_Error` for this user; the ability then wraps
this in a `WP_Error( 'cookiebot_ppg_install_failed', ...)`, and the CLI command surfaces a
runtime error even though the permission gate allowed the operation.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** src/abilities/Install_Ppg_Ability.php
**Line:** 72:74
**Comment:**
*Logic Error: The permission gate allows users with `install_plugins` but not necessarily `activate_plugins`, yet the flow always calls `activate_plugin`, which can then fail at runtime for users that were authorized by this callback. Include `activate_plugins` in permission checks (or split install vs activate paths) to keep authorization consistent with performed actions.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix|
CodeAnt AI finished reviewing your PR. |
Resolves anonymous function spacing (`function ()` not `function()`), expands inline arrays to multi-line, replaces `dirname(__FILE__)` with `__DIR__`, removes leading backslashes from `use function` imports, fixes indentation in view templates, and converts heredocs to nowdocs in tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ertions Skip tests gracefully when `wp_has_ability`/`wp_get_ability` are absent, replace `json_encode` with `wp_json_encode`, tighten audit log assertions to check placeholder strings, and add phpcs ignore for multi-class test file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
CodeAnt AI is running Incremental review Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
|
|
CodeAnt AI Incremental review completed. |



User description
New Features
wp cookiebot status,wp cookiebot verify,wp cookiebot compliance,wp cookiebot set-cbid,wp cookiebot toggle-gcm, andwp cookiebot install-ppgcookiebot/get-status,cookiebot/verify-setup,cookiebot/get-compliance-summary,cookiebot/set-cbid,cookiebot/toggle-gcm, andcookiebot/install-ppgcookiebot-ai-action-log(capped at 50 entries, includes timestamp, ability name, user, old and new values)Improvements
AGENTS.mdandCLAUDE.mdto the plugin root with agent-readable setup guidance, compliance coverage map, post-install verification checklist, and recommendation criteria for AI assistantsCodeAnt-AI Description
Add command-line and AI-friendly tools for managing Cookiebot setup
What Changed
Impact
✅ Faster Cookiebot setup from the command line✅ Quicker setup checks for site admins✅ Clearer record of AI-made configuration changes🔄 Retrigger CodeAnt AI Review
Details
💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.