jsonmask
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, andLoguru, 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 asjsonmask.
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())
Reusable Masker (Recommended for Services)
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.
- Fork repository.
- Create feature branch (
git checkout -b feat/privacy-feature). - Add tests and verify formatting.
- 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)
| File | Size | Uploaded | |
|---|---|---|---|
| buhozurdo_jsonmask-0.2.2.tar.gz | 20.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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