diff --git a/uut-example/java/src/main/java/com/keyware/sonar/ABCVarNameRule.java b/uut-example/java/src/main/java/com/keyware/sonar/ABCVarNameRule.java
new file mode 100644
index 0000000..10e4b71
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/ABCVarNameRule.java
@@ -0,0 +1,14 @@
+public class ABCVarNameRule {
+
+ private static String ABC = "abc"; // Noncompliant {{不能使用ABC作为变量名}}
+ private static String edf = "edf";
+
+ public String getABC(){
+ return ABC;
+ }
+ public void test(){
+ System.out.println(ABC);
+ }
+
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/AbsolutePathDetectorRule.java b/uut-example/java/src/main/java/com/keyware/sonar/AbsolutePathDetectorRule.java
new file mode 100644
index 0000000..0b44079
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/AbsolutePathDetectorRule.java
@@ -0,0 +1,18 @@
+
+public class AbsolutePathDetectorRule{
+ // 使用绝对路径读取配置文件,触发规则
+ String configFilePath = "/path/to/config.properties"; // Noncompliant {{读取配置文件或者服务器中文件时不可使用绝对路径}}
+
+ // 使用相对路径读取配置文件,不触发规则
+ String relativePath = "config.properties";
+
+ public String getABC(){
+ return configFilePath;
+ }
+
+ public void test(){
+ System.out.println(configFilePath);
+ }
+
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/AuthenticationChecker.java b/uut-example/java/src/main/java/com/keyware/sonar/AuthenticationChecker.java
new file mode 100644
index 0000000..c341e76
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/AuthenticationChecker.java
@@ -0,0 +1,24 @@
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class AuthenticationChecker {
+
+ @PostMapping("/account/aa")
+ public String login() {
+ return "login";
+ }
+
+
+ @PostMapping(value ={"/path/bb", "/path/www", "/path/eee"})
+ public String signin() {
+ return "login";
+ }
+
+ @RequestMapping("/myapp/cc")
+ public String auth() {
+ return "login";
+ }
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/AvoidSensitiveInfoInLogsCheck.java b/uut-example/java/src/main/java/com/keyware/sonar/AvoidSensitiveInfoInLogsCheck.java
new file mode 100644
index 0000000..0135c54
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/AvoidSensitiveInfoInLogsCheck.java
@@ -0,0 +1,19 @@
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+public class AvoidSensitiveInfoInLogsCheck {
+ private static final Logger logger = LoggerFactory.getLogger(AvoidSensitiveInfoInLogsCheck.class);
+
+ public void sensitiveOperation() {
+ String password = "password";
+ String token = "password";
+ String secret = "password";
+
+
+ logger.error(password); // Noncompliant {{日志中包含敏感信息}}
+ logger.info(token); // Noncompliant {{日志中包含敏感信息}}
+ logger.debug(secret); // Noncompliant {{日志中包含敏感信息}}
+ logger.warn(password); // Noncompliant {{日志中包含敏感信息}}
+ logger.trace(password); // Noncompliant {{日志中包含敏感信息}}
+
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/CookieSensitiveParameterCheck.java b/uut-example/java/src/main/java/com/keyware/sonar/CookieSensitiveParameterCheck.java
new file mode 100644
index 0000000..08531da
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/CookieSensitiveParameterCheck.java
@@ -0,0 +1,15 @@
+import javax.servlet.http.Cookie;
+
+public class CookieSensitiveParameterCheck {
+
+ public void func1(){
+
+ String password = "";
+
+ Cookie invalidCookie1 = new Cookie("password", "1321"); // Noncompliant {{Cookie参数设置中包含敏感字段}}
+ Cookie invalidCookie2 = new Cookie(password, "1"); // Noncompliant {{Cookie参数设置中包含敏感字段}}
+ Cookie invalidCookie3 = new Cookie("213", password); // Noncompliant {{Cookie参数设置中包含敏感字段}}
+
+ }
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/DynamicCodeCheckerRule.java b/uut-example/java/src/main/java/com/keyware/sonar/DynamicCodeCheckerRule.java
new file mode 100644
index 0000000..a1a3ec8
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/DynamicCodeCheckerRule.java
@@ -0,0 +1,35 @@
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+public class DynamicCodeCheckerRule {
+
+ public void dyan() {
+
+ String args1 = "args1";
+ String args2 = "args2";
+ String args3 = "args3";
+
+ String regular = "function regular(args1,args2,args3){................}";
+ ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
+ try {
+ engine.eval(regular); // Noncompliant {{程序设计时禁止动态构建代码进行功能实现}}
+ if (engine instanceof Invocable) {
+ Invocable invoke = (Invocable) engine;
+ String result = (String) invoke.invokeFunction(
+ "regular",
+ args1,
+ args2,
+ args3);
+ System.out.println(result);
+ } else {
+ System.out.println("error");
+ }
+ } catch (ScriptException | NoSuchMethodException e) {
+ System.out.println("表达式runtime错误:" + e.getMessage());
+ }
+ }
+
+
+}
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/DynamicLibraryLoadChecker.java b/uut-example/java/src/main/java/com/keyware/sonar/DynamicLibraryLoadChecker.java
new file mode 100644
index 0000000..cae1280
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/DynamicLibraryLoadChecker.java
@@ -0,0 +1,10 @@
+// 在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库
+public class DynamicLibraryLoadChecker {
+
+ public void loadLibrary(String libraryName, int number) {
+ String abc = "bac";
+ System.loadLibrary("/path/to/your/library");
+ System.loadLibrary(libraryName); // Noncompliant {{在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库}}
+
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/ErrorMessageRule.java b/uut-example/java/src/main/java/com/keyware/sonar/ErrorMessageRule.java
new file mode 100644
index 0000000..95dfc49
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/ErrorMessageRule.java
@@ -0,0 +1,13 @@
+public class ErrorMessageRule {
+ public static void main(String[] args) {
+ try {
+ String weapon = "A";
+ String a = "1";
+ // Try block to check for exceptions
+ throw new Exception("Java Exception"+weapon + a);// Noncompliant {{错误消息中不得包含敏感信息}}
+ } catch (Exception e) {
+ // Catch block to handle the exception
+ System.out.println("Caught Exception: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/FileCheck.java b/uut-example/java/src/main/java/com/keyware/sonar/FileCheck.java
new file mode 100644
index 0000000..47d46e5
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/FileCheck.java
@@ -0,0 +1,22 @@
+public class FileCheck{
+
+ public String FileName(){
+ String fileName = "";
+ String fileExt = "";
+ String fileSuffix = "";
+
+ if(fileName.endsWith("png") ){// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
+
+ }
+
+ if(fileExt.equals("jpg") ){// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
+
+ }
+
+ if(fileSuffix.equals("jpg")){// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
+
+ }
+ return null;
+ }
+
+}
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/HashSaltPassWordRule.java b/uut-example/java/src/main/java/com/keyware/sonar/HashSaltPassWordRule.java
new file mode 100644
index 0000000..5068c1f
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/HashSaltPassWordRule.java
@@ -0,0 +1,32 @@
+
+public class HashSaltPassWordRule {
+
+ public static void cs(Student student){
+
+ // 结合盐值和口令进行散列计算
+// String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
+
+ student.setPassWord("password");// Noncompliant {{应使用盐值计算口令}}
+
+ }
+
+ static class Student {
+ private String name;
+ private String password;
+
+ public Student(String name, String password) {
+ this.name = name;
+ this.password = password;
+ }
+
+ public void setPassWord(String password) {
+ this.password = password;
+ }
+
+ @Override
+ public String toString() {
+ return "Student{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}';
+ }
+ }
+
+}
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/HttpInputDataRule.java b/uut-example/java/src/main/java/com/keyware/sonar/HttpInputDataRule.java
new file mode 100644
index 0000000..8ee9d4a
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/HttpInputDataRule.java
@@ -0,0 +1,219 @@
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Locale;
+
+public class HttpInputDataRule {
+
+ public static void main(String[] args) {
+ // 假设有一个HttpServletResponse对象
+ HttpServletResponse response = new HttpServletResponse() {
+ @Override
+ public String getCharacterEncoding() {
+ return null;
+ }
+
+ @Override
+ public String getContentType() {
+ return null;
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ return null;
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ return null;
+ }
+
+ @Override
+ public void setCharacterEncoding(String s) {
+
+ }
+
+ @Override
+ public void setContentLength(int i) {
+
+ }
+
+ @Override
+ public void setContentLengthLong(long l) {
+
+ }
+
+ @Override
+ public void setContentType(String s) {
+
+ }
+
+ @Override
+ public void setBufferSize(int i) {
+
+ }
+
+ @Override
+ public int getBufferSize() {
+ return 0;
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+
+ }
+
+ @Override
+ public void resetBuffer() {
+
+ }
+
+ @Override
+ public boolean isCommitted() {
+ return false;
+ }
+
+ @Override
+ public void reset() {
+
+ }
+
+ @Override
+ public void setLocale(Locale locale) {
+
+ }
+
+ @Override
+ public Locale getLocale() {
+ return null;
+ }
+
+ @Override
+ public void addCookie(Cookie cookie) {
+
+ }
+
+ @Override
+ public boolean containsHeader(String s) {
+ return false;
+ }
+
+ @Override
+ public String encodeURL(String s) {
+ return null;
+ }
+
+ @Override
+ public String encodeRedirectURL(String s) {
+ return null;
+ }
+
+ @Override
+ public String encodeUrl(String s) {
+ return null;
+ }
+
+ @Override
+ public String encodeRedirectUrl(String s) {
+ return null;
+ }
+
+ @Override
+ public void sendError(int i, String s) throws IOException {
+
+ }
+
+ @Override
+ public void sendError(int i) throws IOException {
+
+ }
+
+ @Override
+ public void sendRedirect(String s) throws IOException {
+
+ }
+
+ @Override
+ public void setDateHeader(String s, long l) {
+
+ }
+
+ @Override
+ public void addDateHeader(String s, long l) {
+
+ }
+
+ @Override
+ public void setHeader(String s, String s1) {
+
+ }
+
+ @Override
+ public void addHeader(String s, String s1) {
+
+ }
+
+ @Override
+ public void setIntHeader(String s, int i) {
+
+ }
+
+ @Override
+ public void addIntHeader(String s, int i) {
+
+ }
+
+ @Override
+ public void setStatus(int i) {
+
+ }
+
+ @Override
+ public void setStatus(int i, String s) {
+
+ }
+
+ @Override
+ public int getStatus() {
+ return 0;
+ }
+
+ @Override
+ public String getHeader(String s) {
+ return null;
+ }
+
+ @Override
+ public Collection getHeaders(String s) {
+ return null;
+ }
+
+ @Override
+ public Collection getHeaderNames() {
+ return null;
+ }
+ };
+
+ // 设置单个报头
+ response.setHeader("Content-Type", "text/plain"); // Noncompliant {{HTTP输入数据验证}}
+
+ // 添加多个报头
+ String a = "Cache-Control";
+ String b = "no-cache" ;
+ if(a == "asds"){
+
+ }
+ if(b == "asds"){
+
+ }
+
+ response.addHeader(a, b);
+// response.addHeader("X-Custom-Header", "Custom Value");
+
+ // 其他操作...
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/InputSQLVerifyRule.java b/uut-example/java/src/main/java/com/keyware/sonar/InputSQLVerifyRule.java
new file mode 100644
index 0000000..f073695
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/InputSQLVerifyRule.java
@@ -0,0 +1,40 @@
+
+import java.sql.*;
+
+public class InputSQLVerifyRile {
+ private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase";
+ private static final String USER = "username";
+ private static final String PASS = "password";
+
+ public void executeQuery(String userInput) {
+ try {
+ // 获取数据库连接
+ Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
+
+ // 假设我们有一个用户ID字段,我们需要根据用户输入查找记录
+ String sql = "SELECT * FROM users WHERE user_id = ?";
+// if(sql.indexOf("a")){
+//
+// }
+
+ // 创建预编译的Statement(PreparedStatement),用问号作为占位符代替实际值
+ PreparedStatement pstmt = conn.prepareStatement(sql);// Noncompliant {{使用sql语句前应对其进行验证}}
+
+ // 验证用户输入是否符合整数格式(这里仅作简单示例)
+ if (userInput.matches("\\d+")) {
+ int userId = Integer.parseInt(userInput);
+ pstmt.setInt(1, userId);
+
+ // 执行查询
+ ResultSet rs = pstmt.executeQuery();
+
+ // 处理结果集...
+ } else {
+ System.out.println("Invalid input. User ID must be a number.");
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/Md5PassWordVerifyRule.java b/uut-example/java/src/main/java/com/keyware/sonar/Md5PassWordVerifyRule.java
new file mode 100644
index 0000000..5315022
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/Md5PassWordVerifyRule.java
@@ -0,0 +1,29 @@
+public class Md5PassWordVerifyRule{
+ public static void cs(Student student){
+ // 结合盐值和口令进行散列计算
+// String password = DigestUtils.md5Hex(str);
+
+ student.setPassWord("password");// Noncompliant {{应使用单向不可逆的加密算法}}
+
+ }
+
+ static class Student {
+ private String name;
+ private String password;
+
+ public Student(String name, String password) {
+ this.name = name;
+ this.password = password;
+ }
+
+ public void setPassWord(String password) {
+ this.password = password;
+ }
+
+ @Override
+ public String toString() {
+ return "Student{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}';
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/OptionsVerifyRule.java b/uut-example/java/src/main/java/com/keyware/sonar/OptionsVerifyRule.java
new file mode 100644
index 0000000..d475ea5
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/OptionsVerifyRule.java
@@ -0,0 +1,27 @@
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class OptionsVerifyRule implements Filter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {}
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletResponse res = (HttpServletResponse) response;
+ res.addHeader("X-Frame-Options", "DENY");
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {}
+
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+ response.setHeader("X-Frame-Options", "DENY"); // 或者使用SAMEORIGIN,ALLOW-FROM等其他策略
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/PasswordInputTagChecker.html b/uut-example/java/src/main/java/com/keyware/sonar/PasswordInputTagChecker.html
new file mode 100644
index 0000000..35d112c
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/PasswordInputTagChecker.html
@@ -0,0 +1,14 @@
+
+Test for PasswordInputTagChecker
+
+Test for PasswordInputTagChecker
+Test 1 - FAIL
+
+
+
+
+
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/PasswordRegexCheck.java b/uut-example/java/src/main/java/com/keyware/sonar/PasswordRegexCheck.java
new file mode 100644
index 0000000..a504893
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/PasswordRegexCheck.java
@@ -0,0 +1,17 @@
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PasswordRegexCheck {
+
+
+
+ public String isValidPassword(String password) {// Noncompliant {{未对口令进行复杂度验证}}
+ String asdasd = "asdfsdfsdf";
+ Pattern pattern = Pattern.compile("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$");
+ Matcher matcher1 = pattern.matcher(asdasd);
+ Matcher matcher3 = pattern.matcher("");
+ return password;
+ }
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/PathAndKeywordCheck.java b/uut-example/java/src/main/java/com/keyware/sonar/PathAndKeywordCheck.java
new file mode 100644
index 0000000..5000245
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/PathAndKeywordCheck.java
@@ -0,0 +1,14 @@
+
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+
+public class PathAndKeywordCheck {
+
+ public void getParameter(String arg,String brg,String crg) throws Exception {
+ URL url1 = new URL(arg);// Noncompliant {{避免在参数中使用禁止的关键字}}
+ URI url2 = new URI(brg);// Noncompliant {{避免在参数中使用禁止的关键字}}
+ File url3 = new File(crg);// Noncompliant {{避免在参数中使用禁止的关键字}}
+
+ }
+}
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/RSAEncryptionRule.java b/uut-example/java/src/main/java/com/keyware/sonar/RSAEncryptionRule.java
new file mode 100644
index 0000000..9d8186e
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/RSAEncryptionRule.java
@@ -0,0 +1,34 @@
+
+
+import javax.crypto.Cipher;
+import java.security.*;
+
+public class RSAEncryptionRule {
+
+ public static void main(String[] args) throws Exception {
+ // 生成RSA密钥对
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ SecureRandom secureRandom = new SecureRandom();
+ keyPairGenerator.initialize(2048, secureRandom);
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ PublicKey publicKey = keyPair.getPublic();
+ PrivateKey privateKey = keyPair.getPrivate();
+
+ // 待加密的数据
+ String message = "Hello, RSA!";
+
+ // 使用公钥进行加密
+ Cipher encryptCipher = Cipher.getInstance("OAEPWithAndPadding");// Noncompliant {{使用RSA最优加密填充}}
+ encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ byte[] encryptedBytes = encryptCipher.doFinal(message.getBytes());
+
+ // 使用私钥进行解密
+ Cipher decryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
+ decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
+ byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes);
+
+ // 输出结果
+ System.out.println("加密后的数据:" + new String(encryptedBytes));
+ System.out.println("解密后的数据:" + new String(decryptedBytes));
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/RedirectUrlChecker.java b/uut-example/java/src/main/java/com/keyware/sonar/RedirectUrlChecker.java
new file mode 100644
index 0000000..3ff2969
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/RedirectUrlChecker.java
@@ -0,0 +1,41 @@
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.view.RedirectView;
+
+@Controller
+public class RedirectUrlChecker {
+
+ @GetMapping("/old-url")
+ public RedirectView redirectOldUrl(String url) { // Compliant,因为重定向的路径不是由方法传递进来的
+ RedirectView redirectView = new RedirectView();
+ redirectView.setUrl(url);// Noncompliant {{在重定向前对输入数据进行验证}}
+ return redirectView;
+ }
+
+ @GetMapping("/old-url2")
+ public String redirectOldUrl2() { // Compliant,因为重定向的路径不是由方法传递进来的
+ // 302临时重定向到新的URL
+ return "redirect:/new-url";
+ }
+
+ @GetMapping("/old-url3")
+ public RedirectView redirectOldUrl3(String url) {
+ RedirectView redirectView = new RedirectView(url); // Noncompliant {{在重定向前对输入数据进行验证}}
+ redirectView.setUrl(url); // Noncompliant {{在重定向前对输入数据进行验证}}
+ return redirectView;
+ }
+
+ @GetMapping("/old-url4")
+ public String redirectOldUrl4(String url) {
+ // 302临时重定向到新的URL
+ return "redirect:" + url; // Noncompliant {{在重定向前对输入数据进行验证}}
+ }
+
+ @GetMapping("/old-url5")
+ public String redirectOldUrl5(String url) {
+ // 302临时重定向到新的URL
+ return url; // Noncompliant {{在重定向前对输入数据进行验证}}
+ }
+
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/SecurityCookieRule.java b/uut-example/java/src/main/java/com/keyware/sonar/SecurityCookieRule.java
new file mode 100644
index 0000000..e4fa328
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/SecurityCookieRule.java
@@ -0,0 +1,24 @@
+import javax.servlet.http.HttpServletResponse;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+public class SecurityCookieRule {
+
+ public void setCookie(HttpServletResponse response) { // Noncompliant {{设置HTTPS会话中cookie的安全属性}}
+ // 创建一个新的Cookie
+ Cookie cookie = new Cookie("cookieName", "cookieValue");
+
+ // 设置HttpOnly属性(防止通过JavaScript访问)
+ cookie.setHttpOnly(true);
+
+ // 设置Secure属性(表示该Cookie只能通过HTTPS连接传输)
+ cookie.setSecure(true);
+
+ // 设置其他属性,比如过期时间等
+// cookie.setMaxAge(3600); // 有效期为1小时
+
+ // 将Cookie添加到HTTP响应头中
+ response.addCookie(cookie);
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/SendMessageVerifyRule.java b/uut-example/java/src/main/java/com/keyware/sonar/SendMessageVerifyRule.java
new file mode 100644
index 0000000..7bcbef0
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/SendMessageVerifyRule.java
@@ -0,0 +1,25 @@
+import java.io.DataOutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public class SendMessageVerifyRule {
+
+ public static void sendName(String name) {
+ try {
+ ServerSocket ss = new ServerSocket(6666); //建立服务器Socket并绑定端口
+ Socket s = ss.accept();//建立连接
+ DataOutputStream dout = new DataOutputStream(s.getOutputStream());
+ dout.writeUTF(name);//编辑要发送的消息
+ dout.flush();
+ dout.close();
+ ss.close();
+ } catch(Exception e) {
+ System.out.println(e);
+ }
+ }
+
+ public static void main(String[] args){
+ String weapon = "ssss";
+ sendName(weapon );// Noncompliant {{发送信息规则检查}}
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/SessionCacheParamsChecker.java b/uut-example/java/src/main/java/com/keyware/sonar/SessionCacheParamsChecker.java
new file mode 100644
index 0000000..21332be
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/SessionCacheParamsChecker.java
@@ -0,0 +1,35 @@
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+public class SessionCacheParamsChecker {
+
+ private static final long serialVersionUID = 1391640560504378168L;
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response) {
+ // 直接从request获取参数
+ String param = request.getParameter("userId"); // Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
+ request.getParameter("userpassword");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
+ request.getParameter("token");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
+ request.getParameter("url");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
+ // 直接从request获取Cookies
+ Cookie[] cookies = request.getCookies();// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
+ // 将参数存储到session
+ HttpSession session = request.getSession();
+ session.setAttribute("sessionParam", param);
+ // 其他代码...
+ }
+
+ @RestController
+ class TestController{
+
+ @GetMapping("/get")
+ public void get(HttpServletRequest request){
+ String userId = request.getParameter("userId");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
+ }
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/SystemFunctionChecker.java b/uut-example/java/src/main/java/com/keyware/sonar/SystemFunctionChecker.java
new file mode 100644
index 0000000..831b76f
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/SystemFunctionChecker.java
@@ -0,0 +1,16 @@
+
+
+import java.io.IOException;
+
+public class SystemFunctionChecker {
+
+ public void add(String command) throws IOException {
+ Process process = Runtime.getRuntime().exec(command); // Noncompliant {{在构建命令前对输入数据进行验证}}
+
+ }
+
+ public void det(String commands){
+
+ ProcessBuilder pb = new ProcessBuilder(commands);// Noncompliant {{在构建命令前对输入数据进行验证}}
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/UploadFileVerifyRule.java b/uut-example/java/src/main/java/com/keyware/sonar/UploadFileVerifyRule.java
new file mode 100644
index 0000000..c06ede9
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/UploadFileVerifyRule.java
@@ -0,0 +1,53 @@
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+
+@Slf4j
+@RestController
+@RequestMapping("/file")
+public class UploadFileVerifyRule {
+
+ //文件磁盘路径
+ @Value("${files.upload.path}")
+ private String fileUploadPath;
+
+ @PostMapping("/upload")
+ public String upload(@RequestParam MultipartFile file) throws IOException { // Noncompliant {{程序设计时,应以“白名单”方式限制允许用户上传的文件的类型}}
+
+
+
+ long size = file.getSize();
+ if(size > 100){
+
+ }
+ //获取文件原始名称
+ String originalFilename = file.getOriginalFilename();
+ String type = FileUtil.extName(originalFilename);
+// if(type == ""){
+//
+// }
+
+ File localFile = new File(fileUploadPath + File.separator + originalFilename);
+
+ localFile.setExecutable(true);
+ localFile.setReadable(true);
+ localFile.setWritable(true);
+
+ file.transferTo(localFile);
+ return "上传成功";
+ }
+
+ class FileUtil{
+ public static String extName(String filename){
+ // 根据文件名获取文件后缀
+ return filename.substring(filename.lastIndexOf(".") + 1);
+ }
+ }
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/UpperCycleLimitRule.java b/uut-example/java/src/main/java/com/keyware/sonar/UpperCycleLimitRule.java
new file mode 100644
index 0000000..7277eec
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/UpperCycleLimitRule.java
@@ -0,0 +1,17 @@
+public class UpperCycleLimitRule {
+
+ public static void Upper(int number){
+
+ for(int i = 0; i < number; i++){ // Noncompliant {{规定循环次数的上限,在将用户输入的数据用于循环条件前进行验证用户输入的数据是否超过上限}}
+
+ };
+
+ while (number > 0){ // Noncompliant {{规定循环次数的上限,在将用户输入的数据用于循环条件前进行验证用户输入的数据是否超过上限}}
+
+ };
+
+ do{
+
+ }while (number > 0); // Noncompliant {{规定循环次数的上限,在将用户输入的数据用于循环条件前进行验证用户输入的数据是否超过上限}}
+ };
+}
\ No newline at end of file
diff --git a/uut-example/java/src/main/java/com/keyware/sonar/UserStatusVerifyChecker.java b/uut-example/java/src/main/java/com/keyware/sonar/UserStatusVerifyChecker.java
new file mode 100644
index 0000000..cbe3d82
--- /dev/null
+++ b/uut-example/java/src/main/java/com/keyware/sonar/UserStatusVerifyChecker.java
@@ -0,0 +1,72 @@
+import com.fasterxml.classmate.Filter;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+public class UserStatusVerifyChecker {
+
+ private static final long serialVersionUID = 1391640560504378168L;
+
+ static class UserService {
+ public static boolean validate(String username, String password) {
+ return true;
+ }
+ }
+
+ public class AuthenticationFilter implements Filter {
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {// Noncompliant {{对用户进行身份鉴别并建立一个新的会话时让原来的会话失效}}
+ HttpServletRequest request = (HttpServletRequest) req;
+ boolean isValidUser = false;
+// String username = request.getParameter("username");
+// String password = request.getParameter("password");
+// isValidUser = UserService.validate(username, password);
+ if (isValidUser) {
+ HttpSession oldSession = request.getSession(false);
+ if (oldSession != null) {
+ oldSession.invalidate();
+ }
+ HttpSession newSession = request.getSession(true);
+ newSession.setMaxInactiveInterval(30 * 60);
+ newSession.setAttribute("username", username);
+ chain.doFilter(req, resp); // 继续执行下一个过滤器或请求
+ } else {
+ req.getRequestDispatcher("/login.jsp").forward(req, resp); // 跳转到登录页面
+ }
+ }
+
+ @Override
+ public boolean include(Object o) {
+ return false;
+ }
+ }
+
+ public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// Noncompliant {{对用户进行身份鉴别并建立一个新的会话时让原来的会话失效}}
+ boolean isValidUser = false;
+ String username = request.getParameter("username");
+ String password = request.getParameter("password");
+ isValidUser = UserService.validate(username, password);
+ if (isValidUser) {
+// HttpSession oldSession = request.getSession(false);
+ if (oldSession != null) {
+ oldSession.invalidate();
+ }
+ HttpSession newSession = request.getSession(true);
+ newSession.setMaxInactiveInterval(30 * 60);
+ newSession.setAttribute("username", username);
+ return true; // 继续下一个拦截器或请求处理器
+ } else {
+ response.sendRedirect("/login.jsp"); // 跳转到登录页面
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file