Skip to content

fix: block-env-files and protect-env-vars false positives on quoted content#50

Closed
yashexosphere wants to merge 1 commit into
mainfrom
ef-49/fix-env-policy-false-positives
Closed

fix: block-env-files and protect-env-vars false positives on quoted content#50
yashexosphere wants to merge 1 commit into
mainfrom
ef-49/fix-env-policy-false-positives

Conversation

@yashexosphere

@yashexosphere yashexosphere commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Strip quoted string content before regex matching in blockEnvFiles and protectEnvVars
  • Allow .env.example, .env.template, .env.sample (committed templates, no real secrets)
  • Add 30+ true/false positive unit tests

Closes #49

Test plan

  • bun run test:run — all 766 tests pass
  • gh pr create --body "don't commit .env" — no longer blocked
  • git commit -m "export PATH changes" — no longer blocked
  • cat .env — still blocked
  • export API_KEY=abc — still blocked

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Reduced false positives in environment variable and .env file protection policies by improving detection accuracy when keywords appear within quoted command arguments.
    • Safe template files like .env.example and .env.template are now excluded from blocking.
  • Tests

    • Expanded test coverage for environment variable and .env file protection policies with additional edge cases and scenarios.

…ocks

- Add stripQuotedStrings() to ignore .env/.export inside quoted args
- Add negative lookahead to ENV_CMD_RE for .env.example/.env.template
- Add ENV_SAFE_SUFFIX_RE for file path checks on safe template files
- Add comprehensive true/false positive tests for both policies
@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR fixes false positives in block-env-files and protect-env-vars policies by introducing a stripQuotedStrings() helper function that removes quoted argument content before applying security regex checks, and whitelists safe .env* template variants with comprehensive test coverage.

Changes

