Does Julia have an "invisible" function?

I’ve cobbled together a function that will return a password from my gnome keyring, the only problem is that it shows the password on the console when it executes. Does Julia have an “invisible” function, like that of R, such that the value is returned but not shown?
Let me clairfy: I use this string,

PWD=$(read(`secret-tool lookup word1 word2 word3 word4`,String));

which calls the system function “secret-tool”, and it works correctly, however in the process is displays the value of word4, which is the password in the REPL. In R the invisible function wrapped around it stops it from being displayed.
Any other solutions welcome. Thx. J.

Try Base.getpass()?

1 Like

Or maybe I’m not understanding R’s invisible(). Perhaps try using Base.SecretBuffer to store your secrets? These don’t print the values contained within, and have other security-relevant features.

1 Like

What is doing the printing? Are you talking about the REPL?

Maybe you just want to add a semicolon?

julia> getsupersecretpassword() = unsafe_string(pointer([rand(UInt8, 256); 0x00] ))
getsupersecretpassword (generic function with 1 method)

julia> getsupersecretpassword()
"\xa6\x9eoN\x8c\xe6b>gT\xb7\x0eH\xb7\xa2\x87\x11E6\xb8\xf7(jq\xf4!u\x95\x1e\x9f\x89\xcao\xe5`R\x1c\xe13E\xa4~\xa8]\x89\xff\x8c\x14\xf6\x9b\xb0mGP\x8bNNk "

julia> getsupersecretpassword();

julia> 5+5
10

1 Like

I think it’s useful to contrast R and Julia quickly to understand what invisible does in R and why it doesn’t exist in Julia.

R:

> 1
[1] 1
> x <- 1
>

Julia

julia> 1
1

julia> x = 1
1

julia>

This example is meant to illustrate that R prints or does not print the values of expressions in the REPL based on whether or not an assignment occurs. The invisible function changes this behavior by telling R “don’t print this value even if there is no assignment”.

Julia does not make this distinction – it always prints values. To prevent that, use a semicolon as @mkitti says.

This is my final solution, and it does work to hide the password, but anyone who knows Julia can simply remove the semicolon at the end, and it will appear, so not exactly what I wanted. I have to circulate this code to colleagues and others. The syntax for the ODBC connection is very specific with respect to “,” and “;” . Thx. J

con3 = ODBC.Connection(
    "Driver=ODBC Driver 17 for SQL Server;
    SERVER=66.66.66.66;
    DATABASE=dbname;
    UID=username;
    PWD=$(read(`secret-tool lookup word1 word2 word3 word4`,String))");

An easy solution to prevent the output of a function from being shown, is to wrap it into an Invisible type with that behavior:

julia> struct Invisible{T}
           data::T
       end

julia> Base.show(io::IO, x::Invisible) = print(io, "")

julia> foo(x) = Invisible(x^2)
foo (generic function with 1 method)

julia> y = foo(3)


julia> y


julia> y.data
9

As shown in the example, this is not like invisible in R, which only has “transitory effects”. To see (and “use”) the hidden content you have to access the data field of the returned object. But maybe it works for your case.

3 Likes

I really do not understand your problem, if you gonna circulate a code with your password in plaintext inside it (or, if I understood wrongly, at least a command line that can be copied to a console and then will give your password) then I think any worries about security are already void. The code is inherently insecure. It does not even need to be edited (the relevant part just needs to be copy-pasted). I also do not see how this would be different from a R solution, someone knowing R could also easily change the “invisible” wrapping and reveal the secret, no?

1 Like

Thanks Henrique,
You are correct, it is a bit convoluted. A previous model, that has worked very well for me is this: I have to do some SQL work for some clients, and this involves pulling data from another clients SQL server, hence the need for usernames and passwords, which I would rather not spread around in email, pdf documents etc. Therefore I keep my login credentials stored in a gnome secret keyring. I’m now switching from R to Julia but when using R I can put all the working code and some results in RStudio, and knitr it to a pdf, which all clients like to study and use. So the invisible password allows them to see how I’ve done it but also prevents the password from being seen in R results. As long as I keep it hidden, then they would have to get access to my server, and my keyring to get the credentials? Let me know if this is still illogical, or you have a better solution.

Anyone who knows R can simply remove the invisible function call at the beginning, and it will appear, so isn’t this exactly the same situation?

no it’s not logical, if you’re just giving them a pdf file, how could they possibly know your password unless it’s printed in PDF? As for Julia, as long as you hide the result from whatever notebook you’re using when generating pdf, sharing the code with them is whatever.

you do realize that they need to be on the same computer and same account as you when they run secret-tool in order to work right? it’s not reading from the internet, it’s a local command. I don’t understand why ; is “not good enough”

Again Thanks. I don’t think so because the R “decrypt_gk_pw” function hides all the results of getting the encrypted password in the results, it is never visible. But yes, if another person read specific phrase words that I use with decrypt_gk_pw, and then got access to my computer, and my keyring, they could get the password. It is just not broadcasting the credentials. Is this making any sense?

I actually don’t know what you’re seeing here, for me, secret-tool does not print anything, so as long as PWD is not the last line in the notebook, and I don’t call something like print(PWD), it’s never displayed anywhere

> julia -e 'read(`secret-tool lookup db mydb user user1`, String) |> println' 
blah
> julia -e 'read(`secret-tool lookup db mydb user user1`, String)' 

Thanks again, all I know is that in my REPL, which runs inside Emacs, it clearly shows the value of the string, when this code is passed to the ODBC.connect function to get the PWD= I’ve found the ODBC connection to be very unforgiving. I’d show you an example but the only connection I have would … show the password …

It seems like the show method of Connection (here) will print the string of the object with the information. The show method is run if the object is returned in the REPL, so you have a few ways to avoid this. Either not return the object to the REPL, or whenever you do make sure to add a semicolon to remove the output.

You could also override the show method to just make it not show the value by doing something like

Base.show(io::IO, conn::Connection) = print(io, "ODBC.Connection(secret...)")

before you run any of your things using the Connection.

This will still allow anyone that runs the code on your computer to see the password by specifically printing the value of Connection.svn, but I think this is the same as in R since

> a <- decrypt_gk_pw("db mydb user user1")
> a
[1] "qwerty12345"

it is clearly possible to see still, so it is not hidden from anyone who can run the code on the machine.

So the only difference seems to be that the ODBC connection object in julia printed the password when evaluated in the REPL while maybe the R version does not?

Though it is easy to get around by not printing it (with any method mentioned above), and as long as not users have access to you computer and words they can’t get anything just like in R, it does seem like a reasonable thing to not print by default? Maybe open an issue with the ODBC repo?

1 Like

Just to be abundantly clear: removing the semicolon in some baked output (like a Weave’d PDF file or a static HTML export from a notebook or some such) won’t make the password appear. It’s only if the semicolon is removed from your code when you execute it.

4 Likes

If the word4 is not something sensible (like your keyring password), and they would not have access to your key ring, then I think it is reasonable. However, if you do something like knitr with the real code, then you are giving the real keyring password, correct? Even if this yet needs the keyring file to be useful I would not go this way. At least, I would manually edit out these strings from the final document.