# Profanity or objectionable content filter on user input

- **Pattern:** `ab-000501` (`app-store-review-blockers.content-moderation.objectionable-content-filter`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000501
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000501)

## Why it matters

Apple's guideline 1.2 requires apps accepting user-generated text to filter objectionable content before it is stored and shown to others. Storing post or comment text directly to the database with no filtering (CWE-20, OWASP input validation) means a reviewer can post profanity or offensive content in your app and immediately see it appear — a scenario that results in rejection. Client-side filtering alone is insufficient because it is trivially bypassed via direct API calls. The combination of server-side filtering and the reporting mechanism (ab-000498) is the minimum acceptable moderation stack for any UGC platform.

## Severity rationale

Medium because unfiltered UGC submission directly violates Apple guideline 1.2 and any reviewer can verify the failure in seconds by typing into a post field.

## Remediation

Add server-side content filtering to every UGC submission route before writing to the database.

```ts
// src/app/api/posts/route.ts
import Filter from 'bad-words';
const filter = new Filter();

export async function POST(req: Request) {
  const { text } = await req.json();
  if (filter.isProfane(text)) {
    return Response.json({ error: 'Content violates community guidelines' }, { status: 400 });
  }
  // proceed to store
}
```

For image content, integrate AWS Rekognition or Google Vision Safe Search. For higher-volume text needs, the OpenAI Moderation API is free and covers hate speech, self-harm, and sexual content categories that `bad-words` misses. Client-side filtering is a UX nicety, not a substitute for server-side enforcement.

## Detection

- **ID:** `objectionable-content-filter`
- **Severity:** `medium`
- **What to look for:** Count all relevant instances and enumerate each. Search for content filtering on text input: libraries like `bad-words`, `profanity-filter`, `leo-profanity`, or custom filter implementations with word lists. Look for API-side filtering in server routes that accept UGC (search for `filter`, `sanitize`, `moderate`, `check` calls before storing text). Check if text input components have `maxLength` limits. Look for third-party moderation API calls at post/submit time (OpenAI Moderation API, Google Perspective API, Hive Moderation).
- **Pass criteria:** Text submitted as UGC goes through some form of content filtering before being stored and shown to other users — either client-side or server-side. At least 1 implementation must be verified.
- **Fail criteria:** UGC text is accepted and stored with no filtering, sanitization, or moderation checks of any kind.
- **Skip (N/A) when:** App has no user-generated text content (no posts, comments, messages, reviews, or bio fields visible to others).
- **Detail on fail:** `"Post submission in src/api/posts.ts stores text directly to database with no content filtering"`
- **Remediation:** Filtering objectionable content is a requirement for apps with UGC per Apple guideline 1.2.
  1. Add server-side content filtering on all UGC submission endpoints:
     ```js
     import Filter from 'bad-words';
     const filter = new Filter();
     if (filter.isProfane(postText)) {
       return res.status(400).json({ error: 'Content violates community guidelines' });
     }
     ```
  2. For image content, use AWS Rekognition or Google Vision Safe Search
  3. For more sophisticated needs, use OpenAI Moderation API (free) or Perspective API
  4. Client-side filtering alone is not sufficient — always validate server-side

## External references

- cwe CWE-20
- external apple-guideline-1.2-ugc-filter — https://developer.apple.com/app-store/review/guidelines/#user-generated-content

Taxons: regulatory-conformance, injection-and-input-trust

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