IntelliJ plugin SonarLint 로 코드 돌려서 나온 Code Smell, Bug, Vulnerability 등등 정리

2tsumo·2025년 8월 12일
0

java

목록 보기
8/9

SonaLint는 내 코드를 리뷰해주는 IDE 플러그인이다.

나는 inteli J 에서 Action에 sornaLint 를 검색해서 플러그인을 추가한뒤 전체 코드를 돌렸다. 이 작업은 어렵지 않고 쉽게 할 수 있다.

사실 docker에 소나큐브를 설치해서 거기서 내 inteli J의 sonarLint를 연결해서 확인해보고 싶었는데 이틀동안 시도했는데 무슨 문제인지 모르겠는데 되질 않아서 일단 미뤄두었다..

아래 문제점들은 많은 자바 8 개발자들, 특히나 관공서 사이트 유지를 주로하는 웹개발자들 소스에 자주 나오는 에러들 인 것 같다.

나는 java 8 에서 작업중이기 때문에 최신 자바를 쓰는 경우에는 더 다양한 오류가 발생할 수 있다.

전체 코드를 돌리는법

플러그인 깔고 ctrl shift r - Action tab에서 Analyze all files with sonarLint

----수없이 반복된 것

모든 주석, 변수가 아닌 경로(경로 하드코딩 또는 중간 / 문자열 삽입), 클래스 내에 반복되는 변수, 하드코딩(변수에 넣지 않은 채 반복된 값), @RequestMapping 취약점, 모든 System.out, 모든 e.printStackTrace, 사용하지 않은 채 선언된 변수, 불필요한 throw

  1. Links with "target=_blank" should prevent phishing attacks(Vulnerability)
  • 문제점: target="_blank"가 사용된 링크를 사용자가 클릭하면 새 탭에서 링크된 페이지가 열립니다. 가령 이 링크된 페이지가 악의를 가진 사람이 만든 것이고, 이 페이지의 JavaScript에서 window.opener로 부모 윈도우(링크를 건 페이지)의 오브젝트에 접근해서 'window.opener.location = 새로운URL'로 부모 윈도우의 URL을 바꿔친다고 생각해 보세요. 이렇게 부모 윈도우의 정보를 마음대로 사용하거나 조작한다면 어떤 일이 벌어질까요? 개인정보 유출을 유도하는 가짜 페이지로 부적절한 리디렉션을 하는 등의 보안상에 심각한 문제가 발생할 수도 있습니다. target="_blank"가 사용된 링크에 의해 열린 링크된 페이지는 링크를 건 페이지와 같은 프로세스를 통해서 실행됩니다. 그러므로 가령 링크된 페이지에서 높은 부하를 유발하는 JavaScript가 실행되고 있으면 링크를 건 페이지에도 그 영향이 미쳐져 의도하지 않게 퍼포먼스가 떨어지는 문제가 발생할 수도 있습니다.
  • 해결 방법: rel="noopener noreferrer“

1) noopener 지정

noopener(노오프너)를 지정하면, 링크된 페이지에서 window.opener을 사용해서 링크를 건 페이지를 참조(reference)할 수 없게 됩니다. 더불어 링크된 페이지와 링크를 건 페이지는 별개의 프로세스로 취급되기 때문에 서로 연결되어 퍼포먼스가 떨어지는 일도 없게 됩니다.

신뢰할 수 없는 페이지로 이동하는 링크를 부득이하게 만들어야 할 때 사용

  1. noreferrer 지정

noreferrer(노리퍼러)를 지정하면 다른 페이지로 이동할 때, 링크를 건 페이지의 주소 등의 정보를 브라우저가 Referer: HTTP 헤더로 리퍼러(referer 또는 referrer)로서 송신하지 않습니다.

  1. "@RequestMapping" methods should specify HTTP method( Vulnerability)
  • 문제점: @RequestMapping 메서드는 기본적으로 일치하는 모든 요청을 처리합니다. 즉, POST로만 처리되도록 의도한 메서드가 GET에서도 호출될 수 있으므로 해커가 메서드를 부적절하게 호출할 수 있습니다.

해결방법: method = RequestMethod.GET

  1. String literals should not be duplicated(Code smell)

