From 281850b39a60da65c95b889b697208f224a7dc19 Mon Sep 17 00:00:00 2001 From: "pixeebot[bot]" <104101892+pixeebot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 08:12:02 -0400 Subject: [PATCH 1/3] Protect `readLine()` against DoS (#1) Co-authored-by: pixeebot[bot] <23113631+pixeebot@users.noreply.github.com> --- pom.xml | 12 ++++++++++++ src/java/com/vaklinov/zcashui/AddressBookPanel.java | 5 +++-- src/java/com/vaklinov/zcashui/LanguageUtil.java | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index b9b63c2e..12910433 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,7 @@ UTF-8 1.8 ${project.basedir} + 1.0.7 @@ -55,6 +56,11 @@ minimal-json 0.9.5 + + io.github.pixee + java-security-toolkit + ${versions.java-security-toolkit} + @@ -135,4 +141,10 @@ + + + io.github.pixee + java-security-toolkit + + diff --git a/src/java/com/vaklinov/zcashui/AddressBookPanel.java b/src/java/com/vaklinov/zcashui/AddressBookPanel.java index b75af0ef..85596b54 100644 --- a/src/java/com/vaklinov/zcashui/AddressBookPanel.java +++ b/src/java/com/vaklinov/zcashui/AddressBookPanel.java @@ -2,6 +2,7 @@ // Taken from repository https://github.com/zlatinb/zcash-swing-wallet-ui under an MIT licemse package com.vaklinov.zcashui; +import io.github.pixee.security.BoundedLineReader; import java.awt.BorderLayout; import java.awt.Component; import java.awt.FlowLayout; @@ -139,7 +140,7 @@ private void loadEntriesFromDisk() throws IOException { return; try (BufferedReader bufferedReader = new BufferedReader(new FileReader(addressBookFile))) { String line; - while((line = bufferedReader.readLine()) != null) { + while((line = BoundedLineReader.readLine(bufferedReader, 5_000_000)) != null) { // format is address,name - this way name can contain commas ;-) int addressEnd = line.indexOf(','); if (addressEnd < 0) @@ -361,4 +362,4 @@ public Object getValueAt(int rowIndex, int columnIndex) { } } } -} \ No newline at end of file +} diff --git a/src/java/com/vaklinov/zcashui/LanguageUtil.java b/src/java/com/vaklinov/zcashui/LanguageUtil.java index 5c5bbf90..3270dd38 100644 --- a/src/java/com/vaklinov/zcashui/LanguageUtil.java +++ b/src/java/com/vaklinov/zcashui/LanguageUtil.java @@ -1,5 +1,6 @@ package com.vaklinov.zcashui; +import io.github.pixee.security.BoundedLineReader; import javax.swing.*; import java.io.*; import java.text.MessageFormat; @@ -85,7 +86,7 @@ public Locale getUsersPreferredLocale() { return DEFAULT_LOCALE; } BufferedReader bufferedReader = new BufferedReader(new FileReader(languagePrefsFile)); - String country = bufferedReader.readLine().trim(); + String country = BoundedLineReader.readLine(bufferedReader, 5_000_000).trim(); bufferedReader.close(); return supportedLocale.get(country); } catch (FileNotFoundException e) { From 63b4526c4d3e1d1f121b411e60e8f38ab25286b4 Mon Sep 17 00:00:00 2001 From: "pixeebot[bot]" <104101892+pixeebot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 18:59:18 -0500 Subject: [PATCH 2/3] Introduced protections against system command injection (#2) Co-authored-by: pixeebot[bot] <23113631+pixeebot@users.noreply.github.com> --- src/java/com/vaklinov/zcashui/CommandExecutor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/java/com/vaklinov/zcashui/CommandExecutor.java b/src/java/com/vaklinov/zcashui/CommandExecutor.java index c09067d6..b178cd64 100644 --- a/src/java/com/vaklinov/zcashui/CommandExecutor.java +++ b/src/java/com/vaklinov/zcashui/CommandExecutor.java @@ -29,6 +29,7 @@ package com.vaklinov.zcashui; +import io.github.pixee.security.SystemCommand; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; @@ -53,7 +54,7 @@ public CommandExecutor(String args[]) public Process startChildProcess() throws IOException { - return Runtime.getRuntime().exec(args); + return SystemCommand.runCommand(Runtime.getRuntime(), args); } @@ -63,7 +64,7 @@ public String execute() final StringBuffer result = new StringBuffer(); Runtime rt = Runtime.getRuntime(); - Process proc = rt.exec(args); + Process proc = SystemCommand.runCommand(rt, args); final Reader in = new InputStreamReader(new BufferedInputStream(proc.getInputStream())); From 63e088c8f84a707920610b7ff7b7d0416d7505f7 Mon Sep 17 00:00:00 2001 From: "pixeebot[bot]" <104101892+pixeebot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:23:56 +0000 Subject: [PATCH 3/3] Switch order of literals to prevent NullPointerException --- .../com/vaklinov/zcashui/DashboardPanel.java | 16 ++++++++-------- src/java/com/vaklinov/zcashui/HorizenUI.java | 2 +- .../zcashui/TransactionsDetailPanel.java | 16 ++++++++-------- .../com/vaklinov/zcashui/ZCashClientCaller.java | 16 ++++++++-------- .../zcashui/ZendParametersEditDialog.java | 2 +- .../com/vaklinov/zcashui/msg/MessagingPanel.java | 2 +- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/java/com/vaklinov/zcashui/DashboardPanel.java b/src/java/com/vaklinov/zcashui/DashboardPanel.java index 50b505a0..0be95b8b 100644 --- a/src/java/com/vaklinov/zcashui/DashboardPanel.java +++ b/src/java/com/vaklinov/zcashui/DashboardPanel.java @@ -697,13 +697,13 @@ private String[][] getTransactionsDataFromWallet() public int compare(String[] o1, String[] o2) { Date d1 = new Date(0); - if ((!o1[4].equals("N/A")) && (Util.isNumeric(o1[4]))) + if ((!"N/A".equals(o1[4])) && (Util.isNumeric(o1[4]))) { d1 = new Date(Long.valueOf(o1[4]).longValue() * 1000L); } Date d2 = new Date(0); - if (!o2[4].equals("N/A") && Util.isNumeric(o2[4])) + if (!"N/A".equals(o2[4]) && Util.isNumeric(o2[4])) { d2 = new Date(Long.valueOf(o2[4]).longValue() * 1000L); } @@ -724,22 +724,22 @@ public int compare(String[] o1, String[] o2) for (String[] trans : allTransactions) { // Direction - if (trans[1].equals("receive")) + if ("receive".equals(trans[1])) { trans[1] = "\u21E8 IN"; - } else if (trans[1].equals("send")) + } else if ("send".equals(trans[1])) { trans[1] = "\u21E6 OUT"; - } else if (trans[1].equals("generate")) + } else if ("generate".equals(trans[1])) { trans[1] = "\u2692\u2699 MINED"; - } else if (trans[1].equals("immature")) + } else if ("immature".equals(trans[1])) { trans[1] = "\u2696 Immature"; }; // Date - if ((!trans[4].equals("N/A")) && Util.isNumeric(trans[4])) + if ((!"N/A".equals(trans[4])) && Util.isNumeric(trans[4])) { trans[4] = new Date(Long.valueOf(trans[4]).longValue() * 1000L).toLocaleString(); } @@ -762,7 +762,7 @@ public int compare(String[] o1, String[] o2) // Confirmed? try { - boolean isConfirmed = !trans[2].trim().equals("0"); + boolean isConfirmed = !"0".equals(trans[2].trim()); trans[2] = isConfirmed ? (langUtil.getString("panel.dashboard.table.transactions.confirmed.yes") + confirmedSymbol) : diff --git a/src/java/com/vaklinov/zcashui/HorizenUI.java b/src/java/com/vaklinov/zcashui/HorizenUI.java index 4f32da45..61ae1057 100644 --- a/src/java/com/vaklinov/zcashui/HorizenUI.java +++ b/src/java/com/vaklinov/zcashui/HorizenUI.java @@ -624,7 +624,7 @@ public static void main(String argv[]) for (LookAndFeelInfo ui : UIManager.getInstalledLookAndFeels()) { Log.info("Available look and feel: " + ui.getName() + " " + ui.getClassName()); - if (ui.getName().equals("Nimbus")) + if ("Nimbus".equals(ui.getName())) { Log.info("Setting look and feel: {0}", ui.getClassName()); UIManager.setLookAndFeel(ui.getClassName()); diff --git a/src/java/com/vaklinov/zcashui/TransactionsDetailPanel.java b/src/java/com/vaklinov/zcashui/TransactionsDetailPanel.java index b844d7c4..75018563 100644 --- a/src/java/com/vaklinov/zcashui/TransactionsDetailPanel.java +++ b/src/java/com/vaklinov/zcashui/TransactionsDetailPanel.java @@ -246,13 +246,13 @@ private String[][] getTransactionsDataFromWallet() public int compare(String[] o1, String[] o2) { Date d1 = new Date(0); - if ((!o1[4].equals("N/A")) && Util.isNumeric(o1[4])) + if ((!"N/A".equals(o1[4])) && Util.isNumeric(o1[4])) { d1 = new Date(Long.valueOf(o1[4]).longValue() * 1000L); } Date d2 = new Date(0); - if (!o2[4].equals("N/A") && Util.isNumeric(o2[4])) + if (!"N/A".equals(o2[4]) && Util.isNumeric(o2[4])) { d2 = new Date(Long.valueOf(o2[4]).longValue() * 1000L); } @@ -287,22 +287,22 @@ public int compare(String[] o1, String[] o2) for (String[] trans : allTransactions) { // Direction - if (trans[1].equals("receive")) + if ("receive".equals(trans[1])) { trans[1] = "\u21E8 IN"; - } else if (trans[1].equals("send")) + } else if ("send".equals(trans[1])) { trans[1] = "\u21E6 OUT"; - } else if (trans[1].equals("generate")) + } else if ("generate".equals(trans[1])) { trans[1] = "\u2692\u2699 MINED"; - } else if (trans[1].equals("immature")) + } else if ("immature".equals(trans[1])) { trans[1] = "\u2696 Immature"; }; // Date - if ((!trans[4].equals("N/A")) && Util.isNumeric(trans[4])) + if ((!"N/A".equals(trans[4])) && Util.isNumeric(trans[4])) { trans[4] = new Date(Long.valueOf(trans[4]).longValue() * 1000L).toLocaleString(); } @@ -325,7 +325,7 @@ public int compare(String[] o1, String[] o2) // Confirmed? try { - boolean isConfirmed = !trans[2].trim().equals("0"); + boolean isConfirmed = !"0".equals(trans[2].trim()); trans[2] = isConfirmed ? (langUtil.getString("transactions.detail.panel.yes", confirmed)) : (langUtil.getString("transactions.detail.panel.no", notConfirmed)); diff --git a/src/java/com/vaklinov/zcashui/ZCashClientCaller.java b/src/java/com/vaklinov/zcashui/ZCashClientCaller.java index 9f843d4d..de724eb1 100644 --- a/src/java/com/vaklinov/zcashui/ZCashClientCaller.java +++ b/src/java/com/vaklinov/zcashui/ZCashClientCaller.java @@ -335,7 +335,7 @@ public synchronized String[][] getWalletZReceivedTransactions() this.transactionConfirmations.clear(); } String confirmations = this.transactionConfirmations.get(txID); - if ((confirmations == null) || confirmations.equals("0")) + if ((confirmations == null) || "0".equals(confirmations)) { currentTransaction[2] = this.getWalletTransactionConfirmations(txID); this.transactionConfirmations.put(txID, currentTransaction[2]); @@ -860,7 +860,7 @@ public synchronized boolean verifyMessage(String address, String signature, Stri wrapStringParameter(signature), wrapStringParameter(message)); - return response.trim().equalsIgnoreCase("true"); + return "true".equalsIgnoreCase(response.trim()); } @@ -875,12 +875,12 @@ public synchronized boolean isSendingOperationComplete(String opID) Log.info("Operation " + opID + " status is " + response + "."); - if (status.equalsIgnoreCase("success") || - status.equalsIgnoreCase("error") || - status.equalsIgnoreCase("failed")) + if ("success".equalsIgnoreCase(status) || + "error".equalsIgnoreCase(status) || + "failed".equalsIgnoreCase(status)) { return true; - } else if (status.equalsIgnoreCase("executing") || status.equalsIgnoreCase("queued")) + } else if ("executing".equalsIgnoreCase(status) || "queued".equalsIgnoreCase(status)) { return false; } else @@ -901,10 +901,10 @@ public synchronized boolean isCompletedOperationSuccessful(String opID) Log.info("Operation " + opID + " status is " + response + "."); - if (status.equalsIgnoreCase("success")) + if ("success".equalsIgnoreCase(status)) { return true; - } else if (status.equalsIgnoreCase("error") || status.equalsIgnoreCase("failed")) + } else if ("error".equalsIgnoreCase(status) || "failed".equalsIgnoreCase(status)) { return false; } else diff --git a/src/java/com/vaklinov/zcashui/ZendParametersEditDialog.java b/src/java/com/vaklinov/zcashui/ZendParametersEditDialog.java index 014b6068..8b3916da 100644 --- a/src/java/com/vaklinov/zcashui/ZendParametersEditDialog.java +++ b/src/java/com/vaklinov/zcashui/ZendParametersEditDialog.java @@ -382,7 +382,7 @@ private boolean isMultiOccurrenceOption(String fullParam) { String paramName = this.getParamName(fullParam); - return paramName.equals("addnode"); // For now only addnode seems to be a multi-occur option + return "addnode".equals(paramName); // For now only addnode seems to be a multi-occur option } diff --git a/src/java/com/vaklinov/zcashui/msg/MessagingPanel.java b/src/java/com/vaklinov/zcashui/msg/MessagingPanel.java index 31e700c8..a421061c 100644 --- a/src/java/com/vaklinov/zcashui/msg/MessagingPanel.java +++ b/src/java/com/vaklinov/zcashui/msg/MessagingPanel.java @@ -1593,7 +1593,7 @@ private void collectAndStoreNewReceivedMessages(MessagingIdentity groupIdentity) { String memoHex = trans.getString("memo", "ERROR"); String transactionID = trans.getString("txid", "ERROR"); - if (!memoHex.equals("ERROR")) + if (!"ERROR".equals(memoHex)) { String decodedMemo = Util.decodeHexMemo(memoHex); JsonObject jsonMessage = null;