Thanks to visit codestin.com
Credit goes to fory.apache.org

Skip to main content
Version: 0.14

Security Best Practices

This page covers security best practices and DeserializationPolicy.

Production Configuration

Never disable strict=True in production unless your environment is completely trusted:

import pyfory

# Recommended production settings
f = pyfory.Fory(
xlang=False, # or True for cross-language
ref=True, # Handle circular references
strict=True, # IMPORTANT: Prevent malicious data
max_depth=100 # Prevent deep recursion attacks
)

# Explicitly register allowed types
f.register(UserModel, type_id=100)
f.register(OrderModel, type_id=101)
# Never set strict=False in production with untrusted data!

Development vs Production

Use environment variables to switch between configurations:

import pyfory
import os

# Development configuration
if os.getenv('ENV') == 'development':
fory = pyfory.Fory(
xlang=False,
ref=True,
strict=False, # Allow any type for development
max_depth=1000 # Higher limit for development
)
else:
# Production configuration (security hardened)
fory = pyfory.Fory(
xlang=False,
ref=True,
strict=True, # CRITICAL: Require registration
max_depth=100 # Reasonable limit
)
# Register only known safe types
for idx, model_class in enumerate([UserModel, ProductModel, OrderModel]):
fory.register(model_class, type_id=100 + idx)

DeserializationPolicy

When strict=False is necessary (e.g., deserializing functions/lambdas), use DeserializationPolicy to implement fine-grained security controls during deserialization.

Why use DeserializationPolicy?

  • Block dangerous classes/modules (e.g., subprocess.Popen)
  • Intercept and validate __reduce__ callables before invocation
  • Sanitize sensitive data during __setstate__
  • Replace or reject deserialized objects based on custom rules

Blocking Dangerous Classes

import pyfory
from pyfory import DeserializationPolicy

dangerous_modules = {'subprocess', 'os', '__builtin__'}

class SafeDeserializationPolicy(DeserializationPolicy):
"""Block potentially dangerous classes during deserialization."""

def validate_class(self, cls, is_local, **kwargs):
# Block dangerous modules
if cls.__module__ in dangerous_modules:
raise ValueError(f"Blocked dangerous class: {cls.__module__}.{cls.__name__}")
return None

def intercept_reduce_call(self, callable_obj, args, **kwargs):
# Block specific callable invocations during __reduce__
if getattr(callable_obj, '__name__', "") == 'Popen':
raise ValueError("Blocked attempt to invoke subprocess.Popen")
return None

def intercept_setstate(self, obj, state, **kwargs):
# Sanitize sensitive data
if isinstance(state, dict) and 'password' in state:
state['password'] = '***REDACTED***'
return None

# Create Fory with custom security policy
policy = SafeDeserializationPolicy()
fory = pyfory.Fory(xlang=False, ref=True, strict=False, policy=policy)

# Now deserialization is protected by your custom policy
data = fory.serialize(my_object)
result = fory.deserialize(data) # Policy hooks will be invoked

Available Policy Hooks

HookDescription
validate_class(cls, is_local)Validate/block class types during deserialization
validate_module(module, is_local)Validate/block module imports
validate_function(func, is_local)Validate/block function references
intercept_reduce_call(callable_obj, args)Intercept __reduce__ invocations
inspect_reduced_object(obj)Inspect/replace objects created via __reduce__
intercept_setstate(obj, state)Sanitize state before __setstate__
authorize_instantiation(cls, args, kwargs)Control class instantiation

See also: pyfory/policy.py contains detailed documentation and examples for each hook.

Best Practices

  1. Always use strict=True in production
  2. Use DeserializationPolicy when strict=False is necessary
  3. Block dangerous modules (subprocess, os, etc.)
  4. Set appropriate max_depth to prevent stack overflow
  5. Validate data sources before deserialization
  6. Log security events for auditing