feat: differentiate core and plugin classes by ClassLoader to avoid shadowing
改用 StackWalker(RETAIN_CLASS_REFERENCE) 在判定时获取栈帧真实 Class 的 ClassLoader,仅 PluginClassLoader 加载的类才可能判为可疑;伪造官方包名的插件被拦截,官方同名类不再被连坐。编译目标升至 Java 11。
This commit is contained in:
16
pom.xml
16
pom.xml
@@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
<groupId>com.novitechie</groupId>
|
<groupId>com.novitechie</groupId>
|
||||||
<artifactId>plugin-privacy</artifactId>
|
<artifactId>plugin-privacy</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.2.0</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>8</maven.compiler.source>
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
<maven.compiler.target>8</maven.compiler.target>
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
<build>
|
<build>
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.7.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>8</source>
|
<source>11</source>
|
||||||
<target>8</target>
|
<target>11</target>
|
||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
<compilerArgument>-XDignore.symbol.file</compilerArgument>
|
||||||
<fork>true</fork>
|
<fork>true</fork>
|
||||||
@@ -65,6 +65,12 @@
|
|||||||
<artifactId>ja-netfilter</artifactId>
|
<artifactId>ja-netfilter</artifactId>
|
||||||
<version>2025.3.0</version>
|
<version>2025.3.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.sun</groupId>
|
||||||
|
<artifactId>tools</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import java.util.regex.Pattern;
|
|||||||
public class StackTraceRule {
|
public class StackTraceRule {
|
||||||
|
|
||||||
private static final Pattern PACKAGE_NAME_PATTERN = Pattern.compile("\\A\\p{ASCII}*\\z");
|
private static final Pattern PACKAGE_NAME_PATTERN = Pattern.compile("\\A\\p{ASCII}*\\z");
|
||||||
|
private static final String PLUGIN_CLASS_LOADER_NAME = "com.intellij.ide.plugins.cl.PluginClassLoader";
|
||||||
|
private static final StackWalker WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
|
||||||
|
|
||||||
private static List<FilterRule> traceCheckPackageRules = Collections.emptyList();
|
private static List<FilterRule> traceCheckPackageRules = Collections.emptyList();
|
||||||
|
|
||||||
public static void initRules(List<FilterRule> traceCheckPackageRules) {
|
public static void initRules(List<FilterRule> traceCheckPackageRules) {
|
||||||
@@ -21,24 +24,30 @@ public class StackTraceRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean check() {
|
public static boolean check() {
|
||||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
return WALKER.walk(frames -> frames.anyMatch(StackTraceRule::isSuspiciousFrame));
|
||||||
for (StackTraceElement stackTraceElement : stackTrace) {
|
}
|
||||||
if (isSuspiciousFrame(stackTraceElement)) {
|
|
||||||
|
static boolean isSuspiciousFrame(StackWalker.StackFrame frame) {
|
||||||
|
Class<?> declaringClass = frame.getDeclaringClass();
|
||||||
|
return isSuspicious(frame.getMethodName(), declaringClass.getName(), declaringClass.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isSuspicious(String methodName, String className, ClassLoader classLoader) {
|
||||||
|
if (!PACKAGE_NAME_PATTERN.matcher(methodName).matches()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (methodName.length() <= 1 && checkTracePackage(className) && isLoadedByPluginClassLoader(classLoader)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isSuspiciousFrame(StackTraceElement stackTraceElement) {
|
static boolean isLoadedByPluginClassLoader(ClassLoader classLoader) {
|
||||||
String methodName = stackTraceElement.getMethodName();
|
if (classLoader == null) {
|
||||||
if (!PACKAGE_NAME_PATTERN.matcher(methodName).matches()) {
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (methodName.length() <= 1) {
|
for (Class<?> type = classLoader.getClass(); type != null; type = type.getSuperclass()) {
|
||||||
String className = stackTraceElement.getClassName();
|
if (PLUGIN_CLASS_LOADER_NAME.equals(type.getName())) {
|
||||||
if (checkTracePackage(className)) {
|
|
||||||
// DebugInfo.info("short method frame, className: " + className + ", methodName: " + methodName);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user