Skip to content

Overly restrictive .env file blocking prevents reading legitimate files #4969

@Walid-Azur

Description

@Walid-Azur

Issue: Overly Restrictive .env File Blocking

Summary

The Read tool blocks access to ANY file containing ".env" in its path, preventing legitimate reads of:

  • Environment configuration files (.env.local, .env.development, .env.production)
  • Source code files with "env" in the path (environment/, config/env/)
  • Template/example files that should be readable (.env.template)

Reproduction

Current Behavior

// Trying to read any file with "env" in path
Read({ filePath: ".env.local" })
// ❌ Error: "The user has blocked you from reading .env.local, DO NOT make further attempts to read it"

Read({ filePath: "src/config/environment.ts" })
// ❌ Error: "The user has blocked you from reading src/config/environment.ts, DO NOT make further attempts to read it"

Read({ filePath: ".env.template" })
// ❌ Error: "The user has blocked you from reading .env.template, DO NOT make further attempts to read it"

Files Currently Blocked

Blocked (shouldn't be):

  • .env.local, .env.development, .env.production
  • .env.template
  • src/environment/config.ts
  • config/env/settings.ts
  • Any path containing "env"

Allowed (whitelist):

  • .env.sample
  • Files ending with .example

Root Cause

Location: packages/opencode/src/tool/read.ts:63-74

const block = iife(() => {
  const whitelist = [".env.sample", ".example"]

  if (whitelist.some((w) => filepath.endsWith(w))) return false
  if (filepath.includes(".env")) return true  // ❌ TOO BROAD

  return false
})

if (block) {
  throw new Error(`The user has blocked you from reading ${filepath}, DO NOT make further attempts to read it`)
}

Problem: The check filepath.includes(".env") blocks:

  1. Any file with "env" anywhere in the path (not just .env files)
  2. All .env variants (.env.local, .env.development, etc.)
  3. Template files that are safe to read

Impact

Development Workflow Issues

  1. Configuration Discovery: Cannot read environment config files to understand app setup
  2. Template Usage: Cannot read .env.template or .env.example files
  3. Source Code: Cannot read legitimate source files with "env" in path
  4. Debugging: Cannot inspect environment configuration when troubleshooting

Security Intent

The blocking was likely intended to:

  • ✅ Prevent leaking secrets in .env
  • ✅ Protect production credentials

However, it's too aggressive and blocks safe files.

Proposed Solution

Recommended Fix: Basename-Based Blocking

Make the blocking more precise by checking only the filename, not the full path:

const block = iife(() => {
  const whitelist = [
    ".env.sample",
    ".env.example",
    ".example",
    ".env.template",
    ".env.schema"
  ]

  if (whitelist.some((w) => filepath.endsWith(w))) return false

  // Only block files that ARE actual .env files (basename check)
  const basename = path.basename(filepath)
  if (basename.startsWith(".env")) return true

  return false
})

if (block) {
  throw new Error(`The user has blocked you from reading ${filepath}, DO NOT make further attempts to read it`)
}

Alternative: Pattern-Based Whitelist

More explicit pattern matching:

const block = iife(() => {
  const basename = path.basename(filepath)

  // Whitelist: Safe template/example files
  const safePatterns = [
    /\.env\.sample$/,
    /\.env\.example$/,
    /\.env\.template$/,
    /\.env\.schema$/,
    /\.example$/
  ]

  if (safePatterns.some(pattern => pattern.test(filepath))) {
    return false
  }

  // Block: Actual .env files with potential secrets
  const blockPatterns = [
    /^\.env$/,                    // .env
    /^\.env\.local$/,             // .env.local
    /^\.env\.development$/,       // .env.development
    /^\.env\.production$/,        // .env.production
    /^\.env\.staging$/,           // .env.staging
    /^\.env\.test$/,              // .env.test
    /^\.env\.[a-z]+\.local$/      // .env.*.local
  ]

  return blockPatterns.some(pattern => pattern.test(basename))
})

Comparison Table

File Path Current Behavior After Fix
.env ❌ Blocked ❌ Blocked (correct)
.env.local ❌ Blocked ❌ Blocked (correct)
.env.production ❌ Blocked ❌ Blocked (correct)
.env.sample ✅ Allowed ✅ Allowed
.env.example ✅ Allowed ✅ Allowed
.env.template ❌ Blocked ✅ Allowed (fix)
src/environment.ts ❌ Blocked ✅ Allowed (fix)
config/env/settings.ts ❌ Blocked ✅ Allowed (fix)
.example ✅ Allowed ✅ Allowed

Testing

To verify fix:

// Test 1: Block actual .env files
Read({ filePath: ".env" })
// Should throw: blocked

Read({ filePath: ".env.local" })
// Should throw: blocked

// Test 2: Allow template files
Read({ filePath: ".env.template" })
// Should succeed

Read({ filePath: ".env.example" })
// Should succeed

// Test 3: Allow source files with "env" in path
Read({ filePath: "src/config/environment.ts" })
// Should succeed

Read({ filePath: "utils/envParser.ts" })
// Should succeed

Security Considerations

The fix maintains security by:

  • ✅ Still blocking .env and variants (.env.local, .env.production, etc.)
  • ✅ Preventing accidental secret leakage
  • ✅ Allowing safe template/example files
  • ✅ Not blocking legitimate source code

Additional Context

  • Security Goal: Prevent reading files with actual secrets
  • User Experience: Allow reading configuration templates and source code
  • Best Practice: Use .env.example or .env.template for documentation
  • Related Code: packages/opencode/src/tool/read.ts

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions