Skip to content
Back to skills

Langfuse Security Basics

ASecurity

Implement Langfuse security best practices for API keys and data privacy. Use when securing Langfuse integration, protecting API keys, or implementing data privacy controls for LLM observability. Trigger with phrases like "langfuse security", "langfuse API key security", "langfuse data privacy", "secure langfuse", "langfuse PII".

  • 4 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 10, 2026
securitypythondockerapisecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 10, 2026

npx -y skills add micsapp/micstec-skills --skill langfuse-security-basics --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Langfuse Security Basics?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Langfuse Security Basics
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/micsapp-langfuse-security-basics/badge)](https://www.skillsdirectory.com/skills/micsapp-langfuse-security-basics)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: langfuse-security-basics
description: |
  Implement Langfuse security best practices for API keys and data privacy.
  Use when securing Langfuse integration, protecting API keys,
  or implementing data privacy controls for LLM observability.
  Trigger with phrases like "langfuse security", "langfuse API key security",
  "langfuse data privacy", "secure langfuse", "langfuse PII".
allowed-tools: Read, Write, Edit
version: 1.0.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
compatible-with: claude-code, codex, openclaw
---
# Langfuse Security Basics

## Overview
Security practices for Langfuse LLM observability integrations. Langfuse captures prompts, completions, and metadata from LLM calls -- making data privacy and access control critical since traced data may contain PII.

## Prerequisites
- Langfuse instance (cloud or self-hosted)
- API keys provisioned
- Understanding of data privacy requirements

## Instructions

### Step 1: Credential Separation

Langfuse uses separate public and secret keys. Only the secret key should be protected.

```python
import os

# Public key: safe for client-side (identifies project)
LANGFUSE_PUBLIC_KEY = os.environ["LANGFUSE_PUBLIC_KEY"]

# Secret key: NEVER expose (grants write access to traces)
LANGFUSE_SECRET_KEY = os.environ["LANGFUSE_SECRET_KEY"]

# Host (for self-hosted)
LANGFUSE_HOST = os.environ.get("LANGFUSE_HOST", "https://cloud.langfuse.com")

# Validate on startup
assert LANGFUSE_SECRET_KEY, "LANGFUSE_SECRET_KEY required"
assert not LANGFUSE_SECRET_KEY.startswith("pk-"), "Using public key as secret key!"
```

### Step 2: PII Scrubbing Before Tracing

Langfuse stores everything you send. Scrub PII before tracing.

```python
import re
from langfuse import Langfuse

langfuse = Langfuse()

def scrub_pii(text: str) -> str:
    text = re.sub(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b', '[EMAIL]', text, flags=re.IGNORECASE)
    text = re.sub(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', '[PHONE]', text)
    text = re.sub(r'\b\d{3}-\d{2}-\d{4}\b', '[SSN]', text)
    return text

def traced_llm_call(prompt: str, user_id: str):
    trace = langfuse.trace(
        name="llm-call",
        user_id=user_id,  # OK: user IDs are fine
        input=scrub_pii(prompt),  # scrub before tracing
    )
    response = call_llm(prompt)  # send original to LLM
    trace.update(output=scrub_pii(response))  # scrub output too
    return response
```

### Step 3: Access Control for Self-Hosted

```yaml
# docker-compose.yml for self-hosted Langfuse
services:
  langfuse:
    image: langfuse/langfuse:latest
    environment:
      - AUTH_DISABLE_SIGNUP=true           # prevent open registration
      - AUTH_DOMAINS_WITH_SSO_ENFORCEMENT=company.com  # require SSO
      - LANGFUSE_DEFAULT_PROJECT_ROLE=VIEWER  # least privilege default
      - ENCRYPTION_KEY=${ENCRYPTION_KEY}   # encrypt data at rest
```

### Step 4: Trace Data Retention

Configure automatic cleanup of old traces to limit exposure.

```python
# Self-hosted: set retention via environment
# LANGFUSE_RETENTION_DAYS=90

# Cloud: use API to delete old traces
from datetime import datetime, timedelta

def cleanup_old_traces(langfuse: Langfuse, max_age_days: int = 90):
    cutoff = datetime.now() - timedelta(days=max_age_days)
    # Use Langfuse API to list and delete traces older than cutoff
    # Implement based on your Langfuse version's API
    print(f"Cleaning traces older than {cutoff.isoformat()}")
```

## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| PII in traces | Not scrubbing before trace | Apply PII scrubbing to inputs/outputs |
| Secret key leaked | Wrong key in client code | Validate key prefix (sk- vs pk-) |
| Unauthorized access | No SSO enforcement | Enable `AUTH_DOMAINS_WITH_SSO_ENFORCEMENT` |
| Data accumulation | No retention policy | Set `LANGFUSE_RETENTION_DAYS` |

## Examples

### Secure Initialization
```python
from langfuse import Langfuse
langfuse = Langfuse(
    public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
    secret_key=os.environ["LANGFUSE_SECRET_KEY"],
    host=os.environ.get("LANGFUSE_HOST", "https://cloud.langfuse.com")
)
```

## Resources
- [Langfuse Security Docs](https://langfuse.com/docs/data-security-privacy)
- [Self-Hosting Guide](https://langfuse.com/docs/deployment/self-host)

## Output

- Configuration files or code changes applied to the project
- Validation report confirming correct implementation
- Summary of changes made and their rationale

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.