Sign in Publish
contextetech/

Guardrail: mask API keys and passwords

v1
Contexte Tech

254 publication(s) · 338 uses

Instruction English License: MIT updated 2 days ago
# Guardrail: mask API keys and passwords
code: 1x2ywyz | type: guardrail | language: en | licence: MIT | version: v1
description: Guardrail that masks API keys, tokens, passwords, private keys and connection strings before a text, file or export is sent to an AI. Rules, 14 test cases, code.
page: https://contextetech.com/en/guardrails/mask-secrets-api-keys-1x2ywyz
mcp: connect https://contextetech.com/mcp then call load_resource with code "1x2ywyz" (or ask "load 1x2ywyz")
json: https://contextetech.com/api/resources/contextetech--mask-secrets-api-keys
python: pip install contexte && contexte get 1x2ywyz
citation (required by the licence): contextetech. (2026). Guardrail: mask API keys and passwords (Version 1) [Guardrail]. Contexte Tech. https://contextetech.com/en/guardrails/mask-secrets-api-keys-1x2ywyz

Guardrail that masks API keys, tokens, passwords, private keys and connection strings before a text, file or export is sent to an AI. Rules, 14 test cases, code.

Rules

Mask before sending to the AI any secret that gives access to an account or a service:
- API keys (OpenAI, Anthropic, Mistral, Stripe, AWS…) and access tokens (GitHub, JWT);
- passwords written in clear text (password=…, pwd: …);
- private keys (-----BEGIN … PRIVATE KEY-----);
- credentials inside a URL (postgres://user:password@host).
Let through: placeholder values (YOUR_API_KEY, xxx, <key>), URLs without credentials, order or commit IDs, text about passwords that contains none.
Apply it before pasting a .env file, a database export or logs into an assistant.

Test cases

InputExpected
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLEBlock
token: ghp_000000000000000000000000000000000000Block
ANTHROPIC_API_KEY=sk-ant-00000000000000000000000000000000Block
STRIPE_SECRET=sk_live_0000000000000000000000Block
DATABASE_URL=postgres://admin:S3cretPass@db.internal:5432/appBlock
-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA0000000000000000 -----END RSA PRIVATE KEY-----Block
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwMDAwMDAifQ.0000000000000000000000Block
password = Sunshine2026!Block
Passwords must be at least 12 characters long.Allow
Replace YOUR_API_KEY with the key from your account.Allow
The docs are at https://docs.example.com/api.Allow
Commit a1b2c3d fixes the login bug.Allow
Order #2026-10-458712 has shipped.Allow
Sign in with your usual account.Allow

Code

import re

PATTERNS = {
    "private_key": r"-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----",
    "aws_key": r"\bAKIA[0-9A-Z]{16}\b",
    "github_token": r"\bgh[pousr]_[A-Za-z0-9]{36,}\b",
    "llm_api_key": r"\bsk-(?:ant-|proj-)?[A-Za-z0-9_-]{20,}\b",
    "stripe_key": r"\b[sr]k_(?:live|test)_[A-Za-z0-9]{16,}\b",
    "jwt": r"\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b",
    "url_credentials": r"\b[a-z][a-z0-9+.-]*://[^\s:/@]+:[^\s@/]+@",
    "password_assignment": r"(?i)\b(?:password|passwd|pwd|secret|api_?key|token|passphrase)\s*[:=]\s*[\"']?[^\s\"']{6,}",
}
PLACEHOLDERS = ("xxx", "...", "<", "your", "your_", "example_value")

def mask_secrets(text: str) -> tuple[str, bool]:
    """Replaces secrets with [type masked]; returns the text and True if anything was masked."""
    found = False
    for name, pattern in PATTERNS.items():
        def repl(m):
            nonlocal found
            if any(p in m.group(0).lower() for p in PLACEHOLDERS):
                return m.group(0)
            found = True
            return f"[{name} masked]"
        text = re.sub(pattern, repl, text)
    return text, found

Community

No comments yet. Share your feedback, it will help the next person.