Please do not open public issues for security vulnerabilities.
If you discover a security vulnerability, please email security@example.com with:
- Description of the vulnerability
- Steps to reproduce (if applicable)
- Potential impact
- Suggested fix (if available)
We will acknowledge your email within 48 hours and provide a timeline for addressing the issue.
This project uses the following security tools to maintain code quality and security:
- Enabled: Yes
- Frequency:
- On every push to
mainormasterbranches - On every pull request
- Weekly scheduled scan (Sunday 2 AM UTC)
- On every push to
- Purpose: Detect potential security vulnerabilities and code quality issues using GitHub's CodeQL
- Results: Published to GitHub Security tab
- Enabled: Yes
- Checks: Code quality, style, and common issues
- Frequency: On every push and pull request
- Tool: mypy
- Enabled: Yes
- Frequency: On every push and pull request
- Dependencies are managed via
uv - Production dependencies are minimal and pinned in
pyproject.toml - Development dependencies include security-focused linters and type checkers
- Minimum: Python 3.11
- Testing: Python 3.11 and 3.12
- CodeQL: Python 3.11
- Keep Dependencies Updated: Regularly update dependencies to patch security issues
- Use Type Hints: All code uses type hints to catch potential type-related bugs
- Code Review: All changes go through code review via pull requests
- Automated Testing: Comprehensive test suite with 80%+ coverage requirement
- Authentication: Uses OAuth for Anthropic Claude API integration AND password-based auth for network services
The project handles credentials securely:
OAuth Credentials (Claude API):
- Credentials are stored in
~/.claude/.credentials.json(user's home directory) - Credentials are never logged or exposed in output
- Access tokens use OAuth refresh token flow
Agent GitHub Credential (GitHub CLI and git operations):
- Injected per run through the environment as
GH_TOKEN(aliasCLAUDETM_GITHUB_TOKEN) — never read from disk, never taken from a personalghlogin, never persisted by claudetm - Repository-scoped and least privilege, owned by a bot account (e.g.
claudetm[bot]); Git activity is attributed to that disclosed bot identity (GIT_AUTHOR_*/GIT_COMMITTER_*=claudetm[bot]) - Revoked and rotated independently of the Claude credential — rotating one never touches the other
- Never committed, never printed (not in the logs, not by
claudetm doctor, not in an error message), never stored in the image or written into a compose file - Carries no admin scope: CI, required reviews and branch protection stay mandatory, and the credential never bypasses a merge gate
- In a deployment that injects the credential, every
ghinvocation runs withGH_TOKENset and withGH_CONFIG_DIRpointing at a claudetm-owned, empty directory (src/claude_task_master/github/gh_auth.py), so the operator's~/.config/ghis never read and a personal login can never take over an agent run - A container gets the same isolation from the image itself (
GH_CONFIG_DIRis set in theDockerfile), so with no credential injected it has no personal login to fall back to and fails closed, namingGH_TOKEN/CLAUDETM_GITHUB_TOKEN. A developer host with no credential injected keeps using its ownghlogin, unchanged
Password Authentication (Network Services):
- Passwords are hashed using bcrypt with 12 rounds (cost factor)
- Only the hash is stored/configured via
CLAUDETM_PASSWORD_HASH - Plaintext passwords (
CLAUDETM_PASSWORD) are only for development - Password verification uses constant-time comparison to prevent timing attacks
- No persistent storage of API request/response content
- Logs are cleaned automatically (last 10 kept)
- User data is never sent to external services except Anthropic's API
- Webhook payloads are signed with HMAC-SHA256 for integrity verification
Claude Task Master implements password-based Bearer token authentication for network-accessible services:
REST API (claudetm-api):
- All endpoints except
/health,/healthz,/ready,/livez,/docs, and/openapi.jsonrequire authentication - Authentication enforced via
Authorization: Bearer <password>header - FastAPI middleware validates password before request processing
- Returns 401 (Unauthorized) for missing headers
- Returns 403 (Forbidden) for invalid passwords
MCP Server (claudetm-mcp):
- stdio transport: No authentication (local process communication)
- SSE and streamable-http transports: Require Bearer token authentication
- Starlette middleware validates Bearer tokens
- Local connections (localhost) are acceptable without auth
- Remote connections (non-localhost) require authentication
Unified Server (claudetm-server):
- Runs both REST API and MCP server with shared authentication
- Single password configuration applies to all services
- Supports both
CLAUDETM_PASSWORD(plaintext) andCLAUDETM_PASSWORD_HASH(bcrypt)
Passwords are secured using bcrypt, a deliberately slow cryptographic hash function designed to resist brute-force attacks:
Algorithm Details:
- Hashing function: bcrypt with 12 rounds
- Hash format:
$2b$12$...(60 character string) - Password limit: 72 bytes (UTF-8 encoded) - a longer password is rejected, not silently truncated
- Cost factor: 12 rounds (configurable in
src/claude_task_master/auth/password.py)
Verification Method:
- bcrypt's
checkpw()uses constant-time comparison by design - Automatically resistant to timing attacks
- See
src/claude_task_master/auth/password.pyfor implementation
Password Generation:
# Generate bcrypt hash (requires the bcrypt package)
python3 -c "import bcrypt; print(bcrypt.hashpw(b'your-secure-password', bcrypt.gensalt(rounds=12)).decode())"Production Deployment:
- Always use
CLAUDETM_PASSWORD_HASHenvironment variable - Never commit plaintext passwords to version control
- Store hashes in secrets management systems (AWS Secrets Manager, HashiCorp Vault, etc.)
- Use different passwords for dev/staging/production environments
Webhooks use HMAC-SHA256 signatures to authenticate outgoing notifications:
Signature Headers:
X-Webhook-Signature: Simple HMAC-SHA256(secret, payload)X-Webhook-Signature-256: Timestamped HMAC-SHA256(secret, timestamp + "." + payload) - RecommendedX-Webhook-Timestamp: Unix timestamp for freshness validationX-Webhook-Event: Event type identifierX-Webhook-Delivery-Id: Unique delivery identifier
Security Features:
- All webhooks require a shared secret for signature generation
- Timestamped signatures prevent replay attacks (default 5-minute window)
- Constant-time comparison prevents timing attacks
- Raw request body is used for signature calculation (not parsed JSON)
Signature Verification:
- Webhook receivers MUST verify signatures using HMAC-SHA256
- Check timestamp freshness to prevent old replayed webhooks
- Use constant-time string/buffer comparison
- Verified examples provided for Python, Node.js, and TypeScript in
docs/authentication.md
Common Pitfalls:
- ❌ Using parsed JSON instead of raw request body
- ❌ Using simple string comparison (vulnerable to timing attacks)
- ❌ Forgetting the timestamp in signature calculation
- ❌ Not validating timestamp freshness
- ✅ Always use raw bytes and constant-time comparison
- GitHub Actions uses official, verified actions
- No custom shell scripts for sensitive operations
- Secrets are managed through GitHub Secrets
- CodeQL results are uploaded to GitHub's security infrastructure
- Docker images are built and published on release tags only
- Docker image scanning tools can be integrated for vulnerability detection
Docker images published to GitHub Container Registry (ghcr.io):
Build Security:
- Multi-stage build reduces final image size and attack surface
- Base image: Official Python Alpine (lightweight)
- Non-root user execution (UID 1000)
- Minimal dependencies in final image
.dockerignoreexcludes test files, git history, and development artifacts
Runtime Security:
- Images run as non-root user
- No hardcoded secrets in image layers
- Environment variables used for configuration
- Volume mounts for the project directory and the agent's own credential volume — never a personal
~/.claudeor~/.config/gh - Read-only volumes where applicable
Image Distribution:
- Signed image manifests (recommended)
- Version tags and
latesttag for easy updates - Automatic builds on release (v*.. tags)
- Built for multiple architectures (amd64, arm64)
Volume Mounting Best Practices:
- Mount the agent's own credential volume (
claudetm-profiles), never a human's~/.claude: the agent authenticates with a scoped profile, and a personal OAuth file cannot be scoped down or rotated without breaking that person's own login - Mount no personal GitHub configuration: the GitHub credential is injected per run (
GH_TOKEN) andGH_CONFIG_DIRis isolated, so~/.config/ghand~/.gitconfigstay out of the container - Mount project directory as bind mount
- Use named volumes for persistent state
- Ensure proper permissions on mounted directories
-
Use plaintext passwords with
CLAUDETM_PASSWORD- ✅ Acceptable for local development only
- ✅ Simplifies testing and debugging
-
Use stdio MCP transport
- ✅ No network exposure
- ✅ Most secure for development
- ✅ Uses local Claude Desktop
-
Network Security:
- Bind to
localhostonly - Restrict firewall access
- Use VPN for remote development
- Bind to
-
Use bcrypt-hashed passwords with
CLAUDETM_PASSWORD_HASH- ✅ Password never in plaintext
- ✅ Closer to production practices
-
Use SSE transport with authentication
- ✅ Network accessible
- ✅ Password protected
⚠️ Consider TLS with reverse proxy
-
Network Security:
- Bind to internal network only
- Use VPN for external access
- Consider reverse proxy (nginx) for TLS
-
Webhook Security:
- Use HTTPS endpoints only
- Configure unique webhook secrets
- Test signature verification in staging first
-
Use bcrypt-hashed passwords stored in secrets management
- ✅ AWS Secrets Manager, HashiCorp Vault, or cloud provider equivalent
- ✅ Automatic secret rotation
- ✅ Audit trail of access
-
Use SSE transport with TLS
- ✅ Network accessible securely
- ✅ Password protected
- ✅ Encrypted in transit
-
Network Security:
- Use reverse proxy (nginx, Caddy) for TLS termination
- Bind MCP to internal network only
- Implement rate limiting
- Enable WAF (Web Application Firewall)
- Restrict firewall to authorized IPs/VPCs
-
Monitoring & Logging:
- Log all authentication attempts (both success and failure)
- Alert on repeated failed authentication attempts
- Implement centralized logging (CloudWatch, Datadog, ELK)
- Retain logs for compliance (90+ days)
-
Webhook Security:
- Use HTTPS endpoints with valid SSL certificates
- Verify SSL certificates (
verify_ssl=True) - Use unique webhook secrets per receiver
- Rotate webhook secrets regularly
- Monitor webhook delivery failures
- Log webhook events for audit trail
-
Docker Deployment:
- Use specific version tags (not
latest) - Scan images for vulnerabilities before deployment
- Run periodic security updates
- Use container orchestration security features (Kubernetes NetworkPolicy, Pod Security Policy)
- Use specific version tags (not
HTTPS/TLS for REST API:
- Use reverse proxy (nginx, Caddy) to terminate TLS
- Minimum TLS 1.2, recommend 1.3
- Use strong cipher suites
- Implement HSTS (HTTP Strict-Transport-Security) header
WSS for MCP SSE:
- Use secure WebSocket over TLS
- Requires reverse proxy configuration
- Match TLS configuration with REST API
Webhook Delivery:
- Always use HTTPS endpoints
- Verify SSL certificates
- Document expected certificate requirements
Password Hashes:
- Stored as bcrypt hashes (not plaintext)
- Never logged or exposed
- Optionally store in secrets management system
OAuth Credentials:
- Stored in
~/.claude/.credentials.json - File permissions: 600 (owner read/write only)
- Never committed to version control
Webhook Secrets:
- Stored as plaintext in configuration
- Should be stored in secrets management for production
- Use different secrets for different webhooks/environments
This project aims to follow:
- OWASP Top 10 principles
- A07:2021 – Identification and Authentication Failures: Implements Bearer token authentication and bcrypt hashing
- A06:2021 – Vulnerable and Outdated Components: Regular dependency updates and security scanning
- A01:2021 – Broken Access Control: Password authentication and Bearer token validation
- Python Security Best Practices
- PEP 619: Code review practices
- Type hints for catching potential issues
- Regular dependency audits
- GitHub Security Guidelines
- Secret scanning enabled
- CodeQL analysis
- Dependabot for automated updates
- NIST Cybersecurity Framework principles
- Identify: Asset inventory and security scanning
- Protect: Authentication, encryption, and access controls
- Detect: Logging and monitoring
- Respond: Incident response procedures
- Recover: Backup and recovery procedures
See Reporting Security Issues at the top of this document.
Response SLA: 48 hours for initial acknowledgment, 7 days for security patch release.