문제점: 중복된 문자열 리터럴은 모든 항목을 업데이트해야 하므로 리팩토링 프로세스에서 오류가 발생하기 쉽습니다. 반면에 상수는 여러 곳에서 참조할 수 있지만 한 곳에서만 업데이트하면 됩니다.

  • 해결방법:

private static final String ACTION_1 = "action1"; // Compliant

public void run() {

prepare(ACTION_1); // Compliant

execute(ACTION_1);

release(ACTION_1);

}

  1. Sections of code should not be commented out(Code smell)

문제점: 프로그래머는 코드를 주석 처리하면 안 됩니다. 코드는 프로그램을 부풀리고 가독성을 떨어뜨리기 때문입니다. 사용하지 않는 코드는 삭제해야 하며 필요한 경우 소스 제어 기록에서 검색할 수 있습니다.

해결: 주석 삭제

  1. Printf-style format strings should be used correctly(Code smell)

문제점: printf 스타일 형식 문자열은 컴파일러에서 유효성을 검사하지 않고 런타임에 해석되기 때문에 잘못된 문자열이 생성되는 오류를 포함할 수 있습니다.

  • 해결: java.util.Logger logger;

logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject);

logger.log(java.util.logging.Level.SEVERE, "Result {0}'", 14);

org.slf4j.Logger slf4jLog;

org.slf4j.Marker marker;

slf4jLog.debug(marker, "message {}");

slf4jLog.debug(marker, "message {}", 1);

org.apache.logging.log4j.Logger log4jLog;

log4jLog.debug("message {}", 1);

  1. Method names should comply with a naming convention(Code smell)
  • 문제점: 공유 명명 규칙을 통해 팀은 효율적으로 협업할 수 있습니다. 이 규칙은 모든 메서 드 이름이 제공된 정규식과 일치하는지 확인합니다.

해결: With default provided regular expression ^[a-z][a-zA-Z0-9]*$:

  1. "static" base class members should not be accessed via derived types(Code smell)
  • 문제점: 코드 명확성을 위해 기본 클래스의 정적 멤버는 파생 형식의 이름을 사용하여 액세 스해서는 안 됩니다. 그렇게 하면 혼란스럽고 두 개의 다른 정적 멤버가 존재하는 것처럼 보 일 수 있습니다.

-해결: ?

class Parent {

public static int counter;

}

class Child extends Parent {

public Child() {

Parent.counter++;

}

}

  1. Try-with-resources should be used(Code smell)

문제점: Java 7은 문제의 리소스가 닫힐 것을 보장하는 try-with-resources 문을 도입했습니다. 새 구문은 방탄에 가깝기 때문에 이전 try/catch/finally 버전보다 선호되어야 합니다. 이 규칙은 닫기 가능한 리소스가 try-with-resources 문에서 열려 있는지 확인합니다.

이 규칙은 프로젝트의 sonar.java.source가 7보다 낮으면 자동으로 비활성화됩니다.

  • 해결:

try (

FileReader fr = new FileReader(fileName);

BufferedReader br = new BufferedReader(fr)

) {

return br.readLine();

}

catch (...) {}

or

try (BufferedReader br =

new BufferedReader(new FileReader(fileName))) { // no need to name intermediate resources if you don't want to

return br.readLine();

}

catch (...) {}

  1. URIs should not be hardcoded (Code smell)

문제점: URI를 하드 코딩하면 프로그램을 테스트하기가 어렵습니다. 경로 리터럴이 운영 체제 간에 항상 이식 가능한 것은 아니며, 주어진 절대 경로가 특정 테스트 환경에 존재하지 않을 수 있으며, 테스트, 프로덕션 환경을 실행할 때 지정된 인터넷 URL을 사용하지 못할 수 있습니다. 파일 시스템은 일반적으로 개발 환경, ...등과 다릅니다. 이러한 모든 이유로 URI는 하드 코딩되어서는 안 됩니다. 대신 사용자 정의 가능한 매개변수로 대체해야 합니다. 또한 URI의 요소를 동적으로 획득하더라도 경로 구분 기호가 하드 코딩된 경우 이식성이 여전히 제한될 수 있습니다. 이 규칙은 URI 또는 ​​경로 구분 기호가 하드 코딩된 경우 문제를 일으킵니다.

