Skip to main content

jsonmask

CI Coverage PyPI version Python versions License: MIT

Deterministic masking and PII redaction for Python dictionaries, JSON payloads, and logs.

Part of the Búho Zurdo ecosystem 🦉


Overview

jsonmask is an extensible security and data privacy library designed to sanitize sensitive information (PII, authentication tokens, credentials) before persisting data or emitting logs.

  • Rule-based Declarative Masking: Path-based targeting with wildcard support (*, [*]).
  • Deterministic Strategies: Full redaction, partial masking, HMAC/SHA-256 token hashing, entropy threshold detection, and custom callbacks.
  • Built-in Presets: Out-of-the-box configurations for emails, credit cards, credentials, SSNs, and phone numbers.
  • Logging Integration: First-class filters for standard Python logging, structlog, and Loguru, plus structured JSON logs.
  • Learning Mode (Dry-Run): Validate rules and generate match reports without mutating original data.
  • CLI Utility: Native command-line tool for stream processing (JSON / NDJSON) in CI/CD pipelines.

Installation

pip install buhozurdo-jsonmask

# Optional: To use third-party logging integrations (structlog, loguru)
pip install "buhozurdo-jsonmask[loggers]"

PyPI Note: The package is published on PyPI under the name buhozurdo-jsonmask. It is imported in Python directly as jsonmask.

For development:

git clone https://github.com/buhozurdo/jsonmask.git
cd jsonmask
pip install -e ".[dev]"

Quick Start

Python API

from jsonmask import mask, Masker

data = {
    "user": {
        "name": "Ana",
        "email": "ana@example.com"
    },
    "token": "eyJhbGciOiJIUzI1NiIsIn..."
}

rules = [
    {"path": "user.email", "strategy": "redact"},
    {"path": "token", "strategy": "hash"}
]

# Quick masking
masked_data = mask(data, rules=rules)
print(masked_data)
# {
#   "user": {"name": "Ana", "email": "****"},
#   "token": "7e2c25d4"
# }

Learning Mode (Dry-Run)

Safely test rules in production without altering the real data by generating a report of what would have been masked.

from jsonmask import mask

# The original data remains completely untouched
data, report = mask(data, rules=rules, learning_mode=True)

print(f"Would have masked {report.total_fields_masked} fields.")
print("Details:", report.to_dict())
from jsonmask import Masker

# Compile rules once for maximum throughput
masker = Masker.from_rules(rules)

for record in records:
    clean_record = masker.mask(record)

Rules can also be loaded directly from YAML or JSON files:

masker = Masker.from_file("rules.yml")
clean_record = masker.mask(record)

Logging Integration

Standard Library Logging Filter

import logging
from jsonmask import Masker, MaskingFilter

rules = [
    {"path": "request.headers.authorization", "strategy": "partial"},
    {"path": "user.email", "strategy": "redact"}
]

masker = Masker.from_rules(rules)

handler = logging.StreamHandler()
handler.addFilter(MaskingFilter(masker))

logger = logging.getLogger("app")
logger.addHandler(handler)
logger.setLevel(logging.INFO)

# Sensitive data passed in `extra` will be sanitized automatically
logger.info("Incoming request", extra={"request": {"headers": {"authorization": "Bearer abc123def456"}}})

structlog Integration

import structlog
from jsonmask import Masker
from jsonmask.logging_integration import structlog_processor

masker = Masker.from_rules([{"path": "user.email", "strategy": "redact"}])

structlog.configure(
    processors=[
        structlog_processor(masker),
        structlog.processors.JSONRenderer()
    ]
)

Loguru Integration

from loguru import logger
from jsonmask import Masker
from jsonmask.logging_integration import loguru_patcher

masker = Masker.from_rules([{"path": "secret", "strategy": "redact"}])
logger = logger.patch(loguru_patcher(masker))

# Secrets within the `extra` dict are automatically intercepted and sanitized
logger.info("Test payload", extra={"secret": "12345"})

Command Line Interface (CLI)

