imbajin commented on code in PR #2918:
URL:
https://github.com/apache/incubator-hugegraph/pull/2918#discussion_r2626371921
##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/CompressUtil.java:
##########
@@ -158,17 +158,17 @@ public static void decompressTar(String sourceFile,
String outputDir,
}
}
- private static Path zipSlipProtect(ArchiveEntry entry, Path targetDir)
+ private static Path zipSlipProtect(String fileName, Path targetDir)
Review Comment:
‼️ **Critical: Zip slip protection weakened**
The refactoring changes `zipSlipProtect` to accept `String fileName` instead
of `ArchiveEntry entry`, but this removes access to other entry properties that
might be needed for security validation. While the current implementation only
uses `entry.getName()`, accepting the full entry object is a better practice
for:
1. Future security enhancements that might need to validate other entry
properties
2. Consistency with security-focused APIs that typically pass full objects
Consider keeping the `ArchiveEntry` parameter:
```suggestion
private static Path zipSlipProtect(ArchiveEntry entry, Path targetDir)
throws IOException {
Path targetDirResolved = targetDir.resolve(entry.getName());
```
##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/CompressUtil.java:
##########
@@ -220,9 +220,7 @@ public static void decompressZip(String sourceFile, String
outputDir,
ZipInputStream zis = new ZipInputStream(bis)) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
- String fileName = entry.getName();
- File entryFile = new File(Paths.get(outputDir, fileName)
- .toString());
+ File entryFile = new File(zipSlipProtect(entry.getName(),
Paths.get(outputDir)).toString());
Review Comment:
⚠️ **Important: Code formatting inconsistency**
This line is too long and hard to read. The original multi-line format was
more maintainable:
```suggestion
String fileName = entry.getName();
Path entryPath = zipSlipProtect(fileName,
Paths.get(outputDir));
File entryFile = new File(entryPath.toString());
```
This improves:
- Readability by keeping lines under 100 characters
- Debuggability by allowing breakpoints on each step
- Maintainability by separating concerns
##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java:
##########
@@ -140,7 +140,8 @@ public static String decompress(byte[] value, float
bufferRatio) {
}
public static String hashPassword(String password) {
- return BCrypt.hashpw(password, BCrypt.gensalt(4));
+ // OWASP suggest 10 as minimum and 12-14 as production default
+ return BCrypt.hashpw(password, BCrypt.gensalt(12));
Review Comment:
‼️ **Critical: Breaking change for existing users**
Increasing BCrypt cost factor from 4 to 12 is a **256x increase** in
computation time (2^8). While 12 is the recommended value, this change will:
1. **Break existing password hashes**: Old passwords hashed with cost=4
won't match if the application re-hashes on login
2. **Impact performance**: Password operations will be significantly slower
3. **Require migration strategy**: Need a plan to rehash existing passwords
Recommendation:
```suggestion
public static String hashPassword(String password) {
// OWASP recommends 12-14 for production, but use 10 as default to
balance security and performance
// TODO: Implement gradual migration from legacy cost=4 hashes
return BCrypt.hashpw(password, BCrypt.gensalt(10));
}
```
Add a migration path:
1. Check hash cost on login using `BCrypt.getRounds()`
2. If cost < 10, rehash with new cost
3. Document the breaking change in release notes
##########
hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java:
##########
@@ -165,7 +165,8 @@ public static String decompress(byte[] value, float
bufferRatio) {
}
public static String hashPassword(String password) {
- return BCrypt.hashpw(password, BCrypt.gensalt(4));
+ // OWASP suggest 10 as minimum and 12-14 as production default
+ return BCrypt.hashpw(password, BCrypt.gensalt(12));
Review Comment:
⚠️ **Important: Duplicate code across modules**
The same BCrypt cost change is duplicated in
`hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java`.
This creates maintenance burden.
Consider:
1. Consolidating the implementation in one place
2. Making the cost factor configurable
3. Adding a constant: `private static final int BCRYPT_COST_FACTOR = 12;`
This would centralize the security policy and make future updates easier.
##########
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/StringEncodingTest.java:
##########
@@ -180,4 +181,18 @@ public void testReadAsciiString() {
buf = Bytes.fromHex("80");
Assert.assertEquals("", StringEncoding.readAsciiString(buf, 0));
}
+
+ @Test
+ public void testCheckPasswordSupportsOldAndNewCost() {
+ // oldWorkFactor
+ String oldPassword = BCrypt.hashpw("123456", BCrypt.gensalt(4));
+ // newWorkFactor
+ String newPassword = BCrypt.hashpw("123456", BCrypt.gensalt(12));
+
+ Assert.assertTrue(StringEncoding.checkPassword("123456", oldPassword));
+ Assert.assertTrue(StringEncoding.checkPassword("123456", newPassword));
Review Comment:
🧹 **Minor: Test coverage could be improved**
The test validates backward compatibility but could be more comprehensive:
```suggestion
@Test
public void testCheckPasswordSupportsOldAndNewCost() {
String testPassword = "test123!@#";
// Test old work factor (4)
String oldPassword = BCrypt.hashpw(testPassword, BCrypt.gensalt(4));
Assert.assertTrue(StringEncoding.checkPassword(testPassword,
oldPassword));
Assert.assertFalse(StringEncoding.checkPassword("wrong",
oldPassword));
// Test new work factor (12)
String newPassword = BCrypt.hashpw(testPassword, BCrypt.gensalt(12));
Assert.assertTrue(StringEncoding.checkPassword(testPassword,
newPassword));
Assert.assertFalse(StringEncoding.checkPassword("wrong",
newPassword));
// Test that hashPassword uses the new cost factor
String hashedPassword = StringEncoding.hashPassword(testPassword);
Assert.assertTrue(StringEncoding.checkPassword(testPassword,
hashedPassword));
// Verify new hashes use cost=12 (though this is
implementation-dependent)
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]