Skip to content

Add contrast information data collection and output for contrast failures - #1589

Open
pattonwebz wants to merge 10 commits into
developfrom
william/pro-668-add-contrast-information-to-contrast-issues
Open

Add contrast information data collection and output for contrast failures#1589
pattonwebz wants to merge 10 commits into
developfrom
william/pro-668-add-contrast-information-to-contrast-issues

Conversation

@pattonwebz

@pattonwebz pattonwebz commented Mar 20, 2026

Copy link
Copy Markdown
Member

This pull request adds support for storing and displaying additional color contrast data for accessibility issues, specifically for color contrast failures. The changes span backend data handling, database schema, and frontend display, enabling more detailed color contrast information (such as foreground/background colors and contrast ratios) to be saved, retrieved, and shown in the user interface.

Database and Backend Enhancements:

  • The database schema is updated to add a new extra_data column to the accessibility checker table, and the plugin database version is incremented to 1.0.7 to reflect this change. [1] [2]
  • The backend logic for inserting and updating rule data is extended to accept, store, and sanitize an optional extra_data field (as JSON), ensuring that color contrast details can be saved with each relevant issue. [1] [2] [3] [4] [5] [6]
  • All relevant database queries and API responses are updated to include the extra_data field, and it is properly decoded from JSON when retrieved. [1] [2] [3] [4] [5]

Frontend Display Improvements:

  • The frontend highlighter and issue details modal are updated to display color contrast information (foreground/background color swatches, contrast ratio, and requirements) when available, enhancing the clarity of color contrast issues for users. [1] [2]
  • Corresponding SCSS styles are added for the new color contrast UI elements, ensuring they are visually distinct and accessible.

Scanner and Data Collection:

  • The page scanner is updated to extract and attach detailed color contrast data (foreground/background colors, contrast ratios, font size/weight) to violations of type color_contrast_failure, making this information available throughout the stack. [1] [2]

Fixes: #1562

Checklist

  • PR is linked to the main issue in the repo
  • Tests are added that cover changes

Summary by CodeRabbit

  • New Features

    • Color contrast information now displays visually in accessibility issues, showing foreground and background color swatches alongside actual and expected contrast ratio values. This enhancement appears in both the issue highlighter and the issue details modal for comprehensive analysis.
  • Chores

    • Database schema updated to version 1.0.7 to support additional issue metadata.

Copilot AI review requested due to automatic review settings March 20, 2026 23:30
@coderabbitai

coderabbitai Bot commented Mar 20, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The PR adds support for storing and displaying color contrast metadata alongside accessibility violations. A new extra_data database column is added to persist contrast information (foreground/background colors, contrast ratios), with backend processing to capture and store this data via the REST API and frontend components updated to render contrast swatches and ratio displays.

Changes

Cohort / File(s) Summary
Database Schema & Version
accessibility-checker.php, admin/class-update-database.php
Database version incremented to 1.0.7; new nullable extra_data column added to accessibility_checker table.
Backend Data Processing
admin/class-ajax.php, admin/class-frontend-highlight.php, admin/class-insert-rule-data.php
Insert_Rule_Data::insert() now accepts optional $extra_data parameter; AJAX/frontend handlers select and escape/decode extra_data from database results for frontend consumption.
REST API Integration
includes/classes/class-rest-api.php
set_post_scan_results() and process_rules_for_details() methods updated to capture extraData from incoming violations and pass to insert method; JSON decoding applied when returning rule details.
Frontend Contrast Display
src/frontendHighlighterApp/index.js, src/frontendHighlighterApp/sass/app.scss
Issue descriptions conditionally append color contrast section with foreground/background swatches and contrast ratio when extra_data contains color values; new SCSS rules added for contrast layout/styling.
Modal & Details Views
src/issueModal/components/IssueDetailsModal.js
New "Color Contrast Data" section renders swatches and contrast ratios in issue modals when extra_data includes color values.
Page Scanner Enrichment
src/pageScanner/index.js
processViolation() detects color-contrast violations and enriches result object with extraData containing foreground/background colors, contrast ratios, and font metrics extracted from check data.

