| name | finwiz-security |
| description | Security and type safety standards for FinWiz including API key management, input validation, and mypy strict mode. Use when handling sensitive data, API keys, or implementing type safety. |
| allowed-tools | ["Read","Edit"] |
FinWiz Security & Type Safety Standards
Critical security practices and type safety requirements for FinWiz development.
Type Safety (mypy strict mode)
Required Type Annotations
All public functions and methods MUST have complete type annotations:
def analyze_stock(ticker: str, period: int = 365) -> StockAnalysis:
return StockAnalysis(ticker=ticker, period=period)
def log_analysis(ticker: str) -> None:
logger.info(f"Analyzing {ticker}")
def analyze_stock(ticker: str):
return StockAnalysis(ticker=ticker)
Type Annotation Rules
- Return type required (use
-> None if no return)
- All parameters must have type hints
- Use modern Python 3.12+ syntax:
str | None instead of Optional[str]
- Use
list[Type] instead of List[Type]
- Use
# type: ignore only with explanatory comment
API Key Security (CRITICAL)
Environment Variables Only
NEVER hardcode API keys:
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY environment variable not set")
api_key = "sk-proj-abc123..."
Required Environment Variables
Core APIs (Required):
OPENAI_API_KEY - OpenAI API
SERPER_API_KEY - Serper search
FIRECRAWL_API_KEY - Web scraping
ALPHA_VANTAGE_API_KEY - Financial data
Enhanced Features (Optional):
TWELVE_DATA_API_KEY - Market data (technical analysis)
PPLX_API_KEY - Perplexity search (enhanced research)
SEC_API_API_KEY - SEC filings (optional)
CHART_IMG_API_KEY - Chart generation
COINMARKETCAP_API_KEY - Cryptocurrency data
Logging Security
NEVER log full API keys:
logger.info(f"Using API key: {api_key[:8]}...")
logger.info(f"API key: {api_key}")
Input Validation (Pydantic v2 strict)
All External Inputs Must Be Validated
from pydantic import BaseModel, Field, field_validator
class TickerInput(BaseModel):
"""Validate ticker input with strict security."""
model_config = {
"str_strip_whitespace": True,
"str_upper": True,
"extra": "forbid"
}
symbol: str = Field(..., pattern=r'^[A-Z]{1,5}$')
@field_validator('symbol')
@classmethod
def validate_ticker(cls, v: str) -> str:
if not v.isalpha():
raise ValueError('Ticker must contain only letters')
return v.upper()
Validation Requirements
extra='forbid' - Reject unknown fields
Field() constraints - pattern, min_length, ge, le
@field_validator - Complex validation logic
- Sanitize inputs - Strip whitespace, normalize case
- Clear error messages - Actionable feedback
Data Privacy
Never Log Personal Financial Data
logger.info(f"Analyzing portfolio with {len(holdings)} holdings")
logger.info(f"Analyzing portfolio: {holdings}")
Error Messages
Generic to users, detailed internally:
try:
result = api_call(ticker)
except Exception as e:
logger.error(f"API call failed for {ticker}: {e}", exc_info=True)
raise ValueError("Unable to fetch data. Please try again later.")
except Exception as e:
raise ValueError(f"API call to {api_url} failed: {e}")
Rate Limiting & Timeouts
Rate Limiting (Required)
from finwiz.utils.rate_limiter import RateLimiter
limiter = RateLimiter(max_calls=20, period=60)
@limiter.limit
async def fetch_stock_data(ticker: str) -> dict:
return await api_client.get(f"/stock/{ticker}")
Timeouts (Required)
Always set explicit timeouts:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(url)
async with httpx.AsyncClient() as client:
response = await client.get(url)
Secure Coding Patterns
SQL Injection Prevention
cursor.execute(
"SELECT * FROM stocks WHERE ticker = %s",
(ticker,)
)
cursor.execute(f"SELECT * FROM stocks WHERE ticker = '{ticker}'")
Path Traversal Prevention
from pathlib import Path
def read_report(filename: str) -> str:
if not filename.replace('-', '').replace('_', '').isalnum():
raise ValueError("Invalid filename")
base_path = Path("reports")
file_path = (base_path / filename).resolve()
if not str(file_path).startswith(str(base_path.resolve())):
raise ValueError("Path traversal attempt")
return file_path.read_text()
def read_report(filename: str) -> str:
with open(f"reports/{filename}") as f:
return f.read()
Command Injection Prevention
import subprocess
import shlex
def run_analysis(ticker: str) -> str:
if not ticker.isalpha():
raise ValueError("Invalid ticker")
result = subprocess.run(
["python", "analyze.py", ticker],
capture_output=True,
text=True,
timeout=30
)
return result.stdout
def run_analysis(ticker: str) -> str:
result = subprocess.run(f"python analyze.py {ticker}", shell=True)
return result.stdout
Dependency Security
Dependency Scanning
uv audit
uv sync --upgrade
Secure Dependencies
- Keep dependencies updated
- Use dependency scanning tools
- Review third-party packages before adding
- Use lock files (uv.lock)
- Remove unused dependencies regularly
Infrastructure Security
HTTPS Configuration
import httpx
client = httpx.AsyncClient(
verify=True,
timeout=30.0
)
client = httpx.AsyncClient(verify=False)
Secure Headers
headers = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
}
Security Checklist
Before committing code:
Quick Reference
| Security Concern | Solution |
|---|
| API keys | Environment variables + validation at startup |
| Sensitive logs | Mask keys (first 8 chars), anonymize financial data |
| Input validation | Pydantic v2 strict mode with extra='forbid' |
| Type safety | Full annotations, mypy strict mode |
| Rate limits | RateLimiter decorator, CrewAI max_rpm=20 |
| Timeouts | httpx.AsyncClient(timeout=30.0) |
| Error messages | Generic to users, detailed to logs |
| SQL injection | Parameterized queries |
| Path traversal | Path validation and resolution |
| Command injection | List form subprocess calls |
Development Practices
Secure Development Lifecycle
- Use static code analysis tools (ruff, mypy)
- Implement security testing in CI/CD
- Code reviews for security issues
- Security training for developers
- Incident response procedures
Monitoring and Logging
- Log security events (failed auth, suspicious activity)
- Monitor for unusual patterns
- Set up alerts for security incidents
- Regular security audits
- Penetration testing
Apply these security standards consistently across all FinWiz development to protect sensitive financial data and maintain system integrity.