This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: fastapi-pydantic-v2-strict-polymorphic-guardrail

FastAPI Pydantic V2 Strict Polymorphic Deserialization Guardrail

Enforces strict validation (`strict=True`, `extra='forbid'`) alongside explicit tagged discriminators on all polymorphic unions in FastAPI Pydantic v2 schemas. This eliminates algorithmic complexity attacks (ReDoS/Backtracking CPU exhaustion) caused by sequential union branch evaluation and blocks silent type coercion exploits in nested payloads.

Prohibited Anti-Pattern: Lax Untagged Union Deserialization Inducing Silent Type Coercion and Backtracking CPU Exhaustion

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI Pydantic V2 Strict Polymorphic Deserialization Guardrail - Enforces strict validation (`strict=True`, `extra='forbid'`) alongside explicit tagged discriminators on all polymorphic unions in FastAPI Pydantic v2 schemas. This eliminates algorithmic complexity attacks (ReDoS/Backtracking CPU exhaustion) caused by sequential union branch evaluation and blocks silent type coercion exploits in nested payloads.
globs: app/**/*.py, src/**/*.py, api/**/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-pydantic-v2-strict-polymorphic-guardrail"
---

# FastAPI Pydantic V2 Strict Polymorphic Deserialization Guardrail

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Lax Untagged Union Deserialization Inducing Silent Type Coercion and Backtracking CPU Exhaustion

## System Constraints
You are a Principal Engineer enforcing strict polymorphic deserialization guardrails for FastAPI and Pydantic V2. Mandate invariants that eliminate branch-backtracking DoS vulnerabilities, implicit casting bypasses, and type confusion exploits across all incoming request schemas.

## Strict Guidelines
- Engineers MUST ALWAYS use `Annotated[Union[...], Field(discriminator='...')]` or `Discriminator` for any polymorphic payload variants.
- Engineers MUST ALWAYS set `model_config = ConfigDict(strict=True, extra='forbid')` on all Pydantic base classes and union member models.
- Engineers MUST NOT declare raw `Union[...]` or `TypeA | TypeB` as request body schemas without an explicit discriminator tag.
- Models MUST define discriminator fields as exact literal singletons using `Literal[...]` matching the tag value.
- Nested polymorphic structures MUST NOT rely on Pydantic's default lax mode coercion (e.g., parsing string '123' as integer or float, or casting falsy values to False).

## Bad vs Good Implementations
### Polymorphic Event Payload Deserialization in FastAPI

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Untagged `Union` requires linear exploration of all candidates. Without `strict=True`, Pydantic attempts data coercion across branches, enabling type-confusion vulnerabilities. Without a discriminator, combinatorial explosion occurs on nested unions, leaving endpoints vulnerable to denial-of-service via CPU exhaustion.
```python
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class PaymentEvent(BaseModel):
    event_id: str
    amount: int
    metadata: dict[str, str] = {}

class AuditEvent(BaseModel):
    event_id: str
    user_id: int
    action: str

# ANTI-PATTERN: Untagged union with default lax validation.
# Pydantic attempts linear evaluation: tries PaymentEvent, coercing fields
# if possible. Malicious deeply-nested payloads trigger worst-case branch backtracking
# (CPU exhaustion) and silent coercion (e.g., user_id='100' coerced into amount=100).
@app.post("/events")
def handle_event(payload: Union[PaymentEvent, AuditEvent]):
    return {"status": "ok", "type": type(payload).__name__}
```

#### Production Standard (Correct)
> **Standard**: Using an explicit `discriminator` enables O(1) direct branch selection without sequential trial-and-error backtracking. `strict=True` blocks unexpected type coercion, and `extra='forbid'` eliminates payload stuffing attacks.
```python
from typing import Annotated, Literal, Union
from fastapi import FastAPI
from pydantic import BaseModel, ConfigDict, Field

app = FastAPI()

class BaseStrictModel(BaseModel):
    model_config = ConfigDict(strict=True, extra="forbid")

class PaymentEvent(BaseStrictModel):
    event_type: Literal["payment"]
    event_id: str
    amount: int
    metadata: dict[str, str] = Field(default_factory=dict)

class AuditEvent(BaseStrictModel):
    event_type: Literal["audit"]
    event_id: str
    user_id: int
    action: str

StrictPolymorphicEvent = Annotated[
    Union[PaymentEvent, AuditEvent],
    Field(discriminator="event_type")
]

# PRODUCTION FIX: O(1) discriminator lookup, no silent coercion, forbids unexpected fields
@app.post("/events")
def handle_event(payload: StrictPolymorphicEvent):
    return {"status": "ok", "type": payload.event_type}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: FastAPI Pydantic V2 Strict Polymorphic Deserialization Guardrail

FastAPI Pydantic V2 Strict Polymorphic Deserialization Guardrail defines an industrial-grade behavioral standard for backend engineering. Enforces strict validation (`strict=True`, `extra='forbid'`) alongside explicit tagged discriminators on all polymorphic unions in FastAPI Pydantic v2 schemas. This eliminates algorithmic complexity attacks (ReDoS/Backtracking CPU exhaustion) caused by sequential union branch evaluation and blocks silent type coercion exploits in nested payloads. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Lax Untagged Union Deserialization Inducing Silent Type Coercion and Backtracking CPU Exhaustion Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftLax Untagged Union Deserialization Inducing Silent Type Coercion and Backtracking CPU ExhaustionCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS use `Annotated[Union[...], Field(discriminator='...')]` or `Discriminator` for any polymorphic payload variants.

Engineers MUST ALWAYS use `Annotated[Union[...], Field(discriminator='...')]` or `Discriminator` for any polymorphic payload variants.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS set `model_config = ConfigDict(strict=True, extra='forbid')` on all Pydantic base classes and union member models.

Engineers MUST ALWAYS set `model_config = ConfigDict(strict=True, extra='forbid')` on all Pydantic base classes and union member models.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST NOT declare raw `Union[...]` or `TypeA | TypeB` as request body schemas without an explicit discriminator tag.

Engineers MUST NOT declare raw `Union[...]` or `TypeA | TypeB` as request body schemas without an explicit discriminator tag.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Models MUST define discriminator fields as exact literal singletons using `Literal[...]` matching the tag value.

Models MUST define discriminator fields as exact literal singletons using `Literal[...]` matching the tag value.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Nested polymorphic structures MUST NOT rely on Pydantic's default lax mode coercion (e.g., parsing string '123' as integer or float, or casting falsy values to False).

Nested polymorphic structures MUST NOT rely on Pydantic's default lax mode coercion (e.g., parsing string '123' as integer or float, or casting falsy values to False).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is FastAPI Pydantic V2 Strict Polymorphic Deserialization Guardrail critical for AI coding assistants?

Enforces strict validation (`strict=True`, `extra='forbid'`) alongside explicit tagged discriminators on all polymorphic unions in FastAPI Pydantic v2 schemas. This eliminates algorithmic complexity attacks (ReDoS/Backtracking CPU exhaustion) caused by sequential union branch evaluation and blocks silent type coercion exploits in nested payloads. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Lax Untagged Union Deserialization Inducing Silent Type Coercion and Backtracking CPU Exhaustion) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

FastAPI