-해결: String slash = “/”; 이렇게 해야되나??

  1. "Random" objects should be reused (Bug)

문제점: 무작위 값이 필요할 때마다 새로운 Random 객체를 생성하는 것은 비효율적이며 JDK에 따라 무작위가 아닌 숫자를 생성할 수 있습니다. 더 나은 효율성과 무작위성을 위해 단일 Random을 생성한 다음 저장하고 재사용합니다.

Random() 생성자는 매번 고유한 값으로 시드를 설정하려고 합니다. 그러나 시드가 무작위로 또는 균일하게 분포된다는 보장은 없습니다. 일부 JDK는 현재 시간을 시드로 사용하므로 생성된 숫자가 전혀 무작위가 아닙니다.

이 규칙은 메서드가 호출되고 로컬 랜덤 변수에 할당될 때마다 새로운 Random이 생성되는 경우를 찾습니다.

-해결:

private Random rand = SecureRandom.getInstanceStrong(); // SecureRandom is preferred to Random

public void doSomethingCommon() {

int rValue = this.rand.nextInt();

//...

  1. Utility classes should not have public constructors
  • 문제점: 정적 멤버의 컬렉션인 유틸리티 클래스는 인스턴스화할 수 없습니다. 확장할 수 있는 추상 유틸리티 클래스에도 공용 생성자가 없어야 합니다.

Java는 명시적으로 하나 이상을 정의하지 않는 모든 클래스에 암시적 공용 생성자를 추가합니다. 따라서 최소한 하나의 비공개 생성자가 정의되어야 합니다.

  • 해결:

private utilMethod(){

throw new IllegalStateException("Utility class");

}

  1. Synchronized classes Vector, Hashtable, Stack and StringBuffer should not be used

문제점: Vector, Hashtable 및 StringBuffer와 같은 Java API의 초기 클래스는 스레드로부터 안전하도록 동기화되었습니다. 불행히도 동기화는 단일 스레드에서 이러한 컬렉션을 사용하는 경우에도 성능에 큰 부정적인 영향을 미칩니다.

해결:

Vector 대신 ArrayList 또는 LinkedList

Stack대신 Deque

Hashtable 대신 HashMap

StringBuffer 대신 StringBuilder

  1. Composed "@RequestMapping" variants should be preferred

문제점: Spring 프레임워크 4.3은 @RequestMapping 어노테이션의 변형을 도입하여 어노테이션이 있는 메소드의 의미를 더 잘 표현합니다. @GetMapping, @PostMapping, @PutMapping, @PatchMapping 및 @DeleteMapping의 사용은 원시 @RequestMapping(method = RequestMethod.XYZ)의 사용보다 선호되어야 합니다.

해결:

@RequestMapping(path = "/greeting", method = RequestMethod.GET)

-> @GetMapping(path = "/greeting")

  1. Declarations should use Java collection interfaces such as "List" rather than specific implementation classes such as "LinkedList“

문제점: Java Collections API의 목적은 구현 세부 사항을 숨기기 위해 잘 정의된 인터페이스 계층 구조를 제공하는 것입니다. 구현 클래스는 새 컬렉션을 인스턴스화하는 데 사용해야 하지만 인스턴스화 결과는 이상적으로 유형이 Java 컬렉션 인터페이스인 변수에 저장되어야 합니다. 이 규칙은 구현 클래스가 다음과 같은 경우 문제를 발생시킵니다. public 메서드에서 반환됩니다. public 메서드에 대한 인수로 허용됩니다. public 회원으로 노출됩니다.

해결: HashSet -> Set //

HashMap<String, Object> -> Map<String, Object>

  1. Strings should not be concatenated using '+' in a loop

문제점: 문자열은 변경할 수 없는 개체이므로 연결은 단순히 기존 문자열의 끝에 새 문자열을 추가하지 않습니다. 대신 각 루프 반복에서 첫 번째 문자열이 중간 개체 유형으로 변환되고 두 번째 문자열이 추가된 다음 중간 개체가 다시 문자열로 변환됩니다. 또한 이러한 중간 작업의 성능은 문자열이 길어질수록 저하됩니다. 따라서 StringBuilder를 사용하는 것이 좋습니다.

해결:

StringBuilder bld = new StringBuilder();

for (int i = 0; i < arrayOfStrings.length; ++i) {

bld.append(arrayOfStrings[i]);

}

String str = bld.toString();

  1. Exceptions should be either logged or rethrown but not both
  • 문제점: 예외를 기록하고 다시 발생시키는 것이 허용되는 응용 프로그램에서는 동일한 예외의 여러 인스턴스를 포함하는 수 마일 길이의 로그로 끝납니다. 다중 스레드 응용 프로그램에서 이러한 유형의 로그를 디버깅하는 것은 특히 지옥일 수 있습니다. 다른 스레드의 메시지가 기록된 예외의 반복과 엮이기 때문입니다. 대신 예외가 기록되거나 다시 발생해야 합니다.
  • 해결:

catch (SQLException e) {

...

throw new MySQLException(contextInfo, e);

}

or

catch (SQLException e) {

...

LOGGER.log(Level.ERROR, contextInfo, e);

// handle exception...

}

  1. Empty arrays and collections should be returned instead of null

문제점: 실제 배열이나 컬렉션 대신 null을 반환하면 메서드 호출자가 null을 명시적으로 테스트해야 하므로 더 복잡하고 가독성이 떨어집니다.

또한 많은 경우 null은 비어 있음의 동의어로 사용됩니다.

해결:

public static List getResults() {

return Collections.emptyList();

}

public static Result[] getResults() {

return new Result[0];

}

public static void main(String[] args) {

for (Result result: getResults()) {

/ ... /

}

  1. Methods should not be empty

문제점 : 메서드에 메서드 본문이 없는 데는 몇 가지 이유가 있습니다.

의도하지 않은 누락이며 프로덕션에서 예기치 않은 동작을 방지하기 위해 수정해야 합니다.

아직 지원되지 않았거나 지원되지 않을 것입니다. 이 경우 UnsupportedOperationException이 발생해야 합니다.

메서드는 의도적으로 비어 있는 재정의의 경우 중첩된 주석은 공백 재정의에 이유를 설명해야 합니다.

  • 해결:

@Override

public void doSomething() {

// Do nothing because of X and Y.

}

@Override

public void doSomethingElse() {

throw new UnsupportedOperationException();

}

  1. "Map.get" and value test should be replaced with single method call

문제점: 맵에서 값을 추가하거나 변경하기 전에 null에 대해 java.util.Map.get()의 결과를 테스트하는 것이 일반적인 패턴입니다. 그러나 java.util.Map API는 computeIfPresent() 및 computeIfAbsent() 메소드의 형태로 훨씬 더 나은 대안을 제공합니다. 대신 이것들을 사용하면 더 깨끗하고 읽기 쉬운 코드를 만들 수 있습니다.

해결:

return map.computeIfAbsent(key, k -> V.createFor(k));

  1. The diamond operator ("<>") should be used

문제점: Java 7은 제네릭 코드의 장황함을 줄이기 위해 다이아몬드 연산자(<>)를 도입했습니다. 예를 들어 List의 유형을 선언과 생성자 모두에서 선언할 필요 없이 이제 <>를 사용하여 생성자 선언을 단순화할 수 있으며 컴파일러는 유형을 유추합니다.

이 규칙은 프로젝트의 sonar.java.source가 7보다 낮으면 자동으로 비활성화됩니다.

해결: List strings = new ArrayList<>();

Map<String,List> map = new HashMap<>();

  1. "java.nio.Files#delete" should be preferred

문제점: java.io.File#delete가 실패하면 이 boolean메서드는 원인 표시 없이 단순히 false를 반환합니다. 반면에 java.nio.Files#delete가 실패하면 이 void 메소드는 실패 원인을 더 잘 나타내기 위해 일련의 예외 유형 중 하나를 리턴합니다. 그리고 디버깅 상황에서는 일반적으로 더 많은 정보가 더 좋기 때문에 java.nio.Files#delete가 선호되는 옵션입니다.

해결: Files.delete(path);

  1. Try-with-resources should be used
  • 문제점: Java 7은 문제의 리소스가 닫힐 것을 보장하는 try-with-resources 문을 도입했습니다. 새 구문은 방탄에 가깝기 때문에 이전 try/catch/finally 버전보다 선호되어야 합니다.

이 규칙은 닫기 가능한 리소스가 try-with-resources 문에서 열려 있는지 확인합니다.

이 규칙은 프로젝트의 sonar.java.source가 7보다 낮으면 자동으로 비활성화됩니다.

  • 해결:

try (

FileReader fr = new FileReader(fileName);

BufferedReader br = new BufferedReader(fr)

) {

return br.readLine();

}

catch (...) {}

or

try (BufferedReader br =

new BufferedReader(new FileReader(fileName))) { // no need to name intermediate resources if you don't want to

return br.readLine();

}

catch (...) {}

  1. Generic wildcard types should not be used in return parameters

문제점: 와일드카드 유형을 반환 유형으로 사용하지 않는 것이 좋습니다. 유형 유추 규칙은 상당히 복잡하기 때문에 해당 API 사용자가 올바르게 사용하는 방법을 알지 못할 것입니다. "List<? extends Animal>"을 반환하는 메소드의 예를 들어보자. 이 목록에 개, 고양이 등을 추가할 수 있습니까? ... 우리는 단순히 모릅니다. 그리고 컴파일러도 마찬가지이므로 그러한 직접적인 사용을 허용하지 않습니다. 와일드카드 유형의 사용은 메소드 매개변수로 제한되어야 합니다. 이 규칙은 메서드가 와일드카드 유형을 반환할 때 문제를 발생시킵니다.

해결: List getAnimals(){...} or List getAnimals(){...}

  1. "HttpOnly" should be set on cookies

문제점: HttpOnly 쿠키 특성은 브라우저에 클라이언트 측 스크립트가 해당 특성이 있는 쿠키를 읽지 못하도록 하며, 이를 사용하면 XSS(교차 사이트 스크립팅) 공격을 방어할 수 있습니다. 따라서 예방 조치로 세션 ID 쿠키와 같이 서버 측에서 설정된 모든 쿠키에 대해 속성이 기본적으로 설정되어야 합니다. XSRF(교차 사이트 요청 위조) 보호를 구현할 때 일반적으로 XSRF-TOKEN이라는 JavaScript 판독 가능 세션 쿠키가 첫 번째 HTTP GET 요청에서 생성되어야 합니다. 이러한 쿠키의 경우 HttpOnly 속성을 "false"로 설정해야 합니다. 속성 설정은 프로그래밍 방식으로 수행하거나 구성 파일을 통해 전역적으로 수행할 수 있습니다.

해결: cookie.setHttpOnly(true)

  1. "" and "" tags should be used(Bug)

문제점: // 태그는 대부분의 웹 브라우저에서 정확히 동일한 효과를 갖지만 둘 사이에는 근본적인 차이가 있습니다. 은 의미론적 의미를 갖는 반면 는 CSS와 같은 스타일 정보만 전달합니다.

해결: car // train

  1. "" tags should have "id" or "scope" attributes(Bug)

문제점: 가능하면 헤더에 범위 속성을 추가하는 것이 좋습니다.

해결:

  1. "" tags should have a description(Bug)

    문제점: 사용자가 액세스할 수 있도록 하려면 데이터에 액세스하기 전에 테이블에 내용에 대한 설명을 제공하는 것이 중요합니다.

    • 해결: 가장 간단한 방법이자 WCAG2에서 권장하는 방법은
    내부에
    요소를 추가하는 것입니다.
    1. "aria-label" or "aria-labelledby" attributes should be used to differentiate similar elements(Code smell)

    문제점: 페이지에 여러

    또는 요소가 포함된 경우 각 요소에는 aria-label 또는 aria-labelledby 속성이 있어야 구분할 수 있습니다.

    해결:

    • A list of navigation links
    1. Image, area and button with image tags should have an "alt" attribute

    문제점: 이미지 태그가 있는 이미지, 영역 및 버튼에는 "alt" 속성이 있어야 합니다. alt 속성은 이미지에 대한 텍스트 대안을 제공합니다. 실제 이미지를 렌더링할 수 없을 때 사용됩니다.

    해결: rooms of the house.

profile
👨‍💻

0개의 댓글