skills/cookie-auditor/SKILL.md
# Cookie Auditor Skill Audit web pages for GDPR and CCPA cookie consent compliance. ## When to Use - Verifying GDPR compliance before EU launch - Checking CCPA compliance for California users - Pre-deployment privacy compliance checks - Auditing third-party vendors' consent implementation - CI/CD compliance gates ## Audit Approach ### Phase 1: Fresh Session Setup Start with a clean browser state: ```javascript // Via browser_run_code async (page) => { // Clear all cookies await page.c
npx skillsauth add ncklrs/claude-chrome-user-testing skills/cookie-auditorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Audit web pages for GDPR and CCPA cookie consent compliance.
Start with a clean browser state:
// Via browser_run_code
async (page) => {
// Clear all cookies
await page.context().clearCookies();
// Clear local storage
await page.evaluate(() => {
localStorage.clear();
sessionStorage.clear();
});
return 'Session cleared';
}
Before any interaction, record what cookies are set:
async (page) => {
const cookies = await page.context().cookies();
return cookies.map(c => ({
name: c.name,
domain: c.domain,
path: c.path,
expires: c.expires,
httpOnly: c.httpOnly,
secure: c.secure,
sameSite: c.sameSite
}));
}
Classify cookies by purpose:
| Pattern | Category | Essential |
|---------|----------|-----------|
| session, csrf, auth | Necessary | Yes |
| _ga, _gid, analytics | Analytics | No |
| _fbp, _gcl, ads | Marketing | No |
| prefs, theme, lang | Personalization | No |
Look for cookie consent elements:
// Common selectors for cookie banners
const bannerSelectors = [
'[class*="cookie"]',
'[id*="cookie"]',
'[class*="consent"]',
'[id*="consent"]',
'[class*="gdpr"]',
'[class*="privacy-banner"]',
'[aria-label*="cookie"]',
'[role="dialog"][class*="modal"]'
];
Check consent UI for compliance:
Accept Button Detection:
const acceptSelectors = [
'button:has-text("Accept")',
'button:has-text("Allow")',
'button:has-text("Agree")',
'button:has-text("OK")',
'[class*="accept"]'
];
Reject Button Detection:
const rejectSelectors = [
'button:has-text("Reject")',
'button:has-text("Decline")',
'button:has-text("Deny")',
'a:has-text("Reject")',
'[class*="reject"]',
'[class*="decline"]'
];
Preference Detection:
const preferenceSelectors = [
'button:has-text("Settings")',
'button:has-text("Preferences")',
'button:has-text("Manage")',
'button:has-text("Customize")'
];
Load criteria from criteria.json:
| ID | Criterion | Severity | Check Method | |----|-----------|----------|--------------| | GDPR-1 | Banner before cookies | Critical | Pre-consent cookie check | | GDPR-2 | No pre-checked boxes | Critical | Checkbox state analysis | | GDPR-3 | Reject option prominent | Major | Button comparison | | GDPR-4 | Granular consent | Major | Category options check | | GDPR-5 | Withdrawal mechanism | Major | Settings accessibility | | GDPR-6 | Cookie policy link | Minor | Link presence check |
| ID | Criterion | Severity | Check Method | |----|-----------|----------|--------------| | CCPA-1 | Do Not Sell link | Critical | Footer link search | | CCPA-2 | Opt-out mechanism | Critical | Functional test | | CCPA-3 | Privacy policy | Major | Link presence check | | CCPA-4 | Rights disclosure | Minor | Content analysis |
async (page) => {
const checkboxes = await page.$$('input[type="checkbox"]');
const preChecked = [];
for (const checkbox of checkboxes) {
const isChecked = await checkbox.isChecked();
const label = await checkbox.evaluate(el => {
const label = el.closest('label') ||
document.querySelector(`label[for="${el.id}"]`);
return label?.textContent || '';
});
if (isChecked && !isNecessary(label)) {
preChecked.push({ label, checked: true });
}
}
return preChecked;
}
async (page) => {
const accept = await page.$('button:has-text("Accept")');
const reject = await page.$('button:has-text("Reject")');
if (!accept || !reject) return { prominent: false, reason: 'Missing button' };
const acceptBox = await accept.boundingBox();
const rejectBox = await reject.boundingBox();
// Compare sizes
const acceptArea = acceptBox.width * acceptBox.height;
const rejectArea = rejectBox.width * rejectBox.height;
// Reject should be at least 50% the size of accept
return {
prominent: rejectArea >= acceptArea * 0.5,
acceptSize: acceptArea,
rejectSize: rejectArea
};
}
async (page) => {
const ccpaPatterns = [
'Do Not Sell',
'Do Not Share',
'Opt-Out',
'Your Privacy Choices',
'Your California Privacy Rights'
];
for (const pattern of ccpaPatterns) {
const link = await page.$(`a:has-text("${pattern}")`);
if (link) {
return { found: true, text: pattern };
}
}
return { found: false };
}
function calculateScore(results) {
const weights = {
critical: 3,
major: 2,
minor: 1
};
let maxScore = 0;
let actualScore = 0;
for (const result of results) {
const weight = weights[result.severity];
maxScore += weight;
if (result.status === 'pass') {
actualScore += weight;
}
}
const percentage = Math.round((actualScore / maxScore) * 100);
const grade =
percentage >= 90 ? 'A' :
percentage >= 80 ? 'B' :
percentage >= 70 ? 'C' :
percentage >= 60 ? 'D' : 'F';
return { percentage, grade };
}
### FAIL: [ID] - [Title]
- **Severity**: [Critical/Major/Minor]
- **Finding**: [What was observed]
- **Location**: [Where on the page]
- **Fix**: [Remediation guidance]
### PASS: [ID] - [Title]
- **Finding**: [What was observed that indicates compliance]
Pattern: Google Analytics (_ga, _gid) cookies set on page load Detection: Check cookies before any user interaction Fix: Defer analytics until after consent
Pattern: "Marketing cookies" checkbox checked by default Detection: Inspect checkbox state in banner Fix: Default all non-essential to unchecked
Pattern: "Reject" is a small link, "Accept" is a large button Detection: Compare element sizes Fix: Make both options equally prominent
Pattern: No "Do Not Sell" link on California-targeted site Detection: Search footer/privacy areas Fix: Add compliant opt-out link
development
# WCAG Auditor Skill This skill provides WCAG 2.1 accessibility audit capabilities, including criteria definitions, check implementations, and scoring logic. ## Purpose Systematically evaluate web pages against WCAG 2.1 Level A and AA success criteria to identify accessibility barriers and provide remediation guidance. ## WCAG 2.1 Overview WCAG is organized around four principles (POUR): - **Perceivable**: Information must be presentable to users - **Operable**: Interface must be usable - *
development
Comprehensive persona-based user testing skill for web applications. Simulates how real users from different demographics interact with interfaces, including realistic timing, behavioral patterns, and frustration triggers. Use when: - Testing user interfaces before release - Validating UX flows from diverse perspectives - Conducting accessibility reviews - Optimizing onboarding or checkout experiences - Getting feedback on form design
development
# Stripe Checkout Testing Skill This skill provides guidance for testing Stripe checkout flows with any persona. It handles test card data, form detection, and payment-specific narration. ## Purpose Enable realistic user testing of Stripe payment flows using official test cards, with persona-appropriate reactions to checkout experiences. ## Test Card Reference Load card data from `test-cards.json`. Key scenarios: | Scenario | Card | When to Use | |----------|------|-------------| | `succes
testing
# Smoke Testing Skill Run pre-configured smoke tests for common user flows. Quick validation that critical functionality works. ## What is Smoke Testing? Smoke testing is a quick sanity check to ensure basic functionality works before deeper testing. The name comes from electronics - if you turn on a circuit and smoke comes out, you know something is wrong without further testing. ## When to Use - Before releases to catch obvious breaks - After deployments to verify functionality - In CI/CD