fix(shellenv): don't escape newlines in exported env var values (#2814)#2925
Open
mikeland73 wants to merge 2 commits into
Open
fix(shellenv): don't escape newlines in exported env var values (#2814)#2925mikeland73 wants to merge 2 commits into
mikeland73 wants to merge 2 commits into
Conversation
exportify escaped newlines inside double-quoted export values as `\<newline>`. Inside double quotes the shell treats a backslash-newline as a line continuation and removes it, collapsing a multi-line value onto a single line. A bare newline inside double quotes is already literal, so the escaping was both unnecessary and corrupting. This corrupted, for example, a PROMPT_COMMAND set by bash-preexec whose `... 2>&1` and `__bp_interactive_mode` lines got joined into `... 2>&1__bp_interactive_mode`, producing a "1__bp_interactive_mode: ambiguous redirect" error at every prompt when running `eval "$(devbox global shellenv)"`. Drop `\n` from the set of characters escaped inside double quotes and add a regression test pinning the multi-line output. Fixes #2814 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzomNNnDLmX4LMZ4aPtYvm
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a shellenv corruption bug where exportify escaped \n inside double-quoted values as \<newline>, which Bash interprets as a line continuation and strips—collapsing multiline env var values (notably PROMPT_COMMAND) and triggering errors like “ambiguous redirect”.
Changes:
- Stop escaping newline characters in
internal/devbox/envvars.gowhen emittingexport KEY="value";. - Add a regression test to ensure multiline values are preserved and no
\\\nline-continuation sequence is produced.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| internal/devbox/envvars.go | Removes newline from the set of escaped characters in exportify, with clarifying commentary about shell semantics. |
| internal/devbox/envvars_test.go | Adds TestExportifyPreservesNewlines to lock in correct multiline export behavior and prevent regressions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Rename the loop variable `r` to `char` and hoist the explanatory comment out of the loop body so the variable's declaration-to-use distance stays within golangci-lint's varnamelen max-distance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzomNNnDLmX4LMZ4aPtYvm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2814.
eval "$(devbox global shellenv)"could printbash: 1__bp_interactive_mode: ambiguous redirectat every prompt when an environment variable (e.g. aPROMPT_COMMANDset by bash-preexec) contained newlines.Root cause
exportify(internal/devbox/envvars.go) emits each variable asexport KEY="value";, escaping special characters inside the double quotes. It escaped\nby writing a backslash before the newline, producing\<newline>:Inside double quotes the shell treats a backslash-newline as a line continuation and removes it entirely, collapsing a multi-line value onto one line. A bare newline inside double quotes is already literal, so the escaping was both unnecessary and corrupting.
For the reporter's
PROMPT_COMMAND, the lines... >/dev/null 2>&1and__bp_interactive_modewere joined into... 2>&1__bp_interactive_mode, so the2>&1redirect target became1__bp_interactive_mode— hence the "ambiguous redirect" error.Minimal demonstration of the shell behavior:
Fix
Drop
\nfrom the set of characters escaped inside double quotes, so newlines are emitted literally. TheexportifyNushellpath already emits newlines literally, so this makes the two consistent.How was it tested?
TestExportifyPreservesNewlines, which pins the multi-line output and asserts no\<newline>line-continuation is produced.go test ./internal/devbox/ -run 'TestExportify|TestIsValidEnvName'— passes.gofmt -landgo vet ./internal/devbox/— clean./cc @proedie (issue reporter) — thanks for the precise diagnosis and workaround in the report.
Community Contribution License
All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.
By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.
🤖 Generated with Claude Code
https://claude.ai/code/session_01WzomNNnDLmX4LMZ4aPtYvm
Generated by Claude Code