Skip to main content

fortisec

Tests PyPI Python Downloads Ruff Mypy Coverage License

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.

Metadata

Release files for fortisec 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fortisec 0.1.2
File Size Uploaded
fortisec-0.1.2.tar.gz 2.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for fortisec 0.1.2
File Interpreter ABI Platform
fortisec-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 2.1 MB

Release files / fortisec-0.1.2.tar.gz

Download URL fortisec-0.1.2.tar.gz
Size 2.1 MB
Tags Source
SHA-256 checksum
How to use checksums
0e48820f2f70feea09f08c1a98553a59b0d8ba176a5d0c38b5eecc2801dc10c8
BLAKE2b-256 checksum
How to use checksums
ed2393ccd80a2a75864d99a78a1332eca24877530a5ba2546d22d83549f85fa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release files / fortisec-0.1.2-py3-none-any.whl

Download URL fortisec-0.1.2-py3-none-any.whl
Size 15.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
79506967eb934a421f2da6b7931797355519ad5447a407851bcd9bdcd4efdb23
BLAKE2b-256 checksum
How to use checksums
848e23754e27987b4d4e89c2986b5534c4d3dcf84884a8aa0e8f1dee65ff66ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page