Claude Code Plugins

Community-maintained marketplace

Feedback

fnox-security-best-practices

@TheBushidoCollective/han
38
0

Use when implementing secure secrets management with Fnox. Covers encryption, key management, access control, and security hardening.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name fnox-security-best-practices
description Use when implementing secure secrets management with Fnox. Covers encryption, key management, access control, and security hardening.
allowed-tools Read, Write, Edit, Bash, Grep, Glob

Fnox - Security Best Practices

Security guidelines and best practices for managing secrets with Fnox.

Encryption Fundamentals

Always Encrypt Sensitive Data

# Bad: Plain text secrets committed to git
[secrets]
DATABASE_PASSWORD = "super-secret-password"
API_KEY = "sk-live-12345"

# Good: Encrypted secrets
[providers.age]
type = "age"
public_keys = ["age1ql3z..."]

[secrets]
DATABASE_PASSWORD = { provider = "age", value = "age[...]" }
API_KEY = { provider = "age", value = "age[...]" }

Use Strong Encryption

# Good: age encryption (modern, secure)
age-keygen -o ~/.config/fnox/keys/identity.txt

# Good: Cloud KMS (managed encryption)
[providers.kms]
type = "aws-kms"
key_id = "arn:aws:kms:us-east-1:..."

Key Management

Protect Private Keys

# Store age private key securely
chmod 600 ~/.config/fnox/keys/identity.txt

# Never commit private keys
echo "*.txt" >> ~/.config/fnox/keys/.gitignore

Separate Public and Private Keys

# fnox.toml (committed) - public keys only
[providers.age]
type = "age"
public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]

# fnox.local.toml (gitignored) - private keys
[providers.age]
identity = "~/.config/fnox/keys/identity.txt"

Rotate Keys Regularly

# Generate new age key
age-keygen -o ~/.config/fnox/keys/identity-2025.txt

# Re-encrypt all secrets with new key
fnox get --all | fnox set --provider age-new

Access Control

Use Least Privilege

# Good: Separate secrets by environment
[profiles.production]
[profiles.production.providers.prod-secrets]
type = "aws-sm"
region = "us-east-1"

[profiles.production.secrets]
DATABASE_URL = { provider = "prod-secrets", value = "prod/db" }

[profiles.development]
[profiles.development.secrets]
DATABASE_URL = "postgresql://localhost/dev"  # Non-sensitive

Team Access Control

# Multiple age recipients for team
[providers.age]
type = "age"
public_keys = [
  "age1ql3z...",  # Alice (admin)
  "age1qw4r...",  # Bob (developer)
  # Don't include contractors or temporary team members
]

Role-Based Secrets

# Backend secrets
[providers.backend]
type = "aws-sm"
region = "us-east-1"

# Frontend secrets (different access level)
[providers.frontend]
type = "aws-sm"
region = "us-east-1"

[secrets]
BACKEND_DB_PASSWORD = { provider = "backend", value = "backend/db-pass" }
FRONTEND_API_ENDPOINT = { provider = "frontend", value = "frontend/api-url" }

Git Security

Never Commit Sensitive Data

# .gitignore
fnox.local.toml
*.age-identity.txt
*.key
*.pem
.env

Audit Git History

# Check for accidentally committed secrets
git log -p | grep -i "password\|secret\|key"

# Remove secrets from git history (if found)
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch fnox.local.toml' \
  --prune-empty --tag-name-filter cat -- --all

Use Pre-Commit Hooks

# .git/hooks/pre-commit
#!/bin/bash
if git diff --cached --name-only | grep -q "fnox.local.toml"; then
  echo "Error: Attempting to commit fnox.local.toml"
  exit 1
fi

# Check for plain text secrets
if git diff --cached | grep -q "password.*=.*\"[^a]"; then
  echo "Warning: Possible plain text password detected"
  exit 1
fi

Environment Separation

Separate Development and Production

# fnox.toml (development)
[secrets]
DATABASE_URL = "postgresql://localhost/dev"
DEBUG = "true"

# fnox.production.toml (production secrets)
[providers.prod]
type = "aws-sm"
region = "us-east-1"

[secrets]
DATABASE_URL = { provider = "prod", value = "prod/db-url" }
DEBUG = "false"

Use Profiles for Environments

# Development
fnox exec -- node app.js

# Staging
FNOX_PROFILE=staging fnox exec -- node app.js

# Production
FNOX_PROFILE=production fnox exec -- node app.js

Cloud Provider Security

AWS Best Practices

# Use IAM roles instead of access keys
[providers.aws-sm]
type = "aws-sm"
region = "us-east-1"
# No access_key_id or secret_access_key
# Uses IAM role or AWS credentials chain

