We release patches for security vulnerabilities in the following versions:
| Version | Supported |
|---|---|
| 1.x.x | :white_check_mark: |
| < 1.0 | :x: |
The TNFR Python Engine team takes security vulnerabilities seriously. We appreciate your efforts to responsibly disclose your findings and will make every effort to acknowledge your contributions.
Please do not report security vulnerabilities through public GitHub issues.
Instead, please report them via one of the following methods:
Please include the following information in your report:
TNFR provides proactive SQL injection prevention utilities:
The TNFR engine currently uses in-memory NetworkX graphs and file-based persistence (JSON, YAML, Pickle). While no SQL databases are currently used, the codebase includes comprehensive SQL injection prevention utilities for future database functionality.
Security Utilities Available:
from tnfr.security import (
SecureQueryBuilder,
validate_identifier,
sanitize_string_input,
validate_nodal_input,
)
# Always use parameterized queries
builder = SecureQueryBuilder()
query, params = builder.select("nfr_nodes", ["id", "nu_f", "phase"])\
.where("nu_f > ?", 0.5)\
.order_by("nu_f", "DESC")\
.build()
# Validate all identifiers (table/column names)
table_name = validate_identifier("nfr_nodes")
column_name = validate_identifier("nu_f")
# Sanitize string inputs
user_input = sanitize_string_input(user_provided_data, max_length=1000)
# Validate TNFR structural data before persistence
node_data = validate_nodal_input({
"nu_f": 0.75,
"phase": 1.57,
"coherence": 0.85,
})Security Principles:
Example of Safe vs Unsafe Patterns:
# ❌ UNSAFE: Never do this!
# query = f"SELECT * FROM nfr_nodes WHERE id = {user_input}"
# ✓ SAFE: Use parameterized queries
builder = SecureQueryBuilder()
query, params = builder.select("nfr_nodes")\
.where("id = ?", user_input)\
.build()
# Execute: cursor.execute(query, params)TNFR follows strict security practices to prevent hardcoded secrets:
.env files for local development (never commit these!).env.example to .env and fill in your credentialsEnvironment Configuration:
# Copy the example configuration
cp .env.example .env
# Edit .env with your actual credentials
# This file is gitignored and will not be committedUsing Configuration Utilities:
from tnfr.secure_config import (
load_pypi_credentials,
load_github_credentials,
load_redis_config,
get_cache_secret,
)
# Load credentials from environment
pypi_creds = load_pypi_credentials()
github_creds = load_github_credentials()
redis_config = load_redis_config()
# Get cache signing secret
cache_secret = get_cache_secret()Security Best Practices:
Automated Security Testing:
TNFR includes automated tests that scan for hardcoded secrets:
.env in .gitignoreThe TNFR engine uses Python's pickle module for caching complex TNFR structures (NetworkX graphs, EPIs, coherence states). Pickle can execute arbitrary code during deserialization.
Important Security Considerations:
Security Warnings:
Starting from version 1.x, TNFR will emit SecurityWarning when cache layers are created without signature validation. To suppress these warnings in trusted environments, set:
export TNFR_ALLOW_UNSIGNED_PICKLE=1TNFR provides convenient helper functions to create secure cache layers with HMAC signature validation. This is the recommended approach for production deployments.
from tnfr.utils import create_secure_shelve_layer, create_secure_redis_layer
# Set your cache secret via environment variable (recommended)
# export TNFR_CACHE_SECRET="your-secure-random-secret-key"
# Create secure cache layers (reads secret from environment)
shelf_layer = create_secure_shelve_layer("coherence.db")
redis_layer = create_secure_redis_layer()
# Store and retrieve TNFR structures safely
shelf_layer.store("nfr_state", {"epi": [1.5, 2.3], "theta": [0.1, 0.2]})
restored = shelf_layer.load("nfr_state")TNFR_CACHE_SECRET: Secret key for HMAC signature validation (required for secure layers)TNFR_ALLOW_UNSIGNED_PICKLE: Set to 1 to suppress security warnings for unsigned pickle usageFor more control, you can use the HMAC helper functions:
from tnfr.utils import (
create_hmac_signer,
create_hmac_validator,
ShelveCacheLayer,
RedisCacheLayer,
)
# Create HMAC signer and validator
secret = b"your-secure-secret-key"
signer = create_hmac_signer(secret)
validator = create_hmac_validator(secret)
# Create cache layers with signature validation
shelf_layer = ShelveCacheLayer(
"cache.db",
signer=signer,
validator=validator,
require_signature=True,
)
redis_layer = RedisCacheLayer(
namespace="tnfr:cache",
signer=signer,
validator=validator,
require_signature=True,
)ShelveCacheLayer and RedisCacheLayer support payload signing to detect tampering in environments where cache files or Redis instances are not fully trusted.
signer and validator parameters.require_signature=True to activate hardened mode. In hardened mode the cache deletes unsigned or invalid entries and raises a :class:tnfr.utils.SecurityError.Example with custom signing:
import hashlib
import hmac
from tnfr.utils import RedisCacheLayer, SecurityError, ShelveCacheLayer
SECRET = b"tnfr-shared-secret"
def signer(payload: bytes) -> bytes:
return hmac.new(SECRET, payload, hashlib.sha256).digest()
def validator(payload: bytes, signature: bytes) -> bool:
expected = hmac.new(SECRET, payload, hashlib.sha256).digest()
return hmac.compare_digest(expected, signature)
shelf_layer = ShelveCacheLayer(
"cache.db",
signer=signer,
validator=validator,
require_signature=True,
)
redis_layer = RedisCacheLayer(
namespace="tnfr:cache",
signer=signer,
validator=validator,
require_signature=True,
)
try:
shelf_layer.store("alpha", {"value": 1})
data = shelf_layer.load("alpha")
except SecurityError:
# Hardened mode rejected tampered payload
...Tamper Detection:
When hardened mode is active, any tampered cache entry is automatically purged and causes an immediate SecurityError, preventing poisoned payloads from propagating through TNFR simulations.
If you're using ShelveCacheLayer or RedisCacheLayer without signatures:
For trusted, local-only caches (development):
export TNFR_ALLOW_UNSIGNED_PICKLE=1For production deployments (recommended):
# Before
layer = ShelveCacheLayer("cache.db")
# After (secure)
from tnfr.utils import create_secure_shelve_layer
layer = create_secure_shelve_layer("cache.db")Set environment variable in production:
export TNFR_CACHE_SECRET="$(openssl rand -hex 32)"All project dependencies are continuously monitored for security vulnerabilities using automated tools and processes.
What is pip-audit?
pip-audit is a tool that scans Python dependencies for known security vulnerabilities by checking them against the Python Packaging Advisory Database (PyPA).
Automated Scanning Schedule:
How to Run pip-audit Locally:
# Install pip-audit
pip install pip-audit
# Install project dependencies
pip install -e .[all]
# Scan installed packages in your environment
pip-audit
# Or scan a specific site-packages directory
SITE_PACKAGES=$(python -c "import sysconfig; print(sysconfig.get_path('purelib'))")
pip-audit --path "$SITE_PACKAGES"Understanding pip-audit Results:
When vulnerabilities are found, pip-audit reports:
Security Update Process:
When pip-audit detects vulnerabilities in the CI/CD pipeline:
pip-audit-report artifact from the workflow runpyproject.tomlExample Workflow for Fixing a Vulnerability:
# 1. Review the pip-audit report (download from GitHub Actions artifacts)
cat pip-audit.json
# 2. Update the vulnerable dependency in pyproject.toml
# For example, if networkx 2.6 is vulnerable and 3.0 fixes it:
# Change: "networkx>=2.6,<3.0"
# To: "networkx>=3.0,<4.0"
# 3. Update your local environment
pip install -e .[all]
# 4. Run pip-audit again to verify the fix
pip-audit
# 5. Run the test suite
pytest
# 6. Commit and create a pull request
git add pyproject.toml
git commit -m "fix: update networkx to resolve GHSA-xxxx-xxxx-xxxx"
git push origin fix/update-networkxWhy pip-audit is NOT in pre-commit hooks:
While pip-audit is valuable for CI/CD, it is not included in pre-commit hooks because:
Dependabot:
Automated Dependabot version updates (the .github/dependabot.yml
configuration that opened dependabot/* branches) have been removed to
avoid automated branch/PR noise. Dependabot security updates and
alerts are disabled at the repository settings level. Dependency
vulnerability coverage is provided by the pip-audit CI workflow described
above, which scans installed packages against the PyPA advisory database on
every push/PR to main, on a weekly schedule, and on manual dispatch.
The repository relies on a single automated vulnerability scanner plus notification-only repository safeguards:
The previous CodeQL and Bandit/Semgrep (SAST) CI workflows were removed to
eliminate redundant automated scanning. bandit.yaml and
tools/bandit_to_sarif.py remain available for optional manual local audits
(bandit -r src -c bandit.yaml).
TNFR maintains structural fidelity through canonical invariants that prevent:
These invariants ensure predictable, auditable behavior across all TNFR operations.
The TNFR engine is domain-neutral by design, supporting:
The following components use pickle serialization with documented security warnings:
src/tnfr/utils/cache.py:
ShelveCacheLayer: Persistent file-based cachingRedisCacheLayer: Distributed Redis-based cachingsrc/tnfr/dynamics/dnfr.py:
All pickle usage includes:
# nosec annotations where risk is accepted and documentedThe following Bandit checks are intentionally excluded in bandit.yaml:
We believe in responsible disclosure and will credit security researchers who report vulnerabilities (unless they prefer to remain anonymous).
If you have questions about this security policy, please open a GitHub Discussion or contact the maintainers.
Last Updated: November 2025 Policy Version: 1.0