# Users can correct inaccurate personal data through the application UI

- **Pattern:** `ab-001504` (`gdpr-readiness.user-rights.right-to-rectification`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001504
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001504)

## Why it matters

GDPR Art. 16 and Art. 5(1)(d) require that personal data be kept accurate and that data subjects can correct inaccurate information. A profile page that displays personal data as read-only — no edit form, no save button — removes the user's ability to exercise this right. This is a quiet but persistent violation: the user's name or contact details may be wrong, and they have no mechanism to fix it. Email address changes carry additional security weight: allowing an email swap without verification exposes accounts to takeover, which creates a compounding GDPR breach risk on top of the rectification failure.

## Severity rationale

Medium because the violation is a clear but non-urgent Art. 16 gap — users cannot rectify inaccuracies, but the immediate harm is limited unless stale data drives automated decisions that affect the user.

## Remediation

Implement a profile edit form with a `PATCH` API call that persists changes immediately. Route email address changes through a separate verification flow.

```tsx
// app/settings/profile/page.tsx
'use client'
export default function ProfileSettingsPage({ user }: { user: User }) {
  const [name, setName] = useState(user.name ?? '')
  async function handleSave(e: FormEvent) {
    e.preventDefault()
    const res = await fetch('/api/user/profile', {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name }),
    })
    if (res.ok) toast.success('Profile updated.')
  }
  return (
    <form onSubmit={handleSave}>
      <label>Display Name<input value={name} onChange={e => setName(e.target.value)} required /></label>
      <p className="text-sm">To change your email, <a href="/settings/change-email">start the email change process</a>. A verification link will be sent to the new address.</p>
      <button type="submit">Save changes</button>
    </form>
  )
}
```

For the email change flow: store the pending change in a `pending_email_changes` table with an expiry token, send the verification link to the new address, and only apply the swap after the token is clicked. Never update `email` in the users table without email verification.

## Detection

- **ID:** `right-to-rectification`
- **Severity:** `medium`
- **What to look for:** Look for a user profile or account settings page where users can view and edit their personal information. Check what fields are editable — at minimum, name, email address, phone (if collected), and mailing address (if collected) should all be correctable. Verify that changes are actually persisted when the form is submitted (check that the form has a PATCH/PUT API call, not just a UI update). Check whether email address changes require verification via a confirmation link sent to the new address before the change takes effect — this is important both for GDPR (ensuring data accuracy) and for security (preventing account takeover via email change). Count all instances found and enumerate each.
- **Pass criteria:** Users can view all personal data held about them and edit it from a profile or settings page. Changes are immediately persisted to the database. Email changes trigger a verification email to the new address and only take effect after confirmation. All collected personal data fields are editable. At least 1 implementation must be confirmed.
- **Fail criteria:** No profile editing feature exists. Fields are displayed but read-only. Form appears to submit but no API call is made. Inaccurate data has no correction mechanism.
- **Skip (N/A) when:** Application has no user accounts or collects no personal data beyond authentication credentials managed by a third-party identity provider.
- **Detail on fail:** Example: `"Profile page exists but all personal data fields are read-only. No edit form or save button."` or `"Name field is editable but changes are not persisted — no PATCH request made on submit."` or `"Email address cannot be changed after account creation."`.
- **Remediation:** Implement a profile edit form with verified email changes:

  ```tsx
  // app/settings/profile/page.tsx
  'use client'
  import { useState, FormEvent } from 'react'

  export default function ProfileSettingsPage({ user }: { user: User }) {
    const [name, setName] = useState(user.name ?? '')
    const [saving, setSaving] = useState(false)

    async function handleSave(e: FormEvent) {
      e.preventDefault()
      setSaving(true)
      const res = await fetch('/api/user/profile', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name }),
      })
      setSaving(false)
      if (res.ok) toast.success('Profile updated.')
    }

    return (
      <form onSubmit={handleSave}>
        <label>
          Display Name
          <input value={name} onChange={e => setName(e.target.value)} required />
        </label>
        {/* Email change — requires separate verification flow */}
        <p className="text-sm text-muted-foreground">
          To change your email address,{' '}
          <a href="/settings/change-email">start the email change process</a>.
          A verification link will be sent to the new address.
        </p>
        <button type="submit" disabled={saving}>Save changes</button>
      </form>
    )
  }
  ```

  For the email change flow: send a verification token to the new address, store the pending email change in a `pending_email_changes` table with expiry, and only apply the change when the token is clicked.

---

## External references

- gdpr Art. 16
- gdpr Art. 5(1)(d)

Taxons: privacy-consent

HTML version: https://auditbuffet.com/patterns/ab-001504