# Process a JSON file
jsonmask mask --input data.json --rules rules.yml --output masked.json

# Process NDJSON streams via stdin
cat data.ndjson | jsonmask mask --rules rules.yml --ndjson > masked.ndjson

# Generate an execution report
jsonmask mask -i data.json -r rules.yml -o out.json --report report.json

# Validate rules file syntax
jsonmask validate -r rules.yml

# List available strategies
jsonmask list-strategies

# Generate a sample rules template
jsonmask generate-rules > rules.template.yml

Rule Definitions

YAML Specification

rules:
  - path: "user.email"
    strategy: "redact"
    replace_with: "****"

  - path: "cards.*.number"
    strategy: "partial"
    keep_start: 4
    keep_end: 4
    mask_char: "*"

  - path: "headers.authorization"
    strategy: "regex"
    pattern: "Bearer\\s+(.+)"
    replace_with: "Bearer ****"

  - path: "token"
    strategy: "entropy"
    entropy_min: 3.5

Path Syntax Reference

Syntax Example Description
Dot notation user.email Nested dictionary access
Wildcard key cards.*.number Any key at target level
Index items[0].id Specific list element index
Wildcard index items[*].secret All elements inside a list

Available Strategies

Strategy Description Key Parameters
redact Replaces value with placeholder replace_with (default ****)
replace Replaces with exact literal replace_with
hash Truncated SHA-256 hash hash_prefix_length, hash_prefix
partial Retains start/end characters keep_start, keep_end, mask_char
regex Matches regex group and masks pattern, replace_with
entropy Evaluates Shannon entropy entropy_min, replace_with

Regulatory Presets

Pre-configured rules are available for common privacy requirements:

from jsonmask import Masker
from jsonmask.presets import combine_presets

rules = combine_presets("email", "credit_card", "token", "password")
masker = Masker.from_rules(rules)

Available presets: email, credit_card, token, ssn, password, phone, pii (all combined).


Known Limitations

  • Recursive Traversal: Traversal relies on recursive tree inspection. Extremely deep data structures (thousands of nested levels) may trigger a RecursionError.
  • JSONPath Scope: Supports dot notation, dictionary wildcards (*), and list indices ([*]). Complex filter expressions (such as [?(@.price > 10)]) are not supported in the standard matcher.

Testing

# Run test suite
pytest

# Run tests with coverage
pytest --cov=src/jsonmask --cov-report=term-missing

Contributing

Contributions are welcome. Please read CONTRIBUTING.md and adhere to Búho Zurdo Engineering Standards.

  1. Fork repository.
  2. Create feature branch (git checkout -b feat/privacy-feature).
  3. Add tests and verify formatting.
  4. Open Pull Request.

License

MIT License. See LICENSE for details.

Metadata

Release files for buhozurdo-jsonmask 0.2.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 buhozurdo-jsonmask 0.2.2
File Size Uploaded
buhozurdo_jsonmask-0.2.2.tar.gz 20.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for buhozurdo-jsonmask 0.2.2
File Interpreter ABI Platform
buhozurdo_jsonmask-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 44.6 kB

Release files / buhozurdo_jsonmask-0.2.2.tar.gz

Download URL buhozurdo_jsonmask-0.2.2.tar.gz
Size 20.4 kB
Tags Source
SHA-256 checksum
How to use checksums
7bae13b15412ad5f2a1bd8df5b91d0768bda32d3cf5a446f951b7ffc430992fb
BLAKE2b-256 checksum
How to use checksums
348e3ba8d3d4f43c60621d0586c9e363fd6ed09d6990fa52e9c08591bbd998c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / buhozurdo_jsonmask-0.2.2-py3-none-any.whl

Download URL buhozurdo_jsonmask-0.2.2-py3-none-any.whl
Size 24.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4e44cd0690f2bdcfb9fc92361f4fc5215ef6c1069c3dfab805c360d064c24e9b
BLAKE2b-256 checksum
How to use checksums
8c407b5e0612a3d9f135196f028f4bef1b4c6eebe8efc0a091fecebfc372f312
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.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