Skip to content

Security: cachekit-io/cachekit-py

SECURITY.md

Security Policy

Comprehensive security documentation for the cachekit Python SDK.


Table of Contents


Supported Versions

Version Supported
0.4.x βœ…
0.3.x βœ…
< 0.3 ❌

Note

As a young project, we maintain security support for the latest release only. Once we reach 1.0.0, we will establish a longer-term LTS policy.


Reporting a Vulnerability

Important

We take security seriously. If you discover a security vulnerability, please report it responsibly.

Reporting Channels

Channel Use Case
security@cachekit.io Preferred for sensitive issues
GitHub Security Advisory Public vulnerability reports

What to Include

  • Description of the vulnerability
  • Steps to reproduce
  • Affected versions
  • Potential impact
  • Suggested fix (if available)

Response Timeline

Stage Timeline
Initial Response 48 hours
Status Update 7 days
Fix Timeline Varies by severity
πŸ“‹ Disclosure Policy

We follow coordinated disclosure:

  1. Acknowledge receipt within 48 hours
  2. Confirm vulnerability and determine severity
  3. Develop and test fix
  4. Release security patch
  5. Public disclosure after patch availability (coordinated with reporter)

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     cachekit Python SDK                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚   @cache     β”‚  β”‚   @cache     β”‚  β”‚   Redis/CachekitIO    β”‚  β”‚
β”‚  β”‚  Decorator   β”‚  β”‚   .secure    β”‚  β”‚      Backend          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                 β”‚                      β”‚              β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                  β”‚                                              β”‚
β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”                                     β”‚
β”‚         β”‚   PyO3 FFI      β”‚  ◄── This repo                      β”‚
β”‚         β”‚   Wrapper       β”‚                                     β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚   cachekit-core   β”‚  ◄── Separate crate
         β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
         β”‚  β”‚ AES-256-GCM β”‚  β”‚
         β”‚  β”‚ LZ4 Compressβ”‚  β”‚
         β”‚  β”‚ xxHash3     β”‚  β”‚
         β”‚  β”‚ HKDF        β”‚  β”‚
         β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Component Responsibility
cachekit-core (Rust) Compression, checksums, encryption, formal verification
cachekit SDK (this repo) PyO3 FFI wrapper, decorators, Redis backend, configuration

Tip

For comprehensive security details about core cryptographic operations, see cachekit-core SECURITY.md.

This document focuses on Python SDK-specific security: FFI boundary, configuration, and Python-layer tooling.


Python SDK Security Features

No Untrusted Deserialization

Caution

cachekit NEVER uses Python's pickle module due to arbitrary code execution risks (CWE-502).

We use MessagePack (safe binary serialization) with type preservation via schema metadata.

- import pickle  # NEVER - arbitrary code execution
+ import msgpack  # Safe binary serialization

Zero-Knowledge Encryption

When enabled via @cache.secure, client-side AES-256-GCM encryption ensures the server never sees plaintext:

Property Guarantee
Encryption timing Before data touches Redis
Server visibility Opaque ciphertext only
Key derivation HKDF with per-tenant salts
Authentication GCM tags prevent tampering
Compliance GDPR/HIPAA/PCI-DSS ready
πŸ” Master Key Security
Requirement Implementation
Key size Minimum 32 bytes (256 bits)
Configuration CACHEKIT_MASTER_KEY env var
Logging Never exposed in logs/errors
Derivation HKDF with unique tenant salts
⚑ L1 Cache Behavior
Mode L1 Storage L2 Storage Performance
@cache Plaintext Plaintext ~50ns L1 / ~2-7ms L2
@cache.secure Encrypted Encrypted ~50ns L1 / ~2-7ms L2

Both tiers store encrypted bytes when encryption is enabled (encrypt-at-rest everywhere). Decryption happens at read time only, minimizing plaintext exposure.

Note

All cryptographic operations are implemented in cachekit-core. See cachekit-core SECURITY.md for AES-256-GCM, HKDF, and formal verification details.

Sensitive Configuration Masking

All sensitive values are automatically masked:

Context Masked
Structured logs βœ…
Error messages βœ…
Health endpoints βœ…
Monitoring output βœ…

Implementation: Uses pydantic-settings with SecretStr for automatic redaction.

SSRF Protection

When using @cache.io (CachekitIOBackend), the SDK includes built-in Server-Side Request Forgery (SSRF) protection. Custom API URLs are blocked by default - only api.cachekit.io and its subdomains are permitted.

See SSRF Protection for full details, including custom host configuration for development environments.

Lock Token Transport (CWE-532)

The distributed-lock capability token (lock_id) is sent in the X-CacheKit-Lock-Id request header when releasing a lock (DELETE /v1/cache/{key}/lock), never in the URL query string. Query strings are routinely captured by access logs, proxy/CDN logs, and OpenTelemetry http.url spans (CWE-532); a leaked token could be replayed to release a lock within its short TTL. The CacheKit SaaS backend dual-reads the header and the legacy ?lock_id= query during migration, preferring the header (removed in protocol 2.0).

Cache-Key Path Encoding (CWE-22)

Custom @cache(key=...) values are percent-encoded before they reach the CachekitIO request path, so a key can only ever address /v1/cache/{key} and never a different api.cachekit.io endpoint. Without encoding, ?/# would be split into a query/fragment and a /-bearing key would introduce extra path segments, both escaping the cache namespace with the application's bearer token; httpx normalizes these client-side before the request leaves the process (CWE-22), so the SaaS-side key validator never sees them. quote(key, safe="") encodes every reserved character (/ β†’ %2F, ? β†’ %3F, # β†’ %23, % β†’ %25), collapsing the whole key into one inert path segment.

