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

Allow to use a file named - as INPUT #494

Open
meineerde opened this issue Feb 1, 2023 · 10 comments
Open

Allow to use a file named - as INPUT #494

meineerde opened this issue Feb 1, 2023 · 10 comments

Comments

@meineerde
Copy link

Environment

  • OS: macos
  • age version: v1.1.1

What were you trying to do

In trying to encrypt the contents of a file named -. I'm giving this filename as INPUT in

age --encrypt -i example.key -

What happened

age waits indefinitely for something to appear on STDIN instead of reading the file. Aparently, age considers the filename

Suggestions

It would probably be a good idea to honor the -- argument before the final (optional) INPUT argument. Anything given after -- would then be considered a filename. An input file named - could then be specified as

age --encrypt -i example.key -- -

With this schema, we could clearly distinguish the - filename from the current behavior of always forcing a read from STDIN.

Alternatively, you could also specify a flag parameter to indicate that the following argument is a file and deny the specification of a final INPUT argument if this is given, e.g.

age --encrypt -i example.key --input-file -
@magical
Copy link

magical commented Feb 2, 2023

You can probably use ./-.

@meineerde
Copy link
Author

That works indeed. Thanks for the hint!

However, the initial ambiguity described here still makes it rather difficult to script age in a way that I (or rather the user of my script) can throw any valid filename at it with me being sure that it will be indeed interpreted as a file.

Now I have to manually check whether the INPUT argument is - and replace it with ./-

Also, the same basic issue also applies to the --recipients-file option too.

@neruthes
Copy link

You can do realpath -- - to get the absolute path of the file on the VFS tree, so that the leading characters must be /. Ambiguity removed.

@str4d
Copy link

str4d commented Feb 16, 2023

For additional context, originally (during early development) age did treat - as a filename. This behaviour was changed in response to a user request for age to follow the general Linux CLI app convention of interpreting - in filename positions as a marker for stdin or stdout: #143.

@alerque
Copy link
Contributor

alerque commented Feb 16, 2023

I don't think you can have your cake and eat it too. Making - be an alias for STDIN/STDOUT as is convention in many *nix tools precludes it working as an actual filename without escaping. This isn't just an issue with age, and the usual workarounds apply. I think the current behavior is expected and would not want to see it change.

This is even potentially a security issue. Given that - is supposed to be STDIN, if the logic were to change and a local file were to be preferred over the stream, potentially a script using age could be tricked into using a different input than what the script author intended.

@meineerde
Copy link
Author

meineerde commented Feb 16, 2023

Many other tools which accept filenames, accept those only at the end of the argument list. Then, they allow to add a separate -- argument to mark everything following it to be an actual real filename. This can be used to e.g. delete a file named -f with rm -- -f.

Because of this convention, I proposed that age may understand this -- separator to mark everything that follows as a filename rather than any further options. This would then neatly solve the issue with other potential input filenames, such as --armor --passphrase or others.

Interestingly, age currently seems to accept the -- separator there currently, but chooses to ignore it.

As for using the "inline marker" - in places where paths are generally expected (such as with --recipient-file or --identity), this seems like a general anti-pattern to me since it makes it harder to predictably use age with arbitrary filenames (and avoid it hanging waiting for input that may never arrive). I would have rather loved for these options to have separate names (such as --read-recipients, --read-identity, ...), but I guess that ship has sailed...

@dolmen
Copy link

dolmen commented Mar 6, 2024

@meineerde Even if -- was recognized, - would still be handled as STDIN because #143.

@FiloSottile
Copy link
Owner

My understanding of the -- separator is slightly different, it separates flags from arguments, not filenames, so I would actually expect foo -- - to be equivalent to foo - because - is parsed as an argument in both cases.

Are there tools where -- actually changes the semantics of arguments?

@alerque
Copy link
Contributor

alerque commented Jun 16, 2024

It separates flags and arguments from positional arguments. Whether the positional arguments are filenames or not is immaterial, the point is after that you stop parsing for flags and named arguments. In this case the - is not either thing and the meaning would still not change. To avoid the STDIN alias and refer to a file you would still need some escaping or path segment workaround.

@str4d
Copy link

str4d commented Jun 16, 2024

Your understanding is consistent with @meineerde 's observation:

This can be used to e.g. delete a file named -f with rm -- -f.

That is, the reason -- enables rm to treat -f as a filename is not because -- tells rm to do so, but because -- tells rm to not treat -f as a flag (or flag argument), and the first positional argument to rm happens to be a filename. I expect that the first positional argument to many CLI tools also happens to be a filename, leading to the confusion.

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

No branches or pull requests

7 participants