-
Notifications
You must be signed in to change notification settings - Fork 902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cloud Functions: Fix env var escaping #4271
Cloud Functions: Fix env var escaping #4271
Conversation
Fixed! |
These test cases reveal two bugs in functions/env.ts#parse: 1. In a string containing two or more instances of a repeated escape sequence (e.g. \n or \t), only the first one will be replaced with its corresponding unescaped character. This is because of a JS gotcha where String.prototype.replace, when called with a string as the search argument, only replaces the first occurrence. 2. Escapes are not processed in order of occurrence in the input string. With the current implementation, certain sequences are prioritized, even if they are preceded with a backslash that is itself escaped.
b28cfc1
to
272f80b
Compare
Other
|
272f80b
to
8d1d58b
Compare
functions/env.ts#parse now parses multiple occurrences of escaped control characters (\n, \r, \t, \v) and does so in order of occurrence.
All instances of an escapable character are now escaped. This also adds backslash to achieve parity with the escape sequences understood by functions/env.ts#parse.
toUpperSnakeCase in src/functions/secrets.ts only substitutes at most one of period/full-stop (.) or hyphen (-)
This ensures multiple occurrences of . or - are replaced with _.
8d1d58b
to
0f843d4
Compare
@yellcorp This is an incredible contribution - I learned so much from your thorough writeup. Thank you so much for your time in reporting, fixing, and educating us about the issue! It's late in US, so I'll defer reviewing the code to first thing tomorrow morning! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ Incredible work!
.replace("\t", "\\t") | ||
.replace("\v", "\\v"); | ||
return result.replace(/(['"])/g, "\\$1"); | ||
// Escape newlines, tabs, backslashes and quotes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on adding backlashes to the list of things we replace!
Description
Fixes #4270 and a little bit more.
The bug results from the use of
String.prototype.replace
with a first (search) argument of typestring
. This is an unintuitive corner of JavaScript that only replaces the first occurrence of the search string. See MDN. To replace all occurrences, either the search argument must be expressed as an equivalent regex with the/g
flag, or .replaceAll must be used. .replaceAll isn't supported below Node 15, and given this package's dependency on Node >= 12, the regex approach has been used here.Quick demonstration:
There's another reason to use a regex approach - running the string through repeated invocations of .replace(All) processes the escapes in an implementation-defined order, whereas the string really should be scanned from start to end in order to correctly convert (for example)
\\n
to\
n
. The popular npm package dotenv gets tripped up by this as well.The changes outside
.env
files result from manually searching the repo for uses ofString.prototype.replace
having a non-regex first argument. There are more occurrences than the ones fixed here that probably should be audited, but 1. Not all instances are immediately obvious to me whether they intend to replace all occurrences of the search argument 2. I wanted to keep this PR focused.Scenarios Tested
User journeys
Edge cases
\\n
should be interpreted as backslash, letter n.