Integrate secure memory handling in SecureCompletionClient to protect plaintext payloads from disk swapping and memory lingering. The implementation uses a secure_bytes context manager to safeguard sensitive data during encryption. Added fallback mechanism with warning when SecureMemory module is unavailable. Updated docstring to reflect the new security measure.
8.3 KiB
Secure Memory Operations
Overview
NOMYO now includes client-side secure memory operations to protect sensitive data in memory. This feature prevents plaintext payloads from being swapped to disk and guarantees memory is zeroed after encryption.
Features
- Cross-platform support: Linux, Windows, macOS
- Memory locking: Prevents sensitive data from being swapped to disk
- Guaranteed zeroing: Memory is cleared immediately after use
- Context managers: Automatic cleanup even on exceptions
- Backward compatible: Works even if secure memory is not available
- Configurable: Can be enabled/disabled per client instance
Security Benefits
- Prevent memory swapping: Sensitive data won't be written to disk via swap files
- Guaranteed zeroing: Memory is cleared immediately after encryption
- Protection against memory dumping: Reduces risk from memory analysis tools
- Automatic cleanup: Context managers ensure cleanup even on exceptions
Usage
Basic Usage
from nomyo import SecureChatCompletion
# Create client with secure memory enabled (default)
client = SecureChatCompletion(
base_url="https://api.nomyo.ai:12434",
secure_memory=True # Enabled by default
)
# Use as normal - payloads are automatically protected
response = await client.create(
model="Qwen/Qwen3-0.6B",
messages=[{"role": "user", "content": "Sensitive data"}]
)
Disabling Secure Memory
from nomyo import SecureChatCompletion
# Disable secure memory for testing or when not needed
client = SecureChatCompletion(
base_url="https://api.nomyo.ai:12434",
secure_memory=False
)
Global Configuration
from nomyo import disable_secure_memory, enable_secure_memory, get_memory_protection_info
# Disable globally
disable_secure_memory()
# Enable globally
enable_secure_memory()
# Check current status
info = get_memory_protection_info()
print(f"Secure memory enabled: {info['enabled']}")
print(f"Platform: {info['platform']}")
print(f"Protection level: {info['protection_level']}")
Using Secure Bytes Directly
from nomyo import secure_bytes
# Protect sensitive data
sensitive_data = b"Secret information"
with secure_bytes(sensitive_data) as protected:
# Data is locked in memory and will be zeroed on exit
process(protected)
# Memory automatically zeroed here
Platform Support
| Platform | Memory Locking | Secure Zeroing | Protection Level |
|---|---|---|---|
| Linux | ✓ (mlock) | ✓ (memset) | Full |
| Windows | ✓ (VirtualLock) | ✓ (RtlSecureZeroMemory) | Full |
| macOS | ✓ (mlock) | ✓ (memset) | Full |
| Other | ✗ | ✓ (fallback) | Zeroing only |
Implementation Details
Memory Locking
- Linux/macOS: Uses
mlock()system call to lock memory pages - Windows: Uses
VirtualLock()API to lock memory pages - Fallback: If memory locking fails, only zeroing is performed
Memory Zeroing
- bytearray: Zeroed in-place for maximum security
- bytes: Best-effort approach (Python's immutable bytes)
- Automatic: Always performed when exiting context manager
Error Handling
- Graceful degradation: If memory locking fails, continues with zeroing
- No exceptions: Operations continue even if security features unavailable
- Logging: Detailed logs for debugging security issues
Best Practices
- Keep secure memory enabled in production environments
- Use HTTPS for all communications (enabled by default)
- Encrypt sensitive data before processing
- Minimize plaintext lifetime - encrypt as soon as possible
- Monitor security logs for any issues with memory protection
Troubleshooting
Memory Locking Failures
Error: mlock permission denied
Solution: Grant CAP_IPC_LOCK capability or increase ulimit -l
# Temporary solution
sudo prlimit --memlock=unlimited --pid $$
# Permanent solution (Linux)
sudo setcap cap_ipc_lock=ep $(which python)
Windows: Usually works without special privileges
macOS: Usually works without special privileges
Secure Memory Unavailable
If secure memory is not available, the system falls back to standard memory handling with a warning. This ensures the application continues to work while alerting you to the reduced security level.
API Reference
Classes
SecureMemory
Cross-platform secure memory handler.
Methods:
lock_memory(data: bytes) -> bool: Lock memory to prevent swappingunlock_memory(data: bytes) -> bool: Unlock memory pageszero_memory(data: bytes) -> None: Securely zero memoryget_protection_info() -> dict: Get capability information
Context Managers
secure_bytes(data: bytes, lock: bool = True)
Context manager for secure byte handling.
Parameters:
data: Bytes to protectlock: Whether to attempt memory locking (default: True)
Example:
with secure_bytes(sensitive_data) as protected:
# Use protected data
pass
# Memory automatically zeroed
Functions
get_memory_protection_info() -> dict
Get information about available memory protection features.
Returns:
- Dictionary with protection status including:
enabled: Whether secure memory is enabledplatform: Current platformprotection_level: "full", "zeroing_only", or "none"has_memory_locking: Whether memory locking is availablehas_secure_zeroing: Whether secure zeroing is availablesupports_full_protection: Whether full protection is available
disable_secure_memory() -> None
Disable secure memory operations globally.
enable_secure_memory() -> None
Re-enable secure memory operations globally.
Examples
Secure Chat Completion
from nomyo import SecureChatCompletion
async def secure_chat():
# Create client with maximum security
client = SecureChatCompletion(
base_url="https://api.nomyo.ai:12434",
secure_memory=True # Default
)
# All payloads are automatically protected
response = await client.create(
model="Qwen/Qwen3-0.6B",
messages=[
{"role": "system", "content": "You are a secure assistant"},
{"role": "user", "content": "Sensitive information here"}
],
temperature=0.7
)
return response
Secure Data Processing
from nomyo import secure_bytes
import json
def process_sensitive_data(data_dict):
# Serialize to JSON
data_json = json.dumps(data_dict).encode('utf-8')
# Process with secure memory
with secure_bytes(data_json) as protected:
# Perform operations on protected data
result = encrypt_and_send(protected)
return result
Checking Security Status
from nomyo import get_memory_protection_info
def check_security_status():
info = get_memory_protection_info()
print(f"Security Status:")
print(f" Enabled: {info['enabled']}")
print(f" Platform: {info['platform']}")
print(f" Protection Level: {info['protection_level']}")
print(f" Memory Locking: {info['has_memory_locking']}")
print(f" Secure Zeroing: {info['has_secure_zeroing']}")
return info
Security Considerations
Memory Protection Levels
-
Full Protection (Linux/Windows/macOS):
- Memory locked to prevent swapping
- Memory zeroed after use
- Best security available
-
Zeroing Only (Fallback):
- Memory zeroed after use
- No memory locking
- Still provides significant security benefits
-
None (Disabled):
- No memory protection
- Standard Python memory management
- Only for testing or non-sensitive applications
When to Disable Secure Memory
Secure memory should only be disabled in the following scenarios:
- Testing: When testing encryption/decryption without security
- Performance testing: Measuring baseline performance
- Non-sensitive data: When processing public/non-sensitive information
- Debugging: When memory analysis is required
Security Warnings
- Memory locking may fail without appropriate privileges
- Python's memory management limits zeroing effectiveness for immutable bytes
- Always use HTTPS for production deployments
- Monitor logs for security-related warnings