Skip to main content

A robust data validation and serialization library built on top of Pydantic

Project description

Sheildantic

A Python package that combines Pydantic validation with HTML sanitization for secure form handling in web applications.

Overview

Sheildantic provides a seamless way to sanitize and validate user input from web forms, protecting against XSS attacks while leveraging Pydantic's powerful validation capabilities. It's framework-agnostic and works with any web framework that can provide form data as a dictionary or MultiDict.

Key Features

  • HTML Sanitization: Safely handles user-provided HTML content using the NH3 library
  • Pydantic Integration: Validates sanitized data against your Pydantic models
  • MultiDict Support: Properly handles multi-value form fields (like checkboxes or multi-selects)
  • Framework Agnostic: Works with FastAPI, Flask, Django, or any Python web framework
  • Detailed Error Reporting: Provides comprehensive validation error details
  • Configurable Sanitization: Customize allowed HTML tags, attributes, and more

Installation

You can install Sheildantic directly from the GitHub repository:

# Using pip
pip install git+https://github.com/Hybridhash/Sheildantic.git@main

# Using poetry
poetry add git+https://github.com/Hybridhash/Sheildantic.git@main

# Using uv
uv pip install git+https://github.com/Hybridhash/Sheildantic.git@main

Usage

Basic Example

from pydantic import BaseModel
from multidict import MultiDict
from sheildantic.core import InputValidator
from sheildantic.models import SanitizationConfig

# Define your Pydantic model
class BlogPost(BaseModel):
    title: str
    content: str
    tags: list[str] = []
    published: bool = False

# Create sanitization config
config = SanitizationConfig(
    tags={"p", "br", "strong", "em"},  # Allow only these HTML tags
    attributes={},  # No attributes allowed
    max_field_size=10000  # Maximum field size
)

# Create a validator instance
validator = InputValidator(BlogPost, config)

# Example form data (this could come from a web request)
form_data = MultiDict([
    ("title", "<script>alert('XSS')</script>My Blog Post"),
    ("content", "<p>This is <strong>valid</strong> content</p><iframe src='evil.com'></iframe>"),
    ("tags", "python"),
    ("tags", "security"),
    ("published", "true")
])

# Validate the input
result = await validator.validate(form_data)

if result.is_valid:
    # Access the sanitized and validated data
    blog_post = result.model
    print(f"Title: {blog_post.title}")
    print(f"Content: {blog_post.content}")
    print(f"Tags: {blog_post.tags}")
    print(f"Published: {blog_post.published}")
    
    # You can also access the sanitized data directly 
    # (this preserves allowed HTML elements)
    sanitized_content = result.sanitized_data["content"]
else:
    # Handle validation errors
    for error in result.errors:
        print(f"Error in field '{error.field}': {error.message}")

Integration with FastAPI

from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
from sheildantic.core import InputValidator
from sheildantic.models import SanitizationConfig, ValidationResult

app = FastAPI()

class UserComment(BaseModel):
    username: str
    comment: str

async def get_request_data(request: Request):
    """Extract form data from the request"""
    form_data = await request.form()
    return form_data

@app.post("/comments")
async def create_comment(request: Request):
    # Get form data
    data = await get_request_data(request)
    
    # Configure validation
    config = SanitizationConfig(
        tags={"p", "br", "a"},
        attributes={"a": {"href", "title"}},
        url_schemes={"http", "https"},
        link_rel="noopener noreferrer"
    )
    
    # Validate and sanitize
    validator = InputValidator(UserComment, config)
    result = await validator.validate(data)
    
    if not result.is_valid:
        raise HTTPException(
            status_code=400, 
            detail=[err.dict() for err in result.errors]
        )
    
    # Process the valid and sanitized comment
    user_comment = result.model
    # Save to database, etc.
    
    return {
        "status": "success",
        "comment": user_comment.dict()
    }

Code Flow

Sheildantic follows this processing flow:

  1. Input Collection: Receives input data as a dict or MultiDict
  2. Sanitization:
    • Processes the input through NH3 sanitizer
    • Handles MultiDict fields (converting to lists when needed)
    • Applies max field size limits
  3. Validation:
    • Runs sanitized data through Pydantic validation
    • Produces detailed validation errors
  4. Result: Returns a ValidationResult containing:
    • Validation status
    • Sanitized data (with allowed HTML preserved)
    • Validated Pydantic model instance
    • Detailed error information

Configuration Options

The SanitizationConfig class allows you to customize sanitization:

config = SanitizationConfig(
    # Allowed HTML tags (None = use NH3 defaults)
    tags={"p", "br", "strong", "em", "a", "ul", "li"},
    
    # Allowed attributes for specific tags
    attributes={"a": {"href", "title"}},
    
    # Allowed URL schemes
    url_schemes={"http", "https"},
    
    # Strip HTML comments
    strip_comments=True,
    
    # Add rel attribute to links
    link_rel="noopener noreferrer",
    
    # Tags to clean content from
    clean_content_tags={"script", "style"},
    
    # Maximum field size
    max_field_size=10000
)

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sheildantic-0.1.0.tar.gz (7.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sheildantic-0.1.0-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file sheildantic-0.1.0.tar.gz.

File metadata

  • Download URL: sheildantic-0.1.0.tar.gz
  • Upload date:
  • Size: 7.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.9

File hashes

Hashes for sheildantic-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f0fb4f4d6dcf01b6f2abc060f37df3fe37ce6c4dab808df25f8d8f609ef84472
MD5 c33c239c2a93cbf742b442201a34ed3b
BLAKE2b-256 47a54722817309b79bf7b2879d89ba31fa05016ac48b9b16e1e855bbf89d6caf

See more details on using hashes here.

File details

Details for the file sheildantic-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for sheildantic-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 450bed7b50ba4dc20fb676b74c4d2ed846413cb05d0cd5dbabd3622b89b97c71
MD5 7c973b6470afd8714d2cbddfc55ee98e
BLAKE2b-256 686357a0898ca1aa65c7465617fe1790187cb8867129e1ca16c08d4c3cc55741

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page