agentleFS
ncklrsncklrs/claude-chrome-user-testing/skills/cookie-auditor/SKILL.md

cookie-auditor

Skill20 starsChanged 10 months agoMITView on GitHub

Audit web pages for GDPR and CCPA cookie consent compliance. Start with a clean browser state: Before any interaction, record what cookies are set: Classify cookies by purpose: Look for cookie consent elements: Check consent UI for compliance: Accept Button Detection: Reject Button Detection: Preference Detection: Load criteria from criteria.json:

The file

We split this skill into the rules it gives an agent

11 rules. About 0 are common, 11 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈11

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Start with a clean browser state:

    line 17
  2. Distinctive:

    Before any interaction, record what cookies are set:

    line 37
  3. Distinctive:

    Look for cookie consent elements:

    line 67
  4. Distinctive:

    Check consent UI for compliance:

    line 85
  5. Distinctive:

    Detection: Check cookies before any user interaction

    line 272
  6. Distinctive:

    Fix: Default all non-essential to unchecked

    line 279
  7. Distinctive:

    Detection: Search footer/privacy areas

    line 290
  8. Distinctive:

    Fix: Add compliant opt-out link

    line 291
  9. Distinctive:

    Test Fresh Sessions: Always clear cookies before audit

    line 295
  10. Distinctive:

    Deep Pages: Check if consent persists across navigation

    line 298
  11. Distinctive:

    Screenshots: Document violations with annotated screenshots

    line 299

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
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:

// 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';
}

Phase 2: Pre-Consent Cookie Capture

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
  }));
}

Phase 3: Cookie Classification

Classify cookies by purpose:

PatternCategoryEssential
session, csrf, authNecessaryYes
_ga, _gid, analyticsAnalyticsNo
_fbp, _gcl, adsMarketingNo
prefs, theme, langPersonalizationNo

Phase 4: Banner Detection

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"]'
];

Phase 5: Consent Mechanism Analysis

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")'
];

GDPR Criteria Reference

Load criteria from criteria.json:

IDCriterionSeverityCheck Method
GDPR-1Banner before cookiesCriticalPre-consent cookie check
GDPR-2No pre-checked boxesCriticalCheckbox state analysis
GDPR-3Reject option prominentMajorButton comparison
GDPR-4Granular consentMajorCategory options check
GDPR-5Withdrawal mechanismMajorSettings accessibility
GDPR-6Cookie policy linkMinorLink presence check

CCPA Criteria Reference

IDCriterionSeverityCheck Method
CCPA-1Do Not Sell linkCriticalFooter link search
CCPA-2Opt-out mechanismCriticalFunctional test
CCPA-3Privacy policyMajorLink presence check
CCPA-4Rights disclosureMinorContent analysis

Detection Methods

Pre-Checked Box Detection

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;
}

Button Prominence Comparison

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
  };
}

CCPA Link Detection

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 };
}

Scoring

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 };
}

Report Generation

Issue Format

### FAIL: [ID] - [Title]
- **Severity**: [Critical/Major/Minor]
- **Finding**: [What was observed]
- **Location**: [Where on the page]
- **Fix**: [Remediation guidance]

Pass Format

### PASS: [ID] - [Title]
- **Finding**: [What was observed that indicates compliance]

Common Violations

1. Analytics Before Consent

Pattern: Google Analytics (_ga, _gid) cookies set on page load Detection: Check cookies before any user interaction Fix: Defer analytics until after consent

2. Pre-Checked Marketing

Pattern: "Marketing cookies" checkbox checked by default Detection: Inspect checkbox state in banner Fix: Default all non-essential to unchecked

3. Hidden Reject Option

Pattern: "Reject" is a small link, "Accept" is a large button Detection: Compare element sizes Fix: Make both options equally prominent

4. Missing CCPA Link

Pattern: No "Do Not Sell" link on California-targeted site Detection: Search footer/privacy areas Fix: Add compliant opt-out link

Best Practices

  1. Test Fresh Sessions: Always clear cookies before audit
  2. Geo-Simulation: Some banners only show to EU/CA visitors
  3. Mobile Check: Banner behavior may differ on mobile
  4. Deep Pages: Check if consent persists across navigation
  5. Screenshots: Document violations with annotated screenshots

Limitations

  1. Geo-Targeting: Banner may not appear without EU/CA IP
  2. A/B Tests: Different users may see different consent UIs
  3. Dynamic Loading: Some consent tools load asynchronously
  4. Third-Party Tools: Complex consent managers may need special handling
  5. Legal Interpretation: This tool checks technical compliance, not legal advice

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.