# Restrict by resource tags
[providers.aws-sm]
type = "aws-sm"
region = "us-east-1"
# Ensure IAM policy limits access to specific secrets

Azure Best Practices

# Use managed identity
[providers.azure]
type = "azure-kv"
vault_url = "https://my-vault.vault.azure.net"
# Authentication via Azure managed identity

GCP Best Practices

# Use service account with minimal permissions
[providers.gcp]
type = "gcp-sm"
project_id = "my-project"
# Service account with only secretmanager.versions.access

Audit and Monitoring

Log Secret Access

# Enable audit logging in cloud providers
# AWS CloudTrail for Secrets Manager
# Azure Monitor for Key Vault
# GCP Cloud Audit Logs for Secret Manager

Monitor for Anomalies

# Check which secrets are accessed
fnox list

# Verify provider configuration
fnox doctor

# Test provider connectivity
fnox provider test aws-sm

Regular Security Audits

# List all secrets
fnox list

# Verify encryption status
fnox doctor

# Check for plain text secrets
grep -r "password.*=.*\"[^a]" fnox.toml

Secrets Lifecycle

Rotate Secrets Regularly

# Generate new secret
NEW_PASSWORD=$(openssl rand -base64 32)

# Update in fnox
echo "$NEW_PASSWORD" | fnox set DATABASE_PASSWORD

# Update in actual service (database, API, etc.)
# Then verify application still works

Remove Obsolete Secrets

# Remove unused secret
fnox unset OLD_API_KEY

# Clean up from cloud provider
aws secretsmanager delete-secret --secret-id old/api-key

Document Secret Purpose

[secrets]
STRIPE_API_KEY = {
  provider = "age",
  value = "age[...]",
  description = "Stripe secret key for payment processing. Rotate quarterly."
}

DATABASE_PASSWORD = {
  provider = "aws-sm",
  value = "prod/db-password",
  description = "PostgreSQL master password. Last rotated: 2025-01-01"
}

CI/CD Security

Use Dedicated CI Keys

# Separate age key for CI/CD
[providers.age]
type = "age"
public_keys = [
  "age1ql3z...",  # Developer key
  "age1ci3d...",  # CI/CD key (limited access)
]

Restrict CI Secret Access

# .github/workflows/deploy.yml
env:
  FNOX_PROFILE: production
  # Use GitHub secrets for age identity
  AGE_IDENTITY: ${{ secrets.AGE_IDENTITY }}

steps:
  - name: Load secrets
    run: |
      echo "$AGE_IDENTITY" > /tmp/identity.txt
      chmod 600 /tmp/identity.txt
      fnox exec -- ./deploy.sh
      rm /tmp/identity.txt

Minimal CI Permissions

# CI profile with minimal secrets
[profiles.ci]
[profiles.ci.secrets]
DEPLOY_TOKEN = { provider = "age", value = "age[...]" }
# Don't include database passwords or API keys

Best Practices Summary

DO

✅ Always encrypt sensitive secrets ✅ Use strong encryption (age, KMS) ✅ Store private keys securely ✅ Separate dev and prod secrets ✅ Use .gitignore for local overrides ✅ Rotate keys and secrets regularly ✅ Use cloud provider managed identities ✅ Audit secret access ✅ Document secret purpose ✅ Use profiles for environments

DON'T

❌ Never commit private keys ❌ Never use plain text for sensitive data ❌ Don't share private keys between team members ❌ Don't hardcode credentials ❌ Don't mix dev and prod secrets ❌ Don't skip encryption in production ❌ Don't ignore security warnings ❌ Don't use weak passwords as secrets

Common Threats and Mitigations

Threat: Accidental Commit

# Mitigation: Pre-commit hooks
cat > .git/hooks/pre-commit <<'EOF'
#!/bin/bash
if git diff --cached fnox.local.toml > /dev/null; then
  echo "Error: fnox.local.toml should not be committed"
  exit 1
fi
EOF
chmod +x .git/hooks/pre-commit

Threat: Key Compromise

# Mitigation: Immediate rotation
# 1. Generate new key
age-keygen -o ~/.config/fnox/keys/identity-new.txt

# 2. Re-encrypt all secrets
fnox get --all | fnox set --provider age-new

# 3. Update public keys
# 4. Revoke old key

Threat: Unauthorized Access

# Mitigation: Use cloud provider IAM
[providers.aws-sm]
type = "aws-sm"
region = "us-east-1"
# Restrict with IAM policies:
# - Limit to specific secret ARNs
# - Require MFA
# - Restrict by IP range

Related Skills

  • configuration: Managing fnox.toml securely
  • providers: Choosing secure providers