Lightweight security utilities for validation, hashes, entropy, redaction, headers, and safe paths.
Project description
fortisec
A lightweight Python library that helps developers write safer code with ready-to-use security utilities.
Instead of rewriting validation, log redaction, header checks, entropy scoring, and path
safety in every project, fortisec provides well-tested, typed helpers behind a simple
API.
Perfect for:
- Backend APIs
- Security tooling
- DevSecOps automation
- Pentesting scripts
- CI/CD security checks
Features
- Fully typed
- 98% test coverage
- Zero heavy runtime dependencies
- Python 3.10+
- Cross-platform: Linux, Windows, and macOS
- CI tested on Python 3.10, 3.11, 3.12, and 3.13
- MIT licensed
- Fast startup and pure Python implementation
Why fortisec?
| Instead of writing | Use fortisec |
|---|---|
| 40 lines of email and URL regex | validate_email() / validate_url() |
| Manual path traversal checks | safe_join() |
| Custom entropy calculations | entropy_score() |
| Regexes for JWTs and API keys | redact_logs() |
| Manual HTTP header inspection | scan_headers() |
| Hash length lookup tables | identify_hash() |
Installation
pip install fortisec
For local development:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
Quick Start
from fortisec import identify_hash, redact_logs, safe_join, scan_headers, validate_email
print(validate_email("admin@example.com"))
print(identify_hash("d41d8cd98f00b204e9800998ecf8427e"))
clean = redact_logs("Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.payload.signature")
print(clean)
path = safe_join("/srv/app/uploads", "user/avatar.png")
print(path)
result = scan_headers("https://example.com")
print(result.score)
print(result.missing)
Terminal Output
Redact secrets before logs leave your application:
>>> from fortisec import redact_logs
>>> log = """
... Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.payload.signature
... Email: admin@example.com
... OpenAI Key: sk-proj-1234567890abcdefghijklmnopqrstuvwxyz
... """
>>> print(redact_logs(log))
Authorization: Bearer ********
Email: ********
OpenAI Key: ********
Scan security headers:
Security Score: 82/100
✓ Strict-Transport-Security
✓ X-Frame-Options
✓ X-Content-Type-Options
✓ Referrer-Policy
✗ Content-Security-Policy
✗ Permissions-Policy
Recommendation: Add a Content-Security-Policy header.
CLI
fortisec also ships with a small command-line interface for quick checks:
fortisec validate-email admin@example.com
✔ Valid
fortisec hash d41d8cd98f00b204e9800998ecf8427e
MD5
NTLM
LM
fortisec headers https://example.com
fortisec redact "Authorization: Bearer secret-token from admin@example.com"
Authorization: Bearer ******** from ********
Real Examples
Flask uploads
from flask import request
from fortisec import safe_join
UPLOAD_DIR = "/srv/app/uploads"
filename = request.files["avatar"].filename
path = safe_join(UPLOAD_DIR, filename)
request.files["avatar"].save(path)
Logging
import logging
from fortisec import redact_logs
logger = logging.getLogger(__name__)
logger.info(redact_logs(str(request.headers)))
CI checks
from fortisec import validate_url
for url in urls_from_config:
if not validate_url(url):
raise ValueError(f"Invalid URL in config: {url}")
API Overview
Validators
from fortisec.validators import (
validate_cidr,
validate_domain,
validate_email,
validate_hostname,
validate_ip,
validate_ipv4,
validate_ipv6,
validate_port,
validate_url,
)
All validators return True or False and do not raise for invalid input.
Hashes
from fortisec.hashes import hash_length, identify_hash, is_probably_hash
identify_hash() returns possible matches such as ["MD5", "NTLM", "LM"],
["SHA1", "RIPEMD160"], or [].
Entropy
from fortisec.entropy import entropy_score, is_high_entropy, shannon_entropy
Useful for identifying API keys, JWT segments, random tokens, and passwords.
Redaction
from fortisec.redact import redact_logs
redact_logs(
"Authorization: Bearer secret-token from admin@example.com",
redact_ip=True,
placeholder="***",
)
Built-in redaction covers JWTs, AWS keys, GitHub PATs, OpenAI keys, Google API keys, bearer tokens, email addresses, credit cards, IPv4 addresses, and IPv6 addresses. You can also pass custom regex patterns.
HTTP Headers
from fortisec.headers import scan_headers
result = scan_headers("https://example.com")
print(result.score)
print(result.to_json())
print(result.pretty_print())
Safe Paths
from fortisec.paths import safe_join
safe_path = safe_join("/srv/uploads", "images", "avatar.png")
Traversal attempts such as ../../../etc/passwd raise PathTraversalError.
Quality
python -m pytest
python -m ruff check .
python -m black --check .
python -m mypy src/fortisec
python -m build
Publishing
Build and upload:
python -m pip install -U build twine
python -m build
python -m twine check dist/*
python -m twine upload dist/*
Before uploading, update project.urls in pyproject.toml and confirm the package
name is available on PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fortisec-0.1.2.tar.gz.
File metadata
- Download URL: fortisec-0.1.2.tar.gz
- Upload date:
- Size: 2.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e48820f2f70feea09f08c1a98553a59b0d8ba176a5d0c38b5eecc2801dc10c8
|
|
| MD5 |
85d8479abfed7781eb4282de393b145c
|
|
| BLAKE2b-256 |
ed2393ccd80a2a75864d99a78a1332eca24877530a5ba2546d22d83549f85fa9
|
File details
Details for the file fortisec-0.1.2-py3-none-any.whl.
File metadata
- Download URL: fortisec-0.1.2-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79506967eb934a421f2da6b7931797355519ad5447a407851bcd9bdcd4efdb23
|
|
| MD5 |
1be74f1551d015ea6a2caafc9ed8c8ff
|
|
| BLAKE2b-256 |
848e23754e27987b4d4e89c2986b5534c4d3dcf84884a8aa0e8f1dee65ff66ad
|