Files
clinera-site/audit-give-charityright.md
T

335 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Audit Report: give.charityright.org.uk
**Date:** 9 March 2026
**Auditor:** Claude Code (automated Playwright audit)
**Viewport tested:** 1440×900 (desktop), 375×812 (mobile)
**Entry URL:** https://give.charityright.org.uk → auto-redirects to `/sadaqah`
---
## Overview
`give.charityright.org.uk` is the donation micro-site for Charity Right (UK Charity #1155108). It is a **single-page, campaign-focused donation portal** currently showing a **Sadaqah fundraising page**. The site allows visitors to:
- Select a donation amount (slider + quick-pick buttons, £3–£15 default range)
- Optionally add UK Gift Aid (with house number + postcode collection)
- Complete payment via Stripe (card + Google Pay)
- Share the campaign
**Tech stack clues:**
- Custom server-side rendered (SSR) app — no Vue/React/Next fingerprint detected at root
- Stripe.js v3 for payments
- Cloudflare (CDN, challenge platform, Turnstile/hCaptcha)
- Google Tag Manager (GTM-PX5XJXX)
- TikTok Pixel, Facebook Pixel, Google Analytics (multiple GA4 properties), Hotjar 3395285
- CookieHub for consent management
- WAHA (WhatsApp HTTP API) running at `waha.charityright.org.uk` — separate service, credentials leaked in console (see Security)
---
## Phase 1 — Homepage Audit
### Redirect behaviour
- `/``/sadaqah` (permanent or temporary redirect — not a true homepage, no navigation)
### Page title
-`Give Sadaqah — Charity Right` — clear, descriptive
### Meta tags
| Tag | Value | Issue |
|-----|-------|-------|
| `<meta name="description">` | **MISSING** | ❌ No standard description tag |
| `<meta property="og:title">` | `Give Sadaqah — Charity Right` | ✅ |
| `<meta property="og:description">` | `50p feeds a child. Give Sadaqah in 30 seconds.` | ✅ |
| `<meta property="og:image">` | `https://www.charityright.org.uk/wp-content/uploads/2026/02/cr-wrong-1.jpg` | ⚠️ Cross-domain OG image (WordPress) |
| `<meta name="robots">` | **MISSING** | ⚠️ No robots directives |
| `<meta name="viewport">` | `width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover` | ⚠️ `user-scalable=no` disables pinch-zoom — accessibility violation (WCAG 1.4.4) |
### Console errors on load
- ✅ 0 JS errors on sadaqah page itself
- 1 WARNING: Hotjar refuses to load (detects headless browser user-agent) — benign in production
### Cookie consent
- ✅ CookieHub banner shown on first visit (`dialog "About cookies on this site"`)
- ✅ Three options: "Allow all cookies", "Deny all", "Cookie settings"
- ⚠️ "Cookie settings" link uses `href="#"` (dead anchor) — should be `href` to settings panel or use `button` semantics
---
## Phase 2 — Navigation & Links
The site has **no navigation bar or header menu**. It is a single campaign page only. There are no internal links to other sections of the give site.
**External link found:**
- `https://www.charityright.org.uk/donate/` — links to main website (different domain)
**Routes tested:**
| Path | Result |
|------|--------|
| `/sadaqah` | ✅ 200 — Sadaqah donation page |
| `/zakat` | ❌ 404 — "Not Found" blank page |
| `/fidya` | ❌ 404 — "Not Found" blank page |
| `/qurban` | ❌ 404 — "Not Found" blank page |
| `/kaffarah` | ❌ 404 — "Not Found" blank page |
| `/login` | ❌ 404 — "Not Found" blank page |
| `/register` | ❌ 404 — "Not Found" blank page |
| `/campaigns` | ❌ 404 — "Not Found" blank page |
| `/donate` | ❌ 404 — "Not Found" blank page |
| `/appeal` | ❌ 404 — "Not Found" blank page |
**Key issue:** The 404 page returns **no `<title>`** tag and **no styled error page** — just the raw text "Not Found". There is no redirect to a helpful error page and no way back to a valid URL.
---
## Phase 3 — Donation Flow
### Flow architecture
The site uses an **inline slide-up payment panel** (overlay `div#overlay`) rather than a separate checkout page. This is a smooth UX pattern.
### Step 1: Amount selection
- Slider control: 6 (£6 default, feeds 12 children @ 50p/meal)
- Quick-pick buttons: £3, £6, £9, £12, £15
- ✅ Real-time meal counter updates
- ✅ Clear impact messaging ("Feeds 12 children")
### Step 2: Gift Aid
- ✅ Gift Aid toggle button (pre-selected/enabled by default)
- ✅ Calculates HMRC top-up (£6 → £7.50 total)
- House number + postcode fields appear when Gift Aid active
- ⚠️ **No validation visible** if Gift Aid address fields are left empty when proceeding
- ⚠️ Gift Aid declaration text is small/light — readability concern
### Step 3: "Give £6 Sadaqah" button
- Clicking opens a side/bottom panel (`div#overlay.open`)
- The overlay **blocks interaction** with the main page while open (correct modal behaviour)
### Step 4: Checkout panel ("Complete your Sadaqah")
Fields present:
| Field | Type | Placeholder | Label visible |
|-------|------|-------------|---------------|
| Full name | `textbox` | "As it appears on your card" | ✅ "Full name" |
| Email | `textbox` | "For your donation receipt" | ✅ "Email" |
| Card number | Stripe iframe | "Card number" | ✅ "Number" |
| Expiry | Stripe iframe | "MM / YY" | ✅ |
| CVC | Stripe iframe | "CVC" | ✅ |
- "Donate £6" button is **`disabled` by default** — only enabled when Stripe iframe reports complete card details
- ✅ Correct — prevents empty form submission
- ⚠️ Clicking "Give £6 Sadaqah" without filling name/email still opens the overlay — those fields have **no pre-validation** before opening the panel
- ✅ No `<form>` element (0 forms found) — form data handled entirely via JS/Stripe Elements
- ✅ Google Pay option available in Stripe Elements
- ✅ Trust signals: "🔒 Encrypted · Powered by Stripe" and "256-bit secure · No account needed · UK Charity 1155108"
### Empty form submission
- Donate button stays disabled until Stripe card fields are valid — no empty submit possible via UI
- **No visible validation errors** for empty name/email fields — they appear to be validated client-side by Stripe before enabling the button (TBC)
### Donation amount £1 test
- Minimum selectable via slider unclear (minimum appears to be £3 via preset buttons)
- Manual slider minimum not tested — slider defaults to £6
---
## Phase 4 — Mobile Responsiveness (375×812)
### Layout
- ✅ Page renders correctly at 375×812
- ✅ Same UI elements visible — no hidden/broken sections
- ✅ Campaign image scales correctly
- ✅ Quick-pick amount buttons visible and tappable
- ✅ Gift Aid toggle renders correctly
- ✅ Checkout panel (overlay) renders at mobile size
- ⚠️ `user-scalable=no` in viewport meta means users **cannot zoom** on mobile — this is an accessibility violation for low-vision users
- ⚠️ No hamburger menu (site is single-page, so this is acceptable, but there's no navigation at all)
- ✅ No horizontal scroll detected at 375px width
---
## Phase 5 — Performance & Accessibility
### Accessibility
| Check | Result | Issue |
|-------|--------|-------|
| Images missing `alt` | 0 | ✅ |
| Dead anchors `href="#"` | 1 | ⚠️ Cookie settings button uses `href="#"` |
| Unlabelled inputs | 1 | ⚠️ One input has no `aria-label` or `placeholder` |
| `user-scalable=no` in viewport | YES | ❌ WCAG 1.4.4 violation |
| Inline `onclick` handlers | 3 | ⚠️ 3 elements use inline event handlers |
| No `<nav>` landmark | Confirmed | ⚠️ No navigation landmark (single-page is valid but no skip-to-content) |
| No `<meta name="description">` | Confirmed | ❌ SEO/accessibility issue |
### Performance
- **Page load time:** 2,433ms (performance.timing) — acceptable
- **External scripts loaded:** 9 external `<script src>` tags
**External scripts inventory:**
1. `analytics.tiktok.com` — TikTok Pixel (×3 scripts)
2. `connect.facebook.net` — Facebook Pixel (×2 scripts, including large config JS)
3. `static.hotjar.com` — Hotjar session recording
4. `www.googletagmanager.com` — GTM (×1) + GA4 gtag (×4 separate GA properties!)
5. `cdn.cookiehub.eu` — CookieHub consent
6. `js.stripe.com/v3/` — Stripe.js
7. `googleads.g.doubleclick.net` — Google Ads conversion tracking (×2)
**⚠️ Performance concern:** 4 separate Google Analytics 4 properties (`G-1B4QR9YTTB`, `G-6RGJ9BTW2Q`, `G-4DB6TJNHZR`, `AW-876060108`, `AW-925998688`) + GTM + TikTok + Facebook + Hotjar = **significant tracking script bloat**. Each fires multiple analytics events per page load.
**Network errors (analytics):** Multiple `net::ERR_ABORTED` for analytics.google.com POSTs on page navigation — these appear to be in-flight beacons aborted during navigation (non-critical but noisy).
---
## Phase 6 — Key Pages
| Page | Status | Notes |
|------|--------|-------|
| `/sadaqah` | ✅ 200 | Main and only working page |
| `/zakat` | ❌ 404 | Common Islamic giving category — missing |
| `/fidya` | ❌ 404 | Ramadan-specific — missing |
| `/qurban` | ❌ 404 | Eid-related — missing |
| `/kaffarah` | ❌ 404 | Missing |
| `/login` | ❌ 404 | No user accounts on this domain |
| `/register` | ❌ 404 | No user accounts on this domain |
| `/campaigns` | ❌ 404 | Missing |
The site appears to only have the one `/sadaqah` route currently live. All other paths return bare 404 responses.
---
## Phase 7 — Security
### HTTPS
- ✅ Site is fully HTTPS (`https://give.charityright.org.uk`)
- ✅ Stripe iframe loads over HTTPS
- ✅ No mixed content detected
- ✅ Cloudflare CDN with challenge platform (`cdn-cgi/challenge-platform`)
### Forms
- ✅ No `<form>` elements found — payment handled entirely via Stripe.js (no raw card data hits the server)
- ✅ Stripe tokenisation means card details never touch CharityRight servers
### Cookies
| Cookie | Domain | Secure? | HttpOnly? | Concern |
|--------|--------|---------|-----------|---------|
| `cf_clearance` | `.charityright.org.uk` | ✅ (HTTPS-only session) | N/A | Cloudflare bot protection |
| `__stripe_mid`, `__stripe_sid` | `.give.charityright.org.uk` | ✅ | Unknown | Stripe session — should be HttpOnly |
| `cookiehub` | `.charityright.org.uk` | ✅ | N/A | Consent preferences |
| `_ga`, `_ga_*` | `.charityright.org.uk` | ✅ | N/A | Google Analytics |
| `_fbp` | `.charityright.org.uk` | ✅ | N/A | Facebook Pixel |
| `_ttp` | `.charityright.org.uk` + `.tiktok.com` | ✅ | N/A | TikTok tracking |
| `IDE` | `.doubleclick.net` | ✅ | N/A | Google Ads |
⚠️ `__stripe_mid` and `__stripe_sid` are visible in `document.cookie` — meaning they are **not HttpOnly**. Stripe session cookies should ideally be HttpOnly to prevent XSS token theft (though Stripe sets these itself — CharityRight cannot control this).
### 🚨 CRITICAL: Credentials in Browser Console
**From previous browsing session logs captured in the test environment:**
```
[ERROR] SecurityError: Failed to execute 'replaceState' on 'History':
A history state object with URL
'https://waha.charityright.org.uk/dashboard/' cannot be created in a document
with origin 'https://waha.charityright.org.uk' and URL
'https://admin:J59vAcWI56BReJEFCi@waha.charityright.org.uk/dashboard/'.
```
**This is a CRITICAL security issue.** The URL `https://admin:J59vAcWI56BReJEFCi@waha.charityright.org.uk/dashboard/` contains **basic authentication credentials in plaintext** (`admin:J59vAcWI56BReJEFCi`). These were captured in the browser's console log, meaning:
1. Anyone with DevTools access to `waha.charityright.org.uk` could see these credentials
2. The credentials are for the WAHA (WhatsApp HTTP API) admin dashboard
3. WAHA controls WhatsApp messaging for the organisation — a breach here could expose donor communications
**Immediate action required:** Change the WAHA admin password and remove credentials from any hardcoded URLs. Use proper session-based auth instead.
### Hub API 401 Errors
Multiple failed requests to `hub.quikcue.com/api/user/*` (401 Unauthorized):
```
GET https://hub.quikcue.com/api/user/lifecycle → 401
GET https://hub.quikcue.com/api/user/admin → 401
GET https://hub.quikcue.com/api/user/init → 401
```
The give.charityright.org.uk site is calling **QuikCue's hub API** on every page load and receiving 401s. These appear to be unauthenticated calls. This could indicate a misconfigured integration or leftover code from a shared codebase.
### Development URL in Production
From console errors: `http://localhost:3000/api/pledges → 400 Bad Request`
A hardcoded `localhost:3000` URL is being called from production. This is a development/staging configuration leak.
---
## Console Errors Summary
| Error | Source | Severity |
|-------|--------|----------|
| `localhost:3000/api/pledges` returning 400 | Sadaqah page JS | 🔴 High — dev URL in prod |
| `hub.quikcue.com/api/user/*` returning 401 (×8+ times) | Page load | 🟠 Medium — unnecessary failed requests |
| `waha.charityright.org.uk` credentials in URL | WAHA dashboard JS | 🔴 Critical — credential leak |
| `waha.charityright.org.uk/api/*` returning 401 | WAHA dashboard | 🟡 Low — expected if not logged in |
| `give.charityright.org.uk/favicon.ico` returning 404 | Browser | 🟡 Low — missing favicon |
| `analytics.google.com` ERR_ABORTED (×6) | Navigation beacons | 🟢 Info — benign race condition |
---
## Summary Table
| # | Issue | Location | Severity | Category |
|---|-------|----------|----------|----------|
| 1 | **Credentials in URL**: `admin:J59vAcWI56BReJEFCi` in WAHA console error | `waha.charityright.org.uk` | 🔴 **Critical** | Security |
| 2 | **`localhost:3000/api/pledges`** called from production | `/sadaqah` JS | 🔴 **Critical** | Config / Security |
| 3 | **All routes 404** except `/sadaqah` — no error page, no redirect | `/zakat`, `/fidya`, etc. | 🟠 **High** | Navigation |
| 4 | **404 page has no title, no styling, no back link** | All 404 responses | 🟠 **High** | UX |
| 5 | **`hub.quikcue.com` API called 8+ times with 401** on every page load | `/sadaqah` | 🟠 **High** | Performance / Config |
| 6 | **Missing `<meta name="description">`** | All pages | 🟠 **High** | SEO |
| 7 | **`user-scalable=no` in viewport meta** — disables pinch zoom | All pages | 🟠 **High** | Accessibility (WCAG 1.4.4) |
| 8 | **4 separate GA4 properties** + 2 Google Ads + TikTok + Facebook + Hotjar | All pages | 🟡 **Medium** | Performance / Privacy |
| 9 | **No Gift Aid address validation** before proceeding to checkout | `/sadaqah` | 🟡 **Medium** | UX / Data quality |
| 10 | **Name/email not validated** before overlay opens | `/sadaqah` checkout | 🟡 **Medium** | UX |
| 11 | **OG image served from WordPress domain** (`charityright.org.uk/wp-content/`) | `/sadaqah` | 🟡 **Medium** | Reliability / Performance |
| 12 | **No `<meta name="robots">`** directive | All pages | 🟡 **Medium** | SEO |
| 13 | **`href="#"`** on cookie settings anchor | Cookie banner | 🟡 **Medium** | Accessibility |
| 14 | **1 unlabelled input** (no aria-label, no placeholder) | `/sadaqah` | 🟡 **Medium** | Accessibility |
| 15 | **3 inline `onclick` handlers** | `/sadaqah` | 🟡 **Medium** | Code quality |
| 16 | **Hotjar not loading** (detects headless/bot UA) | All pages | 🟡 **Medium** | Analytics |
| 17 | **Missing favicon** (404 on `/favicon.ico`) | All pages | 🟢 **Low** | Branding |
| 18 | **No skip-to-content link** | All pages | 🟢 **Low** | Accessibility |
| 19 | **No `<nav>` landmark** | All pages | 🟢 **Low** | Accessibility |
| 20 | **Stripe session cookies not HttpOnly** | `/sadaqah` | 🟢 **Low** | Security (Stripe-controlled) |
---
## Recommendations (Priority Order)
### 🔴 Immediate (Critical)
1. **Rotate WAHA admin credentials**`admin:J59vAcWI56BReJEFCi` is exposed in browser console. Change password immediately. Audit who accessed WAHA.
2. **Remove `localhost:3000` URL** from production build — likely a `.env` misconfiguration. The `/api/pledges` call should point to the production API endpoint.
### 🟠 High Priority
3. **Add styled 404 page** with charity branding, navigation back to `/sadaqah`, and proper `<title>`.
4. **Fix `hub.quikcue.com` API calls** — either authenticate them properly or remove them from the give site (wrong codebase/integration).
5. **Add `<meta name="description">`** — currently only `og:description` is set.
6. **Remove `user-scalable=no`** from viewport meta — replace with `user-scalable=yes` to comply with WCAG 1.4.4.
### 🟡 Medium Priority
7. **Audit tracking scripts** — consolidate 4 GA4 properties if possible, remove duplicates. Each extra script adds load time and GDPR surface area.
8. **Validate Gift Aid fields before opening checkout overlay** — show inline error if Gift Aid is enabled but address fields are empty.
9. **Validate name/email before showing checkout overlay** — currently you can open the payment panel without entering name/email.
10. **Move OG image to `give.charityright.org.uk` CDN** — remove cross-domain WordPress dependency.
11. **Replace `href="#"` on Cookie Settings** with proper button element or `href="javascript:void(0)"`.
12. **Fix unlabelled input** — audit the 1 input missing both `aria-label` and `placeholder`.
### 🟢 Low Priority
13. Add favicon to `give.charityright.org.uk`.
14. Add `<meta name="robots" content="index,follow">` explicitly.
15. Add skip-to-content link for keyboard/screen reader users.
---
## Screenshots Captured
| File | Description |
|------|-------------|
| `screenshots/cr-homepage.png` | Full page — sadaqah donation page at 1440×900 |
| `screenshots/cr-donation-form.png` | Full page after clicking "Give £6 Sadaqah" |
| `screenshots/cr-form-filled.png` | Checkout overlay with name/email filled |
| `screenshots/cr-form-ready.png` | Checkout overlay with full card details entered, Donate button enabled |
| `screenshots/cr-overlay-open.png` | Overlay state after form interaction |
| `screenshots/cr-mobile.png` | Full page at 375×812 mobile viewport |
| `screenshots/cr-zakat.png` | 404 page for /zakat |