Skip to content

Commit

Permalink
signature added and version bumped in prep for release
Browse files Browse the repository at this point in the history
  • Loading branch information
nahsra committed Sep 6, 2023
1 parent 3f39783 commit c65109e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ In Maven:
<dependency>
<groupId>io.github.pixee</groupId>
<artifactId>java-security-toolkit</artifactId>
<version>1.0.6</version>
<version>1.0.7</version>
</dependency>
```
In Gradle:
```kotlin
implementation("io.github.pixee:java-security-toolkit:1.0.6")
implementation("io.github.pixee:java-security-toolkit:1.0.7")
```

## Contributing
## Contributing
We'd love to get contributions! See [CONTRIBUTING.md](CONTRIBUTING.md).

### Building
Expand Down
33 changes: 32 additions & 1 deletion src/main/java/io/github/pixee/security/Reflection.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ public static Class<?> loadAndVerify(final String name) throws ClassNotFoundExce
return loadAndVerify(name, defaultRestrictions());
}

/**
* This method sandboxes the classloading to prevent possibly dangerous types from being loaded,
* using the default restrictions.
*
* @param name the name of the type to load
* @param initialize whether to initialize the class, passed to {@link Class#forName(String,
* boolean, ClassLoader)}
* @param loader the ClassLoader to use, passed to {@link Class#forName(String, boolean,
* ClassLoader)}
* @throws ClassNotFoundException if the class is not found
* @return the result of {@link Class#forName(String)}, if it passes the default restrictions
*/
public static Class<?> loadAndVerify(
final String name, final boolean initialize, final ClassLoader loader)
throws ClassNotFoundException {
return loadAndVerify(
name, defaultRestrictions(), () -> Class.forName(name, initialize, loader));
}

/**
* This method sandboxes the classloading to prevent possibly dangerous types from being loaded.
*
Expand All @@ -72,6 +91,14 @@ public static Class<?> loadAndVerify(final String name) throws ClassNotFoundExce
public static Class<?> loadAndVerify(
final String name, final Set<ReflectionRestrictions> restrictions)
throws ClassNotFoundException {
return loadAndVerify(name, restrictions, () -> Class.forName(name));
}

private static Class<?> loadAndVerify(
final String name,
final Set<ReflectionRestrictions> restrictions,
final ClassSupplier classSupplier)
throws ClassNotFoundException {

// we can do this check up front before we even load the type
if (restrictions.contains(ReflectionRestrictions.MUST_NOT_INVOLVE_CODE_EXECUTION)) {
Expand All @@ -83,7 +110,7 @@ public static Class<?> loadAndVerify(
}

// load the type so we can do the other checks
final Class<?> type = Class.forName(name);
final Class<?> type = classSupplier.get();

if (restrictions.contains(ReflectionRestrictions.MUST_BE_PUBLIC)) {
final int modifiers = type.getModifiers();
Expand Down Expand Up @@ -116,5 +143,9 @@ public static Class<?> loadAndVerify(
"groovy.",
"org.python.");

private interface ClassSupplier {
Class<?> get() throws ClassNotFoundException;
}

private static final String typeNotAllowedMessage = "type not allowed";
}
13 changes: 12 additions & 1 deletion src/test/java/io/github/pixee/security/ReflectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

/** Test the protections of {@link Reflection}. */
final class ReflectionTest {

@ParameterizedTest
Expand All @@ -26,6 +27,11 @@ void it_protects_dangerous_reflection(final String type) {

// run the same test and confirm that the defaultRestrictions() returns this
assertThrows(SecurityException.class, () -> Reflection.loadAndVerify(type));

// run the same test again on the other signature
assertThrows(
SecurityException.class,
() -> Reflection.loadAndVerify(type, true, getClass().getClassLoader()));
}

@Test
Expand All @@ -38,7 +44,10 @@ void it_enforces_public_restriction() throws ClassNotFoundException {
Reflection.loadAndVerify(
ReflectionTest.class.getName(), setOf(ReflectionRestrictions.MUST_BE_PUBLIC)));

// the type we're testing is public and so we should be able to load it
// the type we're testing is public, and so we should be able to load it
Reflection.loadAndVerify(
Reflection.class.getName(), setOf(ReflectionRestrictions.MUST_BE_PUBLIC));

Reflection.loadAndVerify(
Reflection.class.getName(), setOf(ReflectionRestrictions.MUST_BE_PUBLIC));
}
Expand All @@ -53,6 +62,8 @@ void it_enforces_public_restriction() throws ClassNotFoundException {
void it_loads_normal_classes(final String typeName) throws ClassNotFoundException {
Class<?> type = Reflection.loadAndVerify(typeName);
assertThat(type, is(not(nullValue())));
type = Reflection.loadAndVerify(typeName, true, getClass().getClassLoader());
assertThat(type, is(not(nullValue())));
}

@Test
Expand Down

0 comments on commit c65109e

Please sign in to comment.