Environment and secret management for tilli products, backed by GitHub secrets.
A Rust CLI tool for managing GitHub repository secrets and environments with audit logging capabilities.
- 🔐 Manage GitHub repository secrets and environments
- 📝 Audit logging for all secret operations
- 🚀 Run commands with environment variables from GitHub environments
- 🏢 Organization-level configuration
- 🔒 Secure secret encryption using libsodium
- 🔑 Secure token storage using system keyring
- 🛡️ Input validation to prevent injection attacks
- ✅ File permission checks and warnings
This version includes significant security enhancements:
- ✅ Fixed command injection vulnerability - Commands are now validated
- ✅ Secure secret input - Secrets are read via stdin (hidden) instead of CLI args
- ✅ Keyring token storage - GitHub tokens stored in system keyring instead of plaintext
- ✅ Path traversal prevention - Environment names are validated
- ✅ HTTPS enforcement - Audit URLs must use HTTPS
- ✅ Audit authentication - Support for audit endpoint authentication
- ✅ Error message sanitization - Sensitive data redacted from errors
- ✅ File permission checks - Warns about insecure file permissions
- ✅ Request timeouts - All HTTP requests have proper timeouts
- ✅ Input validation - All inputs validated to prevent injection
See SECURITY_AUDIT.md for the complete security audit report.
cargo build --release
cp target/release/with-env /usr/local/bin/By default, the tool auto-detects the repository from the current directory's git remote. You can override this with the --repo flag:
# Use current directory's git repository (auto-detect)
with-env list-envs
# Specify repository explicitly (uses organization from config)
with-env --repo my-repo list-envs
# Specify repository with owner
with-env --repo owner/repo list-envsThe --repo flag accepts two formats:
repo- Uses the organization from your config fileowner/repo- Explicitly specifies both owner and repository
This is useful when:
- You're not in a git repository directory
- You want to manage secrets for a different repository
- You're writing scripts that need to work across multiple repositories
First, initialize the tool with your GitHub organization:
# With token stored in system keyring (recommended)
with-env init --org your-organization --token ghp_xxxxxxxxxxxxx
# Without token (will use GITHUB_TOKEN env var)
with-env init --org your-organization
# With audit logging
with-env init --org your-organization --audit-url https://audit.example.com/eventsThis will:
- Create a configuration file at
~/.config/with-env/config.toml - Store your GitHub token securely in the system keyring (if provided)
- Set secure file permissions (0600) automatically
Security Note: Tokens are now stored in your system's secure keyring instead of plaintext files. You can also use the GITHUB_TOKEN environment variable.
List all environments for a repository:
# Current directory's repository
with-env list-envs
# Specific repository
with-env --repo my-repo list-envs
with-env --repo owner/repo list-envsList all secrets in a specific environment:
# Current directory's repository
with-env list-secrets production
# Specific repository
with-env --repo my-repo list-secrets production
with-env --repo owner/repo list-secrets productionNote: Environment names must contain only alphanumeric characters, hyphens, and underscores.
Get metadata about a specific secret (note: values cannot be retrieved via GitHub API):
with-env get-secret production DATABASE_URLNote: Secret names must be uppercase with underscores only (e.g., API_KEY, DATABASE_URL).
Set a secret value for an environment (secure input methods):
# Interactive input (recommended - hides your typing)
with-env set-secret production API_KEY
# You'll be prompted to enter the secret value (hidden)
# From a file
with-env set-secret production API_KEY --from-file secret.txt
# From stdin (for scripts)
echo "my-secret-value" | with-env set-secret production API_KEY
# For a specific repository
with-env --repo my-repo set-secret production API_KEY
with-env --repo owner/repo set-secret production API_KEY --from-file secret.txt- Process lists (
ps aux) - Shell history (
.bash_history) - System logs
Delete a secret from an environment:
with-env delete-secret production OLD_SECRETRun a command with environment variables from a specific environment:
# Current directory's repository
with-env run production npm start
# Shorthand (uses "default" environment)
with-env npm start
# Specific repository
with-env --repo my-repo run production npm start
with-env --repo owner/repo npm startSecurity Note: Commands are validated to prevent injection attacks. Commands with shell metacharacters (|, &, ;, etc.) are rejected.
Since GitHub API doesn't allow retrieving secret values, you need to create local environment files at:
~/.config/with-env/envs/<environment-name>.env
Example ~/.config/with-env/envs/production.env:
DATABASE_URL=postgresql://localhost/mydb
API_KEY=abc123
SECRET_TOKEN=xyz789The tool will automatically:
- Load these variables when running commands
- Check file permissions and warn if insecure
- Validate environment file syntax
Security Best Practice: Set secure permissions on environment files:
chmod 600 ~/.config/with-env/envs/*.envWhen an audit URL is configured, the tool automatically logs the following events:
list_secrets- When secrets are listedget_secret- When secret metadata is retrievedset_secret- When a secret is created or updateddelete_secret- When a secret is deletedrun_with_env- When a command is run with environment variables
Configure audit logging during initialization:
with-env init --org your-org --audit-url https://audit.example.com/eventsSecurity Requirements:
- Audit URL must use HTTPS (enforced)
- Audit endpoint should require authentication (use audit token)
- Audit failures will now cause operations to fail (no silent failures)
Audit events include:
- Timestamp (RFC3339 format)
- Action type
- Repository (owner/name)
- Environment name
- Secret name (if applicable)
- User who performed the action
Example audit event:
{
"timestamp": "2025-11-11T19:10:39Z",
"action": "set_secret",
"repository": "tilli-pro/env",
"environment": "production",
"secret_name": "API_KEY",
"user": "username"
}- Rust 1.70 or later
- GitHub Personal Access Token with appropriate permissions:
reposcope for private repositoriesadmin:orgscope for organization secrets
- Git repository with GitHub remote
The configuration file is stored at ~/.config/with-env/config.toml:
organization = "your-organization"
audit_url = "https://your-audit-server.com/events" # Optional
audit_token = "your-audit-token" # OptionalNote: GitHub tokens are no longer stored in the config file. They are stored securely in the system keyring or provided via GITHUB_TOKEN environment variable.
-
Token Storage
- Use system keyring (preferred):
with-env init --token YOUR_TOKEN - Or use environment variable:
export GITHUB_TOKEN=ghp_xxx - Never commit tokens to version control
- Use system keyring (preferred):
-
File Permissions
- Config file:
chmod 600 ~/.config/with-env/config.toml - Env files:
chmod 600 ~/.config/with-env/envs/*.env - Tool will warn you if permissions are insecure
- Config file:
-
Secret Management
- Always use interactive input or files for secrets
- Never pass secrets as CLI arguments
- Use
--from-filefor automation
-
Audit Logging
- Always use HTTPS for audit URLs
- Configure audit authentication tokens
- Monitor audit logs for suspicious activity
-
Input Validation
- Environment names: only alphanumeric, hyphens, underscores
- Secret names: only uppercase letters, numbers, underscores
- Commands: automatically validated for safety
- ✅ Secrets encrypted using libsodium before GitHub upload
- ✅ Tokens stored in system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service)
- ✅ All inputs validated to prevent injection attacks
- ✅ HTTPS enforced for audit endpoints
- ✅ Request timeouts to prevent hanging
- ✅ Sensitive data redacted from error messages
- ✅ File permission checks with warnings
- ✅ Command validation to prevent shell injection
- GitHub API does not allow retrieving secret values
- Local environment files must be kept in sync manually
- Secrets must be managed in two places:
- GitHub (for CI/CD)
- Local files (for command execution)
cargo buildcargo testcargo fmtcargo clippy -- -D warningsSee SECURITY.md for details on reporting security vulnerabilities.
For the complete security audit and remediation details, see SECURITY_AUDIT.md.
See LICENSE file for details.