Experimental feature that prevents LLM agents from seeing raw secrets in your project files and environment variables.
When enabled, Construct creates an isolated workspace where:
- Project files containing secrets are redacted (values replaced with
CONSTRUCT_REDACTED_<HASH>) - Environment variables with secret names are masked for the agent
- The agent cannot access raw secrets, only the masked versions
- Your original project files remain unchanged
Core guarantee: When hide-secrets mode is enabled, the agent process must not have direct access to raw project secrets by default.
This protects against:
- Agents reading
.envfiles and printing secrets - Agents copying credentials to output
- Accidental leakage in logs and terminal output
- Tools that display environment variables
Set the environment variable:
export CONSTRUCT_EXPERIMENT_HIDE_SECRETS=1[security]
hide_secrets = true
hide_secrets_mask_style = "hash"construct claude "Help me debug my API code"The agent will now see redacted secrets instead of real values.
[security]
# Master switch (requires CONSTRUCT_EXPERIMENT_HIDE_SECRETS=1)
hide_secrets = false
# Mask style: "hash" (default) or "fixed"
hide_secrets_mask_style = "hash"
# Emit session report after each run
hide_secrets_report = true
# Hide .git directory (recommended)
hide_git_dir = trueHash (default): Unique placeholder per secret
Before: DATABASE_URL=postgresql://user:pass123@localhost/db
After: DATABASE_URL=CONSTRUCT_REDACTED_A1B2C3D4
Better for debugging - you can identify which secret was redacted.
Fixed: Static placeholder
Before: DATABASE_URL=postgresql://user:pass123@localhost/db
After: DATABASE_URL=CONSTRUCT_REDACTED
Maximum secrecy - all secrets look identical.
# Always scan these files for secrets, even if they don't match heuristics
hide_secrets_deny_paths = [
"**/secrets.yml",
"**/.env.local",
"config/prod/*.yaml"
]# Use ONLY for files that tools must read directly
hide_secrets_allow_paths = [
"~/.aws/credentials", # AWS CLI needs this
"config/tool-specific-secrets.yaml"
]Warning: This breaks the security model for allowlisted files. Use sparingly.
# These env vars will be visible to agents in raw form
hide_secrets_passthrough_vars = [
"PUBLIC_API_URL",
"APP_ENV",
"NON_SECRET_CONFIG"
]Construct scans files matching these patterns:
.env,.env.**.pem,*.key,*.p12,*.pfx,id_rsa,id_ed25519.npmrc,.pypirc,.netrc,.dockercfg*.tfvars,*.tfvars.jsonapplication*.yml,application*.yaml,application*.propertiesconfig*.json,config*.yaml,config*.yml,config*.toml,*.ini
Files are scanned for keys containing:
api_key,apikey,api-keysecret,password,passwd,pwdtoken,auth,authorizationdsn,connection_string,connection-stringprivate_key,private-key,privatekeycredential,cert,certificate
Construct also detects:
- GitHub tokens:
ghp_ - OpenAI keys:
sk- - Anthropic keys:
sk-ant- - AWS keys:
AKIA - Stripe keys:
sk_live_/pk_live_ - Slack tokens:
xoxb- - Private key blocks:
-----BEGIN [A-Z]+ PRIVATE KEY-----
Debugging API code without exposing API keys
construct claude "Debug why my API calls are failing"Code review of authentication logic
construct claude "Review my authentication flow for security issues"Working with sensitive projects
construct claude "Help me refactor this database migration code"When tools need direct secret access
- AWS CLI (
~/.aws/credentials) - kubectl (
~/.kube/config) - Tools that read credentials files directly
Use hide_secrets_allow_paths for these files, or disable hide-secrets mode entirely.
When agents need to make authenticated API calls
- This is handled via the provider proxy (future enhancement)
- For now, use standard mode for workflows requiring API calls
In hide-secrets mode:
- Agent runs in an isolated workspace (OverlayFS on Linux, APFS clones on macOS)
- Agent writes do not persist to your real project
- Changes remain in session workspace only
- On session end, you'll see a warning if there are changes
Example output:
⚠️ Hide-secrets session ended with changes
Files changed: 3
Session directory: ~/.config/construct-cli/security/sessions/abc123
Changes were NOT written to the real project.
Review changes in the session directory.
Sessions are automatically cleaned up:
- Unchanged sessions: Deleted immediately
- Changed sessions: Retained for manual review
- Crashed sessions: Detected via PID checks and cleaned after grace period
# 1. Enable hide-secrets mode
export CONSTRUCT_EXPERIMENT_HIDE_SECRETS=1
# 2. Run agent
construct claude "Debug my database connection code"
# Agent sees:
# DATABASE_URL=CONSTRUCT_REDACTED_A1B2C3D4
# API_KEY=CONSTRUCT_REDACTED_D4E5F6A7
# Your actual .env file:
# DATABASE_URL=postgresql://user:realpass@localhost/db
# API_KEY=sk-1234567890abcdef[security]
hide_secrets = true
# Allow AWS CLI to access credentials
hide_secrets_allow_paths = ["~/.aws/credentials"]construct claude "Use AWS CLI to list S3 buckets"
# Agent can run: aws s3 ls
# But other secrets remain redacted[security]
hide_secrets = true
hide_secrets_deny_paths = [
"config/prod/*.yaml",
"config/staging/*.yaml"
]Check: Is the environment gate set?
echo $CONSTRUCT_EXPERIMENT_HIDE_SECRETS
# Should output: 1Check: Is hide_secrets = true in config?
construct sys doctor | grep hide_secretsProblem: AWS CLI, kubectl, or similar tools failing
aws: Unable to locate credentials
Solution: Add credentials file to allowlist
hide_secrets_allow_paths = ["~/.aws/credentials"]Problem: Non-secret values being redacted
Solution: Use passthrough for specific env vars
hide_secrets_passthrough_vars = ["PUBLIC_API_URL", "APP_NAME"]This is intentional behavior in hide-secrets mode.
To persist changes:
- Review changes in session directory
- Manually copy desired changes to your project
- Or disable hide-secrets mode for that workflow
- Use hide-secrets mode when debugging or reviewing code
- Keep
.githidden (hide_git_dir = true) - Use hash mask style for easier debugging
- Review allowlist entries carefully
- Keep CONSTRUCT_EXPERIMENT_HIDE_SECRETS=1 env-only (don't add to shell profiles)
- Add all config files to allowlist (defeats the purpose)
- Use
hide_secrets_allow_pathsfor files you don't control - Commit actual secrets to git (even with hide-secrets enabled)
- Assume hide-secrets mode prevents all secret leaks (defense-in-depth)
- ✅ Project files with secret values
- ✅ Environment variables with secret names
- ✅ Output from Construct-controlled subprocesses
- ✅
.gitdirectory (whenhide_git_dir = true)
- ❌ Secrets already in git history
- ❌ Binary/archive files (not scanned)
- ❌ Provider API calls (requires proxy feature, V2)
- ❌ Malicious host-side tools outside Construct
- ❌ Subprocess output from non-Construct tools
- Provider proxy for authenticated API calls
- Daemon isolation for stronger security boundaries
- Advanced proxy policy controls
- Organization-level policy presets
Linux: Uses OverlayFS
Lower layer (real project, read-only)
├── .env ← Contains real secrets
└── src/ ← Regular files
Upper layer (session-specific, writable)
├── .env ← Redacted copy (CONSTRUCT_REDACTED_*)
└── changes/ ← Agent writes
Merged view (agent workspace)
├── .env ← Shows redacted version
└── src/ ← Passthrough from lower
macOS: Uses APFS clones (copy-on-write) with similar isolation
Security events are logged to:
~/.config/construct-cli/security/audit/security-audit.log
Events include:
- Session start/end
- Token mint/revoke
- Redaction operations
- Policy violations
View audit logs (V2):
construct sys security audit verify- Issues: Report bugs at github.com/EstebanForge/construct-cli/issues
- Security concerns: Use private security disclosure
- Feature requests: Welcome via GitHub issues
- Implementation Plan - Technical architecture
- Architecture Design - Overall system architecture
- Configuration Guide - General configuration