Skip to main content

Lightweight security utilities for validation, hashes, entropy, redaction, headers, and safe paths.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fortisec-0.1.2.tar.gz (2.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fortisec-0.1.2-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

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

Hashes for fortisec-0.1.2.tar.gz
Algorithm Hash digest
SHA256 0e48820f2f70feea09f08c1a98553a59b0d8ba176a5d0c38b5eecc2801dc10c8
MD5 85d8479abfed7781eb4282de393b145c
BLAKE2b-256 ed2393ccd80a2a75864d99a78a1332eca24877530a5ba2546d22d83549f85fa9

See more details on using hashes here.

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

Hashes for fortisec-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 79506967eb934a421f2da6b7931797355519ad5447a407851bcd9bdcd4efdb23
MD5 1be74f1551d015ea6a2caafc9ed8c8ff
BLAKE2b-256 848e23754e27987b4d4e89c2986b5534c4d3dcf84884a8aa0e8f1dee65ff66ad

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page