Cohort / File(s) Summary
Test Suite Expansion
__tests__/hooks/builtin-policies.test.ts
Expanded test coverage for protect-env-vars with additional deny cases (printenv, echo $HOME, export assignments, env in pipelines) and allow cases for quoted content false positives. Extended block-env-files tests with deny cases for .env* variants and shell operations, plus allow cases for quoted .env mentions and baseline cases for safe template files.
Core Policy Logic
src/hooks/builtin-policies.ts
Added stripQuotedStrings() helper to remove content within "...", '...', and `...` before regex matching. Updated protectEnvVars to apply environment variable regexes against stripped command. Updated blockEnvFiles to whitelist safe .env* suffixes (.example, .template, .sample, .dist, .test) and run .env reference regex against stripped command with negative-lookahead pattern.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Quotes hid secrets in the shell,
Making safe commands rebel!
Now we peek inside the quotes,
Strip the noise from all the notes—
False alarms bounce away! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: eliminating false positives in two policies by handling quoted content.
Description check ✅ Passed The PR description covers the key changes and includes a test plan with specific scenarios, though the description template's checklist items are not marked as completed.
Linked Issues check ✅ Passed The code changes directly address issue #49 by implementing quote-stripping in both policies, adding safe file suffixes, and preventing false positives on quoted content.
Out of Scope Changes check ✅ Passed All changes are narrowly scoped to fix the quoted-content false positives in the two affected policies and their corresponding tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ef-49/fix-env-policy-false-positives

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/builtin-policies.ts`:
- Around line 97-101: ENV_SAFE_SUFFIX_RE / ENV_FILE_PATH_RE / ENV_CMD_RE
currently allow safe substrings anywhere in the path and miss case-insensitive
matches; change the logic to extract the file basename (last path segment),
normalize it to lowercase, and compare it exactly against the whitelist of
allowed template basenames (e.g. ".env", ".env.example", ".env.template",
".env.sample", ".env.dist", ".env.test") instead of using the existing regexes
to match anywhere; update the checks that use ENV_SAFE_SUFFIX_RE,
ENV_FILE_PATH_RE and ENV_CMD_RE (including the other occurrence around the
367-373 area) to use this basename-based, case-insensitive exact comparison so
paths like "/tmp/.env.example/.env" or ".env.example.local" no longer bypass the
policy.
- Around line 114-115: stripQuotedStrings currently replaces entire quoted spans
with empty quotes which removes semantically active shell syntax and permits
real violations to bypass policy checks; change stripQuotedStrings to perform
context-aware masking (e.g., preserve or mark shell-expanding constructs like
$VAR, command substitutions $(...), backticks, and prefixes like bash -c inside
quoted strings) rather than blanking every quoted span so that downstream
matchers still see dangerous patterns, and update any other quote-stripping
logic in this file to the same approach; add regression tests that include
quoted true-positive cases such as cat ".env", source '.env', echo "$HOME", and
bash -lc "cat .env" to ensure these are detected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f158ba6c-128e-4879-85dc-eb2d990fb45b

📥 Commits

Reviewing files that changed from the base of the PR and between 304add2 and 93d468e.

📒 Files selected for processing (2)
  • __tests__/hooks/builtin-policies.test.ts
  • src/hooks/builtin-policies.ts

Comment on lines +97 to +101
// Allow .env.example / .env.template / .env.sample / .env.dist — these are
// committed template files with no real secrets. Block everything else.
const ENV_SAFE_SUFFIX_RE = /\.(?:example|template|sample|dist|test)(?:[./\\]|$)/i;
const ENV_FILE_PATH_RE = /(?:^|[\\/])\.env(?:\.|$)/;
const ENV_CMD_RE = /\.env(?:\b|\s|$|\.)/;
const ENV_CMD_RE = /\.env(?!\.(?:example|template|sample|dist|test)\b)(?:\b|\s|$|\.)/i;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Match the exact safe .env basename instead of regexing the whole path.

Right now a safe-looking substring anywhere in the path suppresses the block, so /tmp/.env.example/.env is allowed, and extra-extension names like .env.example.local also slip through. ENV_FILE_PATH_RE is also case-sensitive, so .ENV/.Env bypass Read/Write on case-insensitive filesystems. Please normalize to the matched basename and compare it against the exact allowed template names.

Also applies to: 367-373

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/builtin-policies.ts` around lines 97 - 101, ENV_SAFE_SUFFIX_RE /
ENV_FILE_PATH_RE / ENV_CMD_RE currently allow safe substrings anywhere in the
path and miss case-insensitive matches; change the logic to extract the file
basename (last path segment), normalize it to lowercase, and compare it exactly
against the whitelist of allowed template basenames (e.g. ".env",
".env.example", ".env.template", ".env.sample", ".env.dist", ".env.test")
instead of using the existing regexes to match anywhere; update the checks that
use ENV_SAFE_SUFFIX_RE, ENV_FILE_PATH_RE and ENV_CMD_RE (including the other
occurrence around the 367-373 area) to use this basename-based, case-insensitive
exact comparison so paths like "/tmp/.env.example/.env" or ".env.example.local"
no longer bypass the policy.

Comment on lines +114 to +115
function stripQuotedStrings(cmd: string): string {
return cmd.replace(/"[^"]*"|'[^']*'|`[^`]*`/g, '""');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

This quote stripping creates a security bypass, not just a false-positive fix.

Because the stripped string is what both policies inspect, semantically active shell syntax disappears before matching. cat ".env", source '.env', echo "$HOME", and bash -lc "cat .env" all become invisible here, so real .env reads and env-var disclosure are now allowed with ordinary quoting. Please make the suppression context-aware instead of blanking every quoted span, and add regression tests for quoted true-positive cases.

Also applies to: 331-339, 373-373

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/builtin-policies.ts` around lines 114 - 115, stripQuotedStrings
currently replaces entire quoted spans with empty quotes which removes
semantically active shell syntax and permits real violations to bypass policy
checks; change stripQuotedStrings to perform context-aware masking (e.g.,
preserve or mark shell-expanding constructs like $VAR, command substitutions
$(...), backticks, and prefixes like bash -c inside quoted strings) rather than
blanking every quoted span so that downstream matchers still see dangerous
patterns, and update any other quote-stripping logic in this file to the same
approach; add regression tests that include quoted true-positive cases such as
cat ".env", source '.env', echo "$HOME", and bash -lc "cat .env" to ensure these
are detected.

@NiveditJain

NiveditJain commented Apr 8, 2026

Copy link
Copy Markdown
Member

we should debate about this and figure out a better strategy for this, current strategy in the PR will allow claude to read .env in say, sub folders.

@NiveditJain NiveditJain deleted the ef-49/fix-env-policy-false-positives branch April 27, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: block-env-files and protect-env-vars false-positive on quoted string content

2 participants