Sequence Diagram

sequenceDiagram
    participant PS as PageScanner
    participant REST as REST API
    participant DB as Database
    participant AJAX as AJAX Handler
    participant FE as Frontend UI

    PS->>PS: processViolation()<br/>Detect color_contrast_failure
    PS->>PS: Extract colors & ratios<br/>from check.data
    PS->>REST: POST violation with<br/>extraData (colors, ratios)
    
    REST->>REST: set_post_scan_results()<br/>Capture extraData parameter
    REST->>REST: JSON encode extraData
    REST->>DB: Insert_Rule_Data::insert()<br/>Store extra_data column
    DB-->>REST: Row inserted/updated
    
    FE->>AJAX: Fetch issue details
    AJAX->>DB: SELECT with extra_data
    DB-->>AJAX: Return row + extra_data
    AJAX->>AJAX: esc_attr(extra_data)
    AJAX-->>FE: Issue with data-extra-data
    
    FE->>FE: descriptionOpen()<br/>Check extra_data.fgColor<br/>& extra_data.bgColor
    FE->>FE: Render swatches<br/>& contrast ratio display
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #1053: Modifies the same database schema, Insert_Rule_Data::insert() signature, and REST API processing flow to add different metadata fields (selector, ancestry, xpath) alongside accessibility violations.
  • #1066: Updates Insert_Rule_Data::insert() method, accessibility_checker table schema additions, REST API insertion logic, and page-scanner/highlighter integrations with similar architectural patterns.

Suggested reviewers

  • SteveJonesDev

Poem

🐰 A rabbit's ode to contrast so fine,
Where colors blend and ratios align,
With swatches bright and ratios shown,
Accessibility's depth is now known!
From scanner to modal, the data does flow,
Making accessibility struggles less so! 🎨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and clearly summarizes the main change: adding contrast information data collection and output for contrast failures.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #1562: collecting and storing contrast data (foreground/background colors, contrast ratio), database schema updates, and rendering contrast information across all views (highlighter, modal).
Out of Scope Changes check ✅ Passed All changes directly support contrast data collection and display. Database schema, backend insert/update logic, scanner extraction, REST API handling, and frontend rendering are all aligned with the stated objective.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch william/pro-668-add-contrast-information-to-contrast-issues

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the accessibility checker by adding support for detailed color contrast data. It includes backend changes for data handling and storage, database schema updates, and frontend improvements for displaying the new data, providing users with more comprehensive information about color contrast issues.

Highlights

  • Enhanced Accessibility Data: This PR introduces the collection, storage, and display of detailed color contrast information for accessibility issues.
  • Database Schema Update: The database schema is updated to include an extra_data column in the accessibility checker table.
  • Frontend Improvements: The frontend now displays color contrast details, including foreground/background colors and contrast ratios, in the highlighter and issue details modal.
  • Data Collection: The page scanner now extracts and attaches color contrast data to color_contrast_failure violations.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively adds functionality to collect, store, and display detailed color contrast information for accessibility issues. The changes are well-structured, spanning from the database schema and backend logic to the frontend UI. My review identified one area for improvement regarding data sanitization to ensure the new functionality is robust and secure.

'rule' => sanitize_text_field( $rule_data['rule'] ),
'ruletype' => sanitize_text_field( $rule_data['ruletype'] ),
'object' => esc_attr( $rule_data['object'] ),
'extra_data' => isset( $rule_data['extra_data'] ) ? sanitize_text_field( $rule_data['extra_data'] ) : null,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using sanitize_text_field on a JSON string is not a robust method for sanitization and can lead to data corruption. If the JSON string contains characters like \u003c or \u003e, they will be stripped or encoded, potentially breaking the JSON structure upon parsing. While this may not affect the current data (color codes and numbers), it's a fragile approach.

A more secure and reliable method would be to decode the JSON string, sanitize each value within the resulting array using appropriate functions (e.g., sanitize_hex_color for colors, floatval for numbers), and then re-encode the array to a JSON string. This would prevent data corruption and add a layer of security against potential injection vulnerabilities, especially since this data is used to generate inline styles on the frontend.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end support for capturing, persisting, and displaying additional color contrast failure details (foreground/background colors and contrast ratios) alongside existing accessibility issue records.

Changes:

  • Extend the page scanner to extract contrast check data and attach it to color_contrast_failure violations.
  • Add an extra_data JSON field to issue storage (DB schema + insert/update paths) and decode it when returning issue details.
  • Render contrast swatches/ratio in the Issue Details modal and the frontend highlighter panel when extra_data is available.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/pageScanner/index.js Attaches extraData (contrast details) to contrast-failure violations.
includes/classes/class-rest-api.php Accepts extraData in scan results and decodes extra_data when returning details.
admin/class-insert-rule-data.php Stores optional extra_data JSON for issue records (insert + update).
admin/class-update-database.php Adds extra_data column to the custom issues table schema.
accessibility-checker.php Bumps EDAC_DB_VERSION to trigger schema update.
admin/class-frontend-highlight.php Includes and decodes extra_data in frontend highlighter AJAX issue payloads.
src/frontendHighlighterApp/index.js Displays contrast swatches/ratio in the highlighter panel.
src/frontendHighlighterApp/sass/app.scss Styles for the new highlighter contrast UI.
src/issueModal/components/IssueDetailsModal.js Displays contrast swatches/ratio in the issue details modal.
admin/class-ajax.php Includes extra_data in details queries and outputs it as a data attribute on issue rows.

Comment on lines +780 to +799
// Color contrast data
if ( matchingObj.extra_data?.fgColor && matchingObj.extra_data?.bgColor ) {
const { fgColor, bgColor, contrastRatio, expectedContrastRatio } = matchingObj.extra_data;
content += `
<div class="edac-highlight-panel-description-contrast">
<div class="edac-highlight-panel-description-contrast-swatches">
<div class="edac-highlight-panel-description-contrast-swatch">
<div class="edac-highlight-panel-description-contrast-swatch-color" style="background-color: ${ fgColor }; color: ${ bgColor };">Aa</div>
<div class="edac-highlight-panel-description-contrast-swatch-label">${ __( 'Foreground', 'accessibility-checker' ) }<br>${ fgColor }</div>
</div>
<div class="edac-highlight-panel-description-contrast-swatch">
<div class="edac-highlight-panel-description-contrast-swatch-color" style="background-color: ${ bgColor }; color: ${ fgColor };">Aa</div>
<div class="edac-highlight-panel-description-contrast-swatch-label">${ __( 'Background', 'accessibility-checker' ) }<br>${ bgColor }</div>
</div>
</div>
<div class="edac-highlight-panel-description-contrast-ratio">
${ __( 'Contrast ratio:', 'accessibility-checker' ) } <strong>${ contrastRatio }:1</strong> (${ __( 'required:', 'accessibility-checker' ) } ${ expectedContrastRatio })
</div>
</div>
`;

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fgColor/bgColor/ratios are interpolated into an HTML string (including a style attribute) and then assigned via innerHTML. Because extra_data ultimately comes from scan results sent over the network and stored in the DB, this is an XSS risk if those fields are ever tampered with. Prefer building these nodes with createElement + textContent (and set styles only after validating allowed color formats), or at minimum escape the interpolated values before concatenating HTML.

Copilot uses AI. Check for mistakes.
Comment on lines 67 to 71
'rule' => $rule,
'ruletype' => $ruletype,
'object' => esc_attr( $rule_obj ),
'extra_data' => $extra_data ? wp_json_encode( $extra_data ) : null,
'recordcheck' => 1,

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$extra_data is JSON-encoded and stored with only sanitize_text_field() applied later, which does not validate structure or constrain values. Since this data originates from a client-provided REST payload, please whitelist expected keys and strictly sanitize/cast values (e.g., validate colors against a safe regex, cast ratios/font sizes to float/int) before encoding and persisting.

Copilot uses AI. Check for mistakes.
Comment on lines +539 to +542

$extra_data = isset( $violation['extraData'] ) && is_array( $violation['extraData'] ) ? $violation['extraData'] : null;

( new Insert_Rule_Data() )->insert( $post, $actual_rule_id, $impact, $html, $landmark, $landmark_selector, $selectors, $extra_data );

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When accepting extraData from the REST request, it's only checked for is_array() and then passed through to DB storage. To prevent persisting untrusted/oversized payloads (and to support safe frontend rendering), validate that extraData contains only the expected scalar fields for contrast issues and sanitize/cast each value before calling insert().

Copilot uses AI. Check for mistakes.
Comment on lines +998 to +999
if ( isset( $result['extra_data'] ) && null !== $result['extra_data'] ) {
$result['extra_data'] = json_decode( $result['extra_data'], true );

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

json_decode() is applied to extra_data without checking decode success. If the DB contains an empty string or malformed JSON, this will silently become null, which can make consumers handle extra_data inconsistently. Consider only replacing the value when decoding succeeds (check json_last_error()), and normalize the field to either null or an array consistently.

Suggested change
if ( isset( $result['extra_data'] ) && null !== $result['extra_data'] ) {
$result['extra_data'] = json_decode( $result['extra_data'], true );
if ( isset( $result['extra_data'] ) && '' !== $result['extra_data'] && null !== $result['extra_data'] ) {
$decoded_extra_data = json_decode( $result['extra_data'], true );
if ( JSON_ERROR_NONE === json_last_error() && is_array( $decoded_extra_data ) ) {
$result['extra_data'] = $decoded_extra_data;
} else {
$result['extra_data'] = null;
}
} else {
$result['extra_data'] = null;

Copilot uses AI. Check for mistakes.
Comment on lines +146 to 147
$array['extra_data'] = ! empty( $result['extra_data'] ) ? json_decode( $result['extra_data'], true ) : null;

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra_data is decoded from JSON without checking for decode errors. If the DB contains malformed JSON, this will quietly set extra_data to null and can make frontend behavior inconsistent. Consider verifying json_last_error() (or using a helper) and only returning decoded data when valid.

Suggested change
$array['extra_data'] = ! empty( $result['extra_data'] ) ? json_decode( $result['extra_data'], true ) : null;
if ( ! empty( $result['extra_data'] ) ) {
$decoded_extra_data = json_decode( $result['extra_data'], true );
if ( JSON_ERROR_NONE === json_last_error() ) {
$array['extra_data'] = $decoded_extra_data;
} else {
$array['extra_data'] = null;
}
} else {
$array['extra_data'] = null;
}

Copilot uses AI. Check for mistakes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pageScanner/index.js (1)

385-409: ⚠️ Potential issue | 🟠 Major

Expand extraData to include relevant CSS context, not just computed values.

The extraData object stores computed colors, ratios, and font metrics, but omits the CSS declarations that produced the failing contrast pair. Per the PR requirement for "CSS context," this should also capture the relevant style properties (e.g., color, background-color, etc.) to help identify hover/focus state issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pageScanner/index.js` around lines 385 - 409, When item.id ===
'color_contrast_failure' and check.data exists, expand result.extraData to also
include the CSS context that produced the failing pair: add a property (e.g.,
cssDeclarations or styleContext) to result.extraData that contains the relevant
style properties such as color, background-color, background-image, border,
opacity and any state-specific values (hover/focus) if available; pull these
from check.data (or from the element's computed/style info available on the
violation) so that result.extraData includes both the computed values (fgColor,
bgColor, contrastRatio, etc.) and the originating CSS declarations for easier
debugging (use the existing variables check.data and result.extraData to locate
where to add this).
🧹 Nitpick comments (2)
admin/class-insert-rule-data.php (1)

166-166: Avoid sanitize_text_field() on an encoded JSON payload.

Line 166 sanitizes a pre-encoded JSON string, which can alter structured data. Sanitize fields before wp_json_encode(), then persist the JSON string as-is.

Suggested patch
- 'extra_data'        => isset( $rule_data['extra_data'] ) ? sanitize_text_field( $rule_data['extra_data'] ) : null,
+ 'extra_data'        => ( isset( $rule_data['extra_data'] ) && is_string( $rule_data['extra_data'] ) )
+ 	? $rule_data['extra_data']
+ 	: null,

As per coding guidelines, "Follow WordPress security best practices (sanitization, validation, nonces) in all PHP code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@admin/class-insert-rule-data.php` at line 166, The code is sanitizing an
already-encoded JSON payload (using sanitize_text_field on
$rule_data['extra_data']) which can corrupt structured data; instead sanitize
and validate the individual fields of the array before calling wp_json_encode(),
then store the resulting JSON string unchanged. Update the logic around
$rule_data['extra_data'] in class-insert-rule-data.php (the place where
extra_data is prepared/persisted) to remove sanitize_text_field from the encoded
payload, sanitize each element of the source array (or run wp_kses/esc_* as
appropriate), run wp_json_encode() on the sanitized array, and assign that JSON
string to extra_data for storage.
src/issueModal/components/IssueDetailsModal.js (1)

459-463: Guard ratio rendering when contrast metadata is incomplete.

Line 461 and Line 462 can render undefined values when contrastRatio or expectedContrastRatio is missing. Please gate this block or provide a fallback string.

Suggested patch
-							<p className="edac-analysis__contrast-ratio">
-								{ __( 'Contrast ratio:', 'accessibility-checker' ) }{ ' ' }
-								<strong>{ issue.extra_data.contrastRatio }:1</strong>{ ' ' }
-								({ __( 'required:', 'accessibility-checker' ) } { issue.extra_data.expectedContrastRatio })
-							</p>
+							{ issue?.extra_data?.contrastRatio && issue?.extra_data?.expectedContrastRatio && (
+								<p className="edac-analysis__contrast-ratio">
+									{ __( 'Contrast ratio:', 'accessibility-checker' ) }{ ' ' }
+									<strong>{ issue.extra_data.contrastRatio }:1</strong>{ ' ' }
+									({ __( 'required:', 'accessibility-checker' ) } { issue.extra_data.expectedContrastRatio })
+								</p>
+							) }

As per coding guidelines, "Gracefully handle JavaScript errors to avoid breaking accessibility features".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/issueModal/components/IssueDetailsModal.js` around lines 459 - 463, The
contrast ratio block in IssueDetailsModal is rendering raw values that can be
undefined; update the rendering logic in the IssueDetailsModal component to
first check that issue.extra_data exists and that issue.extra_data.contrastRatio
and issue.extra_data.expectedContrastRatio are present (or substitute safe
fallbacks like 'N/A' or '—'), and only render the <p
className="edac-analysis__contrast-ratio"> block (or its values) when those
values are defined to avoid showing "undefined" or breaking the UI; adjust
checks around issue.extra_data.contrastRatio and
issue.extra_data.expectedContrastRatio accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@includes/classes/class-rest-api.php`:
- Around line 540-542: The $extra_data coming from the REST body must be
validated and normalized before persisting: in class-rest-api.php (before
calling ( new Insert_Rule_Data() )->insert(...)) whitelist allowed keys (e.g.
only accept the known keys used by admin/class-ajax.php and
src/frontendHighlighterApp/index.js), remove any unknown keys, and coerce/escape
each allowed value to a safe scalar (cast to string/int/bool as expected,
strip_tags/esc_html or use wp_kses_allowed_html for limited HTML, and enforce
length limits); if validation fails set $extra_data to null or an empty array;
then pass the sanitized $extra_data into Insert_Rule_Data::insert(). Ensure you
apply WordPress sanitization functions and document the accepted keys in a
comment.

---

Outside diff comments:
In `@src/pageScanner/index.js`:
- Around line 385-409: When item.id === 'color_contrast_failure' and check.data
exists, expand result.extraData to also include the CSS context that produced
the failing pair: add a property (e.g., cssDeclarations or styleContext) to
result.extraData that contains the relevant style properties such as color,
background-color, background-image, border, opacity and any state-specific
values (hover/focus) if available; pull these from check.data (or from the
element's computed/style info available on the violation) so that
result.extraData includes both the computed values (fgColor, bgColor,
contrastRatio, etc.) and the originating CSS declarations for easier debugging
(use the existing variables check.data and result.extraData to locate where to
add this).

---

Nitpick comments:
In `@admin/class-insert-rule-data.php`:
- Line 166: The code is sanitizing an already-encoded JSON payload (using
sanitize_text_field on $rule_data['extra_data']) which can corrupt structured
data; instead sanitize and validate the individual fields of the array before
calling wp_json_encode(), then store the resulting JSON string unchanged. Update
the logic around $rule_data['extra_data'] in class-insert-rule-data.php (the
place where extra_data is prepared/persisted) to remove sanitize_text_field from
the encoded payload, sanitize each element of the source array (or run
wp_kses/esc_* as appropriate), run wp_json_encode() on the sanitized array, and
assign that JSON string to extra_data for storage.

In `@src/issueModal/components/IssueDetailsModal.js`:
- Around line 459-463: The contrast ratio block in IssueDetailsModal is
rendering raw values that can be undefined; update the rendering logic in the
IssueDetailsModal component to first check that issue.extra_data exists and that
issue.extra_data.contrastRatio and issue.extra_data.expectedContrastRatio are
present (or substitute safe fallbacks like 'N/A' or '—'), and only render the <p
className="edac-analysis__contrast-ratio"> block (or its values) when those
values are defined to avoid showing "undefined" or breaking the UI; adjust
checks around issue.extra_data.contrastRatio and
issue.extra_data.expectedContrastRatio accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 35ba74b0-f6fa-40b8-bf42-7153d75f4719

📥 Commits

Reviewing files that changed from the base of the PR and between 7b6ef1f and c081255.

📒 Files selected for processing (10)
  • accessibility-checker.php
  • admin/class-ajax.php
  • admin/class-frontend-highlight.php
  • admin/class-insert-rule-data.php
  • admin/class-update-database.php
  • includes/classes/class-rest-api.php
  • src/frontendHighlighterApp/index.js
  • src/frontendHighlighterApp/sass/app.scss
  • src/issueModal/components/IssueDetailsModal.js
  • src/pageScanner/index.js

Comment on lines +540 to +542
$extra_data = isset( $violation['extraData'] ) && is_array( $violation['extraData'] ) ? $violation['extraData'] : null;

( new Insert_Rule_Data() )->insert( $post, $actual_rule_id, $impact, $html, $landmark, $landmark_selector, $selectors, $extra_data );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Validate and normalize extraData before persisting it.

This field comes straight from the REST body and is later surfaced in the admin/front-end UIs (admin/class-ajax.php and src/frontendHighlighterApp/index.js). Storing arbitrary keys and strings here turns the new contrast metadata into a stored XSS/CSS-injection vector for anyone who can hit edit_post on the scanned post. Please whitelist the expected keys and cast each value to a safe format before calling Insert_Rule_Data::insert(). As per coding guidelines: Follow WordPress security best practices (sanitization, validation, nonces) in all PHP code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@includes/classes/class-rest-api.php` around lines 540 - 542, The $extra_data
coming from the REST body must be validated and normalized before persisting: in
class-rest-api.php (before calling ( new Insert_Rule_Data() )->insert(...))
whitelist allowed keys (e.g. only accept the known keys used by
admin/class-ajax.php and src/frontendHighlighterApp/index.js), remove any
unknown keys, and coerce/escape each allowed value to a safe scalar (cast to
string/int/bool as expected, strip_tags/esc_html or use wp_kses_allowed_html for
limited HTML, and enforce length limits); if validation fails set $extra_data to
null or an empty array; then pass the sanitized $extra_data into
Insert_Rule_Data::insert(). Ensure you apply WordPress sanitization functions
and document the accepted keys in a comment.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Accessibility Checker build (primary only)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add contrast information to contrast issues

2 participants