Secure File Handling
Relevant source files
The following files were used as context for generating this wiki page:
Secure File Handling in the Rosy Tax Processor project encompasses the lifecycle of sensitive tax documents from upload to final PDF generation. The system is designed as a local-first prototype, focusing on protecting Personally Identifiable Information (PII) through sanitization, validation, and temporary storage management.
The primary goal is to ensure that tax documents (PDFs, images, or text) are processed without exposing sensitive data like Social Security Numbers (SSNs) in plaintext API responses, while maintaining strict control over file access and local storage.
Ingestion and Validation Architecture
The system implements a multi-layered validation approach for all incoming files. When a user uploads files via the /upload endpoint, the backend immediately subjects them to security checks before any processing occurs.
Validation Workflow
- Size Restriction: Files are checked against a hard limit (5 MB) to prevent denial-of-service or storage exhaustion.
- Type Filtering: Only specific extensions related to tax documents are allowed.
- Filename Sanitization: Original filenames are stripped of dangerous characters and path components to prevent directory traversal attacks.
The following flowchart illustrates the initial ingestion security logic:
Sources: security.py:10-25, backend.py:53-65, README.md:144-150
Security Configuration Constants
| Parameter | Value | Description |
|---|---|---|
ALLOWED_EXT | .pdf, .txt, .png, .jpg, .jpeg | Permitted file extensions for processing. |
MAX_UPLOAD_BYTES | 5,242,880 (5 MB) | Maximum size allowed per uploaded file. |
Filename Limit | 200 Characters | Maximum length for sanitized filenames. |
Sources: security.py:9-10, security.py:19
Data Privacy and PII Protection
A core component of the security model is the protection of PII, specifically Social Security Numbers. This is achieved through regex-based masking before any data is sent to the frontend.
PII Masking Logic
The mask_pii_in_result function recursively traverses the pipeline results. It identifies string values and applies a masking pattern to SSNs (formatted as 123-45-6789), converting them to XXX-XX-6789. This ensures that while the backend processes the full data for tax calculation and form filling, the user interface and network logs do not contain plaintext SSNs.
Temporary File Management
To maintain a clean security posture on the host machine, the system utilizes isolated temporary directories for different stages of the lifecycle.
- Upload Isolation: Files are stored in directories prefixed with
rosy_upload_. - Finalization Isolation: Generated PDFs for download are stored in directories prefixed with
rosy_final_. - Automated Cleanup: The
uploadendpoint explicitly removes uploaded source files immediately after the pipeline extraction is complete, even before the response is returned to the user.
Sources: backend.py:51, backend.py:88-92, backend.py:101
Secure Form Generation
The transition from extracted data to a physical document is handled by the forms.py module. It supports both a fallback ReportLab canvas and an AcroForm filling mechanism using pdfrw.
Access Control for Downloads
The system includes a /download helper endpoint specifically for the demo. To mitigate risks, it implements a primitive path check ensuring that the requested file path contains the designated temporary directory prefix (rosy_upload_). This prevents arbitrary file reads from the server's file system.
@app.route('/download')
def download():
path = request.args.get('path')
if not path or not os.path.exists(path):
return 'Not found', 404
# ensure path contains 'rosy_upload_'
if 'rosy_upload_' not in path:
return 'Not allowed', 403
# ... read and return file bytes
Sources: backend.py:38-48, forms.py:87-122
Summary of Secure Handling Features
| Feature | Implementation | File Reference |
|---|---|---|
| Filename Sanitization | re.sub(r'[^A-Za-z0-9._-]', '_', base) | security.py:14-19 |
| SSN Masking | re.sub(r"\b(\d{3})-(\d{2})-(\d{4})\b", r"XXX-XX-\3", s) | security.py:28-32 |
| Type Validation | Extension whitelist check against ALLOWED_EXT | security.py:22-25 |
| Size Validation | Stream length check against MAX_UPLOAD_BYTES | backend.py:59-61 |
| Path Protection | Prefix validation in the /download route | backend.py:44-46 |
Conclusion
The Rosy Tax Processor implements a robust local security model that prioritizes the sanitization of input and the masking of sensitive output. By combining strict file validation with recursive PII masking, the system provides a secure environment for processing highly sensitive tax data within a prototype context. While effective for local use, the documentation notes that production deployment would require additional measures such as HTTPS, authentication, and encryption at rest.