Biometric not working when executing the CLI from java
Hello
I'm building a java CLI that wraps op for some operations.
The issue was first observed when running a native binary compiled with Graalvm, but after investigation it is perfectly reproducible using pure java (but not the system java for some reason).
Reproducing
- Ubuntu 20.04.1
- 1Password for Linux 8.7.3
- CLI 2.5.1 configured to support Biometric authentication as per https://developer.1password.com/docs/cli/get-started/#sign-in
- Sign up to the account with
op sign in
, verify you can list your vaults:op vault ls
. - create the following file and compile it with javac (
javac Op.java
):
// Op.java import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; public class Op { public static void main(String args[]) throws IOException { List<String> commands = Arrays.asList("op", "vault", "ls"); call(commands); } private static Process call(List<String> args) throws IOException { ProcessBuilder pb = new ProcessBuilder(args) .redirectErrorStream(true) .directory(new File(System.getProperty("user.dir"))); pb.inheritIO(); return execute(pb); } private static Process execute(ProcessBuilder pb) throws IOException { var p = pb.start(); try { p.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return p; } }
- Run the compiled class with
java Op
. If you are using the system java (installed withapt install ...
) it should be a success, but if you are using a java that is not the system java you will see an issue. For instance, I managed to reproduce the issue running a java installed with asdf. You will see something similar too:
[ERROR] 2022/07/18 12:34:12 connecting to desktop app: connection reset, make sure the CLI is correctly installed and CLI Biometric Unlock is enabled in the 1Password app
Looking into systemctl one can see:
Jul 18 12:46:13 *** polkitd(authority=local)[42243]: Operator of unix-session:c1 FAILED to authenticate to gain authorization for action com.1password.1Password.authorizeCLI for unix-process:36645:669364 [/opt/1Password/1password --enable-crashpad] (owned by unix-user:***)
and:
Jul 18 12:47:13 *** 1password.desktop[36645]: WARN 2022-07-18T12:47:13.840 tokio-runtime-worker(ThreadId(2)) [1P:foundation/op-sys-info/src/process_information/linux.rs:247] binary permission verification failed for /home/$USER/.asdf/installs/java/temurin-11.0.15+10/bin/java
The second line is also visible in 1password logs.
Additional notes
- This works ok on osX.
- I'm not set on whether the issue is on 1password client side (as it seems there is a check on the binary) or on Polkit side.
- The original issue was with a binary compiled with Graalvm, but the symptoms and logs are exactly the same with this minimal example. If needed I can build a minimal reproduction case with a Graalvm native binary though.
1Password Version: 8.7.3
Extension Version: 2.5.1
OS Version: Ubuntu 20.04.1
Browser:_ Not Provided
Comments
-
Hello
I'm building a java CLI that wraps op for some operations.
The issue was first observed when running a native binary compiled with Graalvm, but after investigation it is perfectly reproducible using pure java (but not the system java for some reason).Reproducing
- Ubuntu 20.04.1
- 1Password for Linux 8.7.3
- CLI 2.5.1 configured to support Biometric authentication as per https://developer.1password.com/docs/cli/get-started/#sign-in
- Sign up to the account with
op sign in
, verify you can list your vaults:op vault ls
. - create the following file and compile it with javac (
javac Op.java
):
// Op.java import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; public class Op { public static void main(String args[]) throws IOException { List<String> commands = Arrays.asList("op", "vault", "ls"); call(commands); } private static Process call(List<String> args) throws IOException { ProcessBuilder pb = new ProcessBuilder(args) .redirectErrorStream(true) .directory(new File(System.getProperty("user.dir"))); pb.inheritIO(); return execute(pb); } private static Process execute(ProcessBuilder pb) throws IOException { var p = pb.start(); try { p.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return p; } }
- Run the compiled class with
java Op
. If you are using the system java (installed withapt install ...
) it should be a success, but if you are using a java that is not the system java you will see an issue. For instance, I managed to reproduce the issue running a java installed with asdf. You will see something similar too:
[ERROR] 2022/07/18 12:34:12 connecting to desktop app: connection reset, make sure the CLI is correctly installed and CLI Biometric Unlock is enabled in the 1Password app
Looking into systemctl one can see:
Jul 18 12:46:13 *** polkitd(authority=local)[42243]: Operator of unix-session:c1 FAILED to authenticate to gain authorization for action com.1password.1Password.authorizeCLI for unix-process:36645:669364 [/opt/1Password/1password --enable-crashpad] (owned by unix-user:***)
and:
Jul 18 12:47:13 *** 1password.desktop[36645]: WARN 2022-07-18T12:47:13.840 tokio-runtime-worker(ThreadId(2)) [1P:foundation/op-sys-info/src/process_information/linux.rs:247] binary permission verification failed for /home/$USER/.asdf/installs/java/temurin-11.0.15+10/bin/java
The second line is also visible in 1password logs.
Additional notes
- This works ok on osX.
- I'm not set on whether the issue is on 1password client side (as it seems there is a check on the binary) or on Polkit side.
- The original issue was with a binary compiled with Graalvm, but the symptoms and logs are exactly the same with this minimal example. If needed I can build a minimal reproduction case with a Graalvm native binary though.
0 -
Hey @pierrebeitz ,
Thank you for reaching out to us!
I think you just uncovered a bug :D The issue here seems to be that the 1Password application enforces, on Linux, that the parent caller of the CLI would be owned by root. While in a normal use-case, such as making a CLI command from bash, this would not become apparent, it seems that in this case, since the/home/$USER/.asdf/installs/java/temurin-11.0.15+10/bin/java
file is most likely not owned by root, it does not pass this check.Although I do not have a Linux system to run local tests on and to try to reproduce this issue, there are a couple of things that come to mind that you could try, in order to try to address this problem:
- prefix the
op
command by/bin/bash -c
. This should ensure that the parent of theop
command is bash, which is owned already by root - try changing the ownership of your java build to root, or install an alternative java version to be owned by root
These being said, we do realise that this is indeed not in line with what happens on the other OS's, and, from a security standpoint, it does not bring too much to the table, so I have opened an internal ticket for investigating getting rid of this check. I'll make sure to update you when any developments are made there. In the meantime, please, let us know if any of the workarounds from above would work for you. Otherwise, I'm going to set up a VM with a test environment, where hopefully I'll be able to come up with new ideas.
Looking forward to hearing from you!
Best,
Horia0 - prefix the
-
Hello @Horia.Culea_1P
Thanks for your answer. Sadly none of the proposed workarounds seem to change a thing:
- Modifying the java code like this:
List<String> commands = Arrays.asList("/bin/bash", "-c", "op vault ls");
I observe the same error message and the same log injournalctl
. - Modifying the binary permission, I observe the same error message and the same log in
journalctl
.
Error message:
[ERROR] 2022/07/21 09:16:04 connecting to desktop app: connection reset, make sure the CLI is correctly installed and CLI Biometric Unlock is enabled in the 1Password app
Log:
Jul 21 09:16:04 *** 1password.desktop[4511]: WARN 2022-07-21T09:16:04.984 tokio-runtime-worker(ThreadId(1)) [1P:foundation/op-sys-info/src/process_information/linux.rs:247] binary permission verification failed for /home/$USER/.asdf/installs/java/temurin-11.0.15+10/bin/java
Just to be aligned on the permissions:
$ ls -al /home/$USER/.asdf/installs/java/temurin-11.0.15+10/bin/java -rwxr-xr-x 1 root root 12768 Apr 19 21:38 /home/***/.asdf/installs/java/temurin-11.0.15+10/bin/java
And for the sake of completeness, I even ran
chmod 777 /home/$USER/.asdf/installs/java/temurin-11.0.15+10/bin/java
to make sure I wasn't missing another linux permission. This resulted in the exact same error and log.
I must admit I'm getting curious about this linesrc/process_information/linux.rs:247
:)Regards
0 - Modifying the java code like this:
-
Hey @pierrebeitz !
Apologies for the late reply here. I have an idea of what could be happening here. Could you maybe try a slight variation of the
/bin/bash -c
workaround?- Create a file
op.sh
with the following content:
#!/bin/bash op ${@}
chmod +x ./op.sh
- Replace
op
withop.sh
in your Java code.
I would expect this to do the trick because in contrast to
/bin/bash -c
, the above script does spawnop
as a child ofbash
. That should satisfy the existing security check.I must admit I'm getting curious about this line src/process_information/linux.rs:247 :)
Haha, so would I! It's actually a security check that existed before the CLI integration was built and this code was only used by our browser extensions. It still exists because taking out a security check is not easy and until now, it has never caused any problems. Now that we know it can cause some problems, we will re-evaluate whether it is still required. However, because we err on the side of caution when it comes to security, I cannot make any commitments on if and when this will happen if we can find a workaround.
Let me know if the above workaround fixes the problem!
Joris
0 - Create a file
-
This seems to work.
0 -
Hello @Joris_1P
Sorry for the delay. I confirm the provided workaround works.
Thanks for the detailed answer about the legacy reasons for the security check.Pierre
0 -
Glad we could help!
0