RFC-3986 marks . as unreserved, so quote (like cachekit-ts encodeURIComponent and cachekit-rs urlencoding::encode) leaves it raw β€” but a key of exactly . or .. is still a live dot-segment that httpx collapses: .. β†’ GET /v1, and on the sub-resource routes ../ttl β†’ GET /v1/ttl, ../lock β†’ GET /v1/lock, reaching a different route with the bearer token. The encoder special-cases an all-dot segment (.. β†’ %2E%2E) so it can no longer collapse; only a segment that is entirely dots is affected (a:.. is untouched), so canonical keys are unchanged.

Encode-once matches the SaaS validator's single decode, so a canonical key round-trips byte-for-byte. Python's quote(key, safe="") is byte-identical to cachekit-rs urlencoding::encode, and resolves to the same server-side key as cachekit-ts encodeURIComponent after that single decode, so cross-SDK cache lookups still coincide.


FFI Boundary Security

Important

The PyO3 FFI boundary between Python and Rust is security-critical.

Memory Safety

Guarantee Mechanism
Type safety PyO3's compile-time type system
No unsafe serialization MessagePack only (no pickle)
Buffer validation Inputs validated before Rust calls
Panic handling Rust panics β†’ Python exceptions

Thread Safety

Guarantee Mechanism
GIL protection All FFI calls acquire GIL
Rust synchronization Send/Sync guarantees in cachekit-core
TSan validation PyO3 false positives documented

Warning

TSan suppressions in rust/tsan_suppressions.txt only cover PyO3/Python runtime false positives. Any data races in cachekit code are real bugs and must be fixed.


Dependency Security

Rust Dependencies

Tool Purpose Config
cargo-deny License + vulnerability scanning deny.toml
cargo-audit CVE scanning against RustSec Advisory Database .github/workflows/security-fast.yml (inline ignore list)
πŸ“‹ Policy Details

Allowed licenses: MIT, Apache-2.0, BSD-3-Clause

Denied licenses: GPL (all variants)

Vulnerability scanning: RustSec Advisory Database

Note

Core dependencies (ring / aes-gcm for AES-256-GCM, lz4_flex, xxhash-rust, rmp-serde, hkdf, sha2) are audited in cachekit-core. See cachekit-core dependency docs. blake3 is not a cachekit-core dependency: it is a cachekit-py (Python) dependency used for cache-key hashing in src/cachekit/hash_utils.py, audited in this repo's own Python dependencies below.

Python Dependencies

Tool Purpose Command
pip-audit CVE scanning make security-audit

CI/CD Security

Tiered Security Checks

Tier Timing Trigger Checks
Fast < 3 min Every PR cargo-audit, cargo-deny, clippy, machete, pip-audit
Medium < 15 min Post-merge cargo-geiger (<5% unsafe), semver-checks
Deep < 2 hr Nightly Sanitizers (ASan, TSan, MSan), security report
πŸ“ Workflow Files
Tier Workflow
Fast .github/workflows/security-fast.yml
Medium .github/workflows/security-medium.yml
Deep .github/workflows/security-deep.yml

Tip

Kani formal verification and cargo-fuzz run in cachekit-core CI. This SDK relies on cachekit-core's verification results.

Local Development

# One-time setup
make security-install

# Quick checks (< 3 min)
make security-fast

# Comprehensive (< 15 min)
make security-medium

# Python dependencies
make security-audit

# Generate report
make security-report

Reports are archived in reports/security/ for compliance and audit trails.


Known Limitations

Cryptographic Security

Note

This SDK does not implement cryptography directly. All cryptographic operations are in cachekit-core.

SDK Responsibilities:

  • Safely calling cachekit-core via FFI
  • Protecting master keys in memory (SecretStr)
  • Preventing key leakage in logs/errors
  • Validating inputs before FFI calls

For cryptographic guarantees, see:

CI Workflow Validation

⚠️ Validation Status

Validated:

  • Workflow syntax
  • Job structure and dependencies
  • Tool installation procedures
  • Trigger configuration

Requires validation on first PR:

  • Actual timing (fast < 3min, medium < 15min, deep < 2h)
  • Sanitizer execution on Linux runners
  • Caching effectiveness
  • Resource limits and timeouts

Version Policy

Release Type Scope Breaking Changes
Patch (0.1.x) Security fixes ❌
Minor (0.x.0) New features ❌
Major (x.0.0) Breaking changes βœ…

Note

Pre-1.0: Minor versions may include breaking changes.

Security patches are backported to the latest supported version.


Security Roadmap

Quarter Milestone
Q2 2026 Add Hypothesis fuzzing for Python layer
Q3 2026 Third-party security audit (SDK + FFI boundary)
Q4 2026 SLSA Level 3 compliance

Contact

Purpose Channel
Security issues security@cachekit.io
General issues GitHub Issues
Maintainers GitHub Repository

Acknowledgments

We appreciate responsible disclosure from the security community. Security researchers who report valid vulnerabilities will be acknowledged in release notes (with permission).


Report Vulnerability Β· cachekit-core Security Β· GitHub

Last Updated: 2025-12-09

There aren't any published security advisories