Skip to content
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

Command::env doesn't report an error for keys with = in them #122335

Open
5225225 opened this issue Mar 11, 2024 · 5 comments · May be fixed by #126391
Open

Command::env doesn't report an error for keys with = in them #122335

5225225 opened this issue Mar 11, 2024 · 5 comments · May be fixed by #126391
Assignees
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@5225225
Copy link
Contributor

5225225 commented Mar 11, 2024

fn main() {
    println!(
        "{:?}",
        std::process::Command::new("printenv")
            .arg("foo")
            .env("foo=bar", "baz")
            .output()
    );
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4c8d4bb6d9fb790591d7cf07dbf516e8

This has a stdout of bar=baz, so the foo key has value bar=baz.

Which isn't what I asked for in env, but what I asked for is invalid.

We probably shouldn't panic from a bad env call, but this program shouldn't be able to spawn without erroring.

I assume .env("foo=bar", "baz").env_remove("foo=bar") shouldn't error. (Also, not sure how non-unix platforms handle this, but this validation should presumably be platform-specific).

I'm not sure if this is a bug or just weird behavior.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 11, 2024
@jieyouxu jieyouxu added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-discussion Category: Discussion or questions that doesn't represent real issues. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Mar 11, 2024
@mindstorm38
Copy link

mindstorm38 commented Mar 18, 2024

It should be analogous to libc's setenv, as said in the manual (https://man7.org/linux/man-pages/man3/setenv.3.html) EINVAL is returned if = is present in var name. For me, it should return an error upon process spawn (when arguments are aggregated), I would've preferred an early error in .env but the builder pattern would be horrible, and anyway its signature is already set in stone.

I think that it should be considered a bug, the windows impl should have the same issue (not tested) because no check is made on name (like for unix), and for CreateProcessW, win32 API explicitly states that "Because the equal sign is used as a separator, it must not be used in the name of an environment variable." (https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw).

@ChrisDenton
Copy link
Member

I think that it should be considered a bug, the windows impl should have the same issue (not tested) because no check is made on name (like for unix), and for CreateProcessW, win32 API explicitly states that "Because the equal sign is used as a separator, it must not be used in the name of an environment variable." (https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw).

It's undocumented but = is allowed as the first character of a key name. This is used by the command prompt to sneak through "hidden" environment variables.

@5225225
Copy link
Contributor Author

5225225 commented Mar 20, 2024

I assume that acts like a dotfile then, where you have the full envar be =foo=bar, meaning a envar with key foo and value bar (unless you parse it "normally" in which case it's a blank name and a value of foo=bar)? How should we parse it then?

@ChrisDenton
Copy link
Member

ChrisDenton commented Mar 21, 2024

Parsing is done simply by making sure the key name is at least one character. So =C:=C:\\Users\\ChrisDenton is parsed as ("=C:", "C:\\Users\\ChrisDenton"). We already handle this in the standard library

// Windows allows environment variables to start with an equals
// symbol (in any other position, this is the separator between
// variable name and value). Since`s` has at least length 1 at
// this point (because the empty string terminates the array of
// environment variables), we can safely slice.
let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) {

So in relation to the OP we'd just skip over the first character when disallowing = in the key name but otherwise we wouldn't make any distinction between "hidden" and not hidden variables (that's up to the shell).

@tbu-
Copy link
Contributor

tbu- commented Jun 13, 2024

@rustbot claim

tbu- added a commit to tbu-/rust that referenced this issue Jun 13, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
@tbu- tbu- linked a pull request Jun 13, 2024 that will close this issue
tbu- added a commit to tbu-/rust that referenced this issue Jun 13, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
tbu- added a commit to tbu-/rust that referenced this issue Jun 13, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
tbu- added a commit to tbu-/rust that referenced this issue Jun 20, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
tbu- added a commit to tbu-/rust that referenced this issue Jun 20, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 21, 2024
Validate environment variable names in `std::process`

Make sure that they're not empty and do not contain `=` signs beyond the first character. This prevents environment variable injection, because previously, setting the `PATH=/opt:` variable to `foobar` would lead to the `PATH` variable being overridden.

Fixes rust-lang#122335.
tbu- added a commit to tbu-/rust that referenced this issue Jul 10, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
tbu- added a commit to tbu-/rust that referenced this issue Jul 10, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 10, 2024
Validate environment variable names in `std::process`

Make sure that they're not empty and do not contain `=` signs beyond the first character. This prevents environment variable injection, because previously, setting the `PATH=/opt:` variable to `foobar` would lead to the `PATH` variable being overridden.

Fixes rust-lang#122335.
try-job: x86_64-msvc
tbu- added a commit to tbu-/rust that referenced this issue Oct 7, 2024
Make sure that they're not empty and do not contain `=` signs beyond the
first character. This prevents environment variable injection, because
previously, setting the `PATH=/opt:` variable to `foobar` would lead to
the `PATH` variable being overridden.

Fixes rust-lang#122335.
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 13, 2024
Validate environment variable names in `std::process`

Make sure that they're not empty and do not contain `=` signs beyond the first character. This prevents environment variable injection, because previously, setting the `PATH=/opt:` variable to `foobar` would lead to the `PATH` variable being overridden.

Fixes rust-lang#122335.
try-job: x86_64-msvc
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 17, 2024
Validate environment variable names in `std::process`

Make sure that they're not empty and do not contain `=` signs beyond the first character. This prevents environment variable injection, because previously, setting the `PATH=/opt:` variable to `foobar` would lead to the `PATH` variable being overridden.

Fixes rust-lang#122335.
try-job: x86_64-msvc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants