ERL-1069: Support disabling echo input in new shell
Original reporter: starbelly
Affected versions: OTP-19.0, OTP-20.0, OTP-21.0, OTP-22.0
Component: stdlib
Migrated from: https://bugs.erlang.org/browse/ERL-1069
Currently disabling input echo is only supported in the new shell. This prevents getting sensitive information at runtime in an escript (or similar) problematic. Currently in rebar3_hex and mix/hex we are clearing the input ever 1ms and while this works it is obviously not an ideal solution/situation security wise and at the very least leads to bad UX.
We did have a solution in rebar3_hex that worked for most platforms but bugs arose with it. Namely, opening up a tty_sl port does the job but subsequent io:get_line/1 calls never return after receiving input (seemingly). It is not 100% clear if this work-around is in fact a bug, so I did not open a bug report for it in favor of this is one feature request. Can gladly do so if that is what should be done.
Please find below a way to reproduce this behavior:
{code:erlang}
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -noshell -boot
%%
main(_) ->
erlang:display({echo_off_support, io:setopts([{echo, false}])}),
%% So we do a hack with tty_sl, which works but with a side effect that
%% results in no subsequent calls able to return from an io:get_line/1 call
Msg = <<"Enter your foo : ">>,
error_logger:tty(false),
Port = open_port({spawn, "tty_sl -e"}, [binary, eof]),
port_command(Port, <<0, Msg/binary>>),
receive
{Port, {data, PwLine}} ->
[Pw | _] = binary:split(PwLine, <<"\n">>),
port_command(Port, <<0, $\n>>),
port_close(Port),
error_logger:tty(true),
Pw
end,
io:get_line(<<"Enter your bar : ">>),
erlang:display("We'll never make it here :("),
halt(1).
{code}
starbelly said:
P.S. I'd be happy to do a PR, but perhaps would need a big of guidance.
josevalim said:
If my understanding is correct, there is nothing to be done with the old shell because it does not intercept characters as they are typed. The trick that we use in Hex is to hide the characters by using "\r", see here: [https://github.com/hexpm/hex/blob/ab402f98c1efe6855c93dfc5130c2b7a4b1ef753/lib/mix/tasks/hex.ex#L363-L392]
Another option is to make `io:get_password` public API and make it available on the old shell too.
starbelly said:
@[~josevalim], yes, that's what is done in rebar3_hex as well based off what's done in hex :) We thought it was only needed when on windows, but then we ran into this problem and switched to the trick you allude to for all platforms. This works, but what would benefit everyone is for get_password/0 and get_password/1 to work on all platforms and within escripts. I'm going to look into this again over the coming weeks.
rickard said:
A PR would be appreciated
I encountered a problem during Windows installation. When using bat to execute 'Install. exe', I will be prompted with a screen input of 'Do you want a minimum startup install of Sasl [No]:'. How can I skip this input?
IIRC, command line parameter -minimal was giving [No]. Could you try adding that to bat file?
IIRC, command line parameter
-minimalwas giving[No]. Could you try adding that to bat file?
Thank you for your reply, but I tried adding the -minimal parameter and prompted 'Unknown command switch -minimal'. Can you give an example?
It was my bad, I confused Linux vs Windows Install.
On Windows, you need to supply -s command line argument, e.g. Install.exe -s "....<path>...".
Also, I think this specific GitHub issue is not related to your problem.