TaipanStack v0.3.4 โ Quality, Security Hardening & Code Health¶
Overview¶
v0.3.4 is a quality patch release that significantly deepens test coverage, hardens security validators, modularises the codebase, and introduces a new password security module โ all while maintaining 100% backwards compatibility.
This release merges 23 Pull Requests covering test improvements, security fixes, refactoring/code-health, and performance optimisations.
1. ๐ Security Fix โ Plaintext Password Handling¶
File: src/app/secure_system.py | PR #93
UserService.create_user previously stored user passwords as plaintext strings. This has been corrected: passwords are now properly hashed before being passed to the internal user store.
# Before (insecure)
user = User(username=username, password=password)
# After (secure)
user = User(username=username, password=hash_password(password))
[!WARNING] This is a security fix. All deployments on v0.3.3 or earlier are encouraged to upgrade immediately and re-hash any stored passwords.
2. ๐ New password Security Module¶
File: src/taipanstack/security/password.py + tests/test_security_password.py
A dedicated password security module has been introduced, providing:
hash_password(password: str) -> strโ bcrypt-based secure hashingverify_password(plain: str, hashed: str) -> boolโ constant-time comparisongenerate_secure_token(length: int = 32) -> strโ cryptographically secure random token generator
from taipanstack.security.password import hash_password, verify_password
hashed = hash_password("my_secret_password")
assert verify_password("my_secret_password", hashed) # True
assert not verify_password("wrong_password", hashed) # False
3. ๐ Async Resilience (@retry & @circuit_breaker)¶
Files: src/taipanstack/utils/retry.py & src/taipanstack/utils/circuit_breaker.py
Native asynchronous support was added to both resilience primitives. Coroutines are wrapped transparently, allowing the event loop to yield correctly via asyncio.sleep(). Both decorators export precise @overload signatures, matching strict-mode mypy requirements.
from taipanstack.utils.retry import retry
from taipanstack.utils.circuit_breaker import circuit_breaker
@retry(max_attempts=3)
@circuit_breaker(failure_threshold=5)
async def fetch_user_data(user_id: int) -> dict:
return await async_http_client.get(f"/users/{user_id}")
4. ๐ก๏ธ Pydantic Security Types¶
File: src/taipanstack/security/types.py
Introduced native Pydantic v2 compatibility for TaipanStack's security validators. You can now declaratively shield your API models against SSRF, Path Traversal, and Command Injection directly inside the type annotations using SafeUrl, SafePath, SafeCommand, and SafeProjectName.
from pydantic import BaseModel
from taipanstack.security.types import SafeUrl, SafeCommand
class WebhookPayload(BaseModel):
# Validates URL format AND rejects SSRF (loopback/private IPs)
target_url: SafeUrl
# Validates against shell metacharacters (; | $ > &)
script_step: SafeCommand
5. ๐ต๏ธ Structlog Data Masking¶
File: src/taipanstack/utils/logging.py
Added the mask_sensitive_data_processor to the structlog pipeline. This processor automatically intercepts structured log event dictionaries and redacts sensitive parameters based on case-insensitive key patterns (password, secret, token, authorization, api_key).
from taipanstack.utils.logging import get_logger
log = get_logger()
# The value "super_secret_value" will be logged as "***REDACTED***"
log.info("user_authenticated", username="alice", password="super_secret_value")
3. ๐งช Test Coverage Improvements¶
Extensive test coverage has been added across all validators and core modules. Every new test asserts both positive and negative code paths:
| Test File | New Tests | Coverage Target |
|---|---|---|
test_security_validators.py |
6 new | validate_ip_address, validate_port, validate_url, validate_python_version |
test_security_validators_extended.py |
4 new | validate_ip_address (IPv4 + IPv6 edge cases) |
test_result_module.py |
3 new | @safe / @safe_from base Exception and explicit raise |
test_utils_logging.py |
4 new | log_operation expected/unexpected exception branches |
test_utils_filesystem.py |
4 new | Path traversal without base_dir |
test_compat.py |
2 new | get_optimization_level CVE-2020-10735 integer string limits |
test_secure_system.py |
3 new | UserService โ UserAlreadyExistsError path |
test_security_password.py |
7 new | New password module โ hashing, verification, token generation |
test_security_ssrf.py |
2 updated | DNS error message platform-independence + hostname truncation |
Notable: CVE-2020-10735 Test Coverage (PR #129)¶
Python 3.11+ enforces a limit on integer-string conversion to prevent DoS via extremely large integers. v0.3.4 ensures get_optimization_level correctly handles the ValueError raised when an environment variable contains a string exceeding 4300 digits:
huge_int_str = "9" * 4500
with patch.dict(os.environ, {"STACK_OPTIMIZATION_LEVEL": huge_int_str}):
assert get_optimization_level() == 1 # falls back gracefully
URL Port Lazy Evaluation Fix (PR #130 / #126)¶
urlparse is lazily evaluated โ accessing .port triggers full parsing. validate_url now explicitly evaluates the port attribute during the parse step:
parsed = urlparse(url)
_ = parsed.port # triggers lazy evaluation โ catches out-of-range ports
This ensures that http://example.com:99999999999 raises ValueError("Invalid URL format: Port out of range") as expected.
4. ๐งน Code Health & Refactoring¶
| Change | File(s) | PR |
|---|---|---|
Remove unused compat imports from taipanstack.core public API |
core/__init__.py |
#99 |
Remove unused imports from root __init__.py |
taipanstack/__init__.py |
#100 |
Define proper __all__ in utils/__init__.py |
utils/__init__.py |
#98 |
Remove redundant from __future__ import annotations |
Multiple | #112 |
| Preserve valid config package public API | config/__init__.py |
#102 |
5. โก Performance¶
| Change | File | PR | Gain |
|---|---|---|---|
Optimise string concatenation in generate_pre_commit_config using list + join instead of += |
config/generators.py |
#130 | ~10โ15% on large configs |
6. ๐ง CI / DevOps¶
| Fix | Detail |
|---|---|
| openSUSE Leap repo | Added zypper removerepo repo-openh264 \|\| true before package install to suppress failures on CI runners without the codec repo (PR #116) |
| Actions Group Bump | Bumped actions/checkout, actions/setup-python, and related actions to latest versions (PR #95) |
Q&A Summary¶
| Metric | v0.3.3 | v0.3.4 |
|---|---|---|
| Test Coverage | 100% | 100% |
| Total Tests | ~650 | ~685 |
| Security Fixes | 0 | 1 (critical) |
| New Security Modules | โ | password.py & types.py |
| New Async Support | โ | retry & circuit_breaker |
| CVE Test Coverage | โ | โ CVE-2020-10735 |
| Breaking Changes | 0 | 0 |
Upgrade¶
pip install --upgrade taipanstack==0.3.4
No breaking changes โ upgrade is safe for all v0.3.x installations.