# Deep link parameters are validated before use

- **Pattern:** `ab-001858` (`mobile-navigation-linking.deep-linking.param-validation`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001858
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001858)

## Why it matters

Unvalidated deep link parameters are the mobile equivalent of SQL injection — an attacker crafts a URL like `myapp://product?id=../../admin` and your app executes database queries or navigation logic against that raw string. OWASP A03 (Injection) and CWE-20 (Improper Input Validation) both target exactly this pattern. A product ID that arrives as `"../config"` and lands directly in a fetch call exposes data that the user was never meant to see. Beyond security, invalid parameters crash screens and generate unhandled exceptions that are reported to production crash tracking.

## Severity rationale

Critical because unvalidated deep link parameters are user-controlled input that flows directly into data-fetching and navigation logic, enabling injection and unauthorized data access.

## Remediation

Validate every parameter from `route.params` at the screen boundary before it touches any data-fetching or navigation call. Use a Zod schema at the entry point so validation is explicit and type-safe:

```tsx
import { z } from 'zod'
import { useRoute } from '@react-navigation/native'

const ParamsSchema = z.object({
  id: z.string().regex(/^\d+$/, 'ID must be numeric'),
})

function ProductDetailScreen() {
  const route = useRoute()
  const parsed = ParamsSchema.safeParse(route.params)

  if (!parsed.success) {
    return <ErrorScreen message="Invalid product ID" />
  }

  const productId = parseInt(parsed.data.id, 10)
  // safe to fetch
}
```

Apply this pattern to every screen that has a `:param` segment in its deep link definition — not just the ones you think are sensitive.

## Detection

- **ID:** `param-validation`
- **Severity:** `critical`
- **What to look for:** Examine screens that receive deep link parameters (via `route.params`). Check whether parameters are validated, type-checked, or sanitized before use. Look for uses of `route.params` without validation, or direct DOM/data access with user-provided IDs.
- **Pass criteria:** Count all screens that receive deep link parameters via `route.params`. Screens receiving deep link parameters must validate their type and format before use. At least 1 validation pattern (type check, regex test, or schema validation) must exist per parameterized screen. Numeric IDs are checked to be numeric, string IDs are sanitized.
- **Fail criteria:** Parameters from deep links are used directly without validation (e.g., `const userId = route.params.id` followed by database query without checking if id is a valid number). No more than 0 parameterized screens should lack validation.
- **Skip (N/A) when:** The app has no deep links with dynamic parameters (0 URL patterns with `:param` segments).
- **Detail on fail:** Describe validation gaps. Example: `"ProductDetail screen accesses route.params.id directly in a data fetch without validating it's a valid product ID"` or `"No type checking on deep link parameters"`
- **Remediation:** Validate all deep link parameters before use. In your screens:

  ```tsx
  function ProductDetailScreen() {
    const route = useRoute()
    const { id } = route.params

    // Validate before use
    if (!id || typeof id !== 'string' || !/^\d+$/.test(id)) {
      return <ErrorScreen message="Invalid product ID" />
    }

    // Now safe to use
    const productId = parseInt(id, 10)
    // ... fetch and render
  }
  ```

  For more complex validation, consider using a library like Zod:

  ```tsx
  const ParamsSchema = z.object({ id: z.string().regex(/^\d+$/) })
  const parsed = ParamsSchema.safeParse(route.params)
  if (!parsed.success) {
    return <ErrorScreen message="Invalid parameters" />
  }
  ```

## External references

- cwe CWE-20
- owasp A03

Taxons: injection-and-input-trust, user-experience

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