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:
- Input Collection: Receives input data as a dict or MultiDict
- Sanitization:
- Processes the input through NH3 sanitizer
- Handles MultiDict fields (converting to lists when needed)
- Applies max field size limits
- Validation:
- Runs sanitized data through Pydantic validation
- Produces detailed validation errors
- 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0fb4f4d6dcf01b6f2abc060f37df3fe37ce6c4dab808df25f8d8f609ef84472
|
|
| MD5 |
c33c239c2a93cbf742b442201a34ed3b
|
|
| BLAKE2b-256 |
47a54722817309b79bf7b2879d89ba31fa05016ac48b9b16e1e855bbf89d6caf
|
File details
Details for the file sheildantic-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sheildantic-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
450bed7b50ba4dc20fb676b74c4d2ed846413cb05d0cd5dbabd3622b89b97c71
|
|
| MD5 |
7c973b6470afd8714d2cbddfc55ee98e
|
|
| BLAKE2b-256 |
686357a0898ca1aa65c7465617fe1790187cb8867129e1ca16c08d4c3cc55741
|