Using `.deep` to compare `Array`s is deprecatedSC-W1051Array comparison using conventional comparison operatorsSC-W1046Invalid deprecated annotation usedSC-W1035Duplicate `case` bodiesSC-W1036Method parameter shadowedSC-W1037Incorrect stringification of an `Array`SC-W1047Use `.isNaN` to check if a `Double` is `NaN`SC-W1052Use `==` or `!=` instead of `.equals(null)` to compare against `null`SC-W1053`Try` values must be checked before calling `.get`SC-W1054Builtin structure shadowed by user defined typeSC-W1055Consider adding explicit type annotations to public membersSC-W1058Initializing `StringBuilder` with a `Char` results in empty stringSC-W1060Potential `NoSuchElementException` in accessing filtered elementsSC-R1006Calling garbage collector manually does not necessarily improve performanceSC-P1008Do not attempt to trap `IllegalMonitorStateException`SC-W1039Use string interpolation to concatenate an entity to a stringSC-W1070Audit: log4j version used could lead to remote code executionSC-A1003Comparing a fresh object with the result of `getClass` always evaluates to `false`SC-W1071Exception in `catch` clause is unreachableSC-W1072Missing type parameter for cast operationsSC-W1075`hashCode()` relies on a mutable valueSC-W1076Method's generic parameter shadows class' generic parameterSC-W1078Sealed entity has no descendantsSC-W1079Equality methods overridden in a `case` classSC-W1074Missing `catch` clause for `try`SC-W1081`equals()` and `hashCode()` must be overridden in pairSC-W1073Consider using `Symbol()` over deprecated symbol literal syntaxSC-W1080Do not prefix enum members with enum's nameSC-R1085Consider specifying type in `catch` clauseSC-W1089Enum value has a member that maps to an already mapped valueSC-W1087Annotating a method with both `inline` and `tailrec` annotations results in a compile-time error in future Scala versionsSC-W1088Access modifiers `protected[this]` and `private[this]` are deprecatedSC-W1090Use the `inline` keyword instead of the annotationSC-R1087If-else chain has a duplicate conditionSC-W1086`length`-like property is compared against values which always evaluate to the same resultSC-W1091XML literals are deprecated and will be phased outSC-W1094Misplaced `return` statement in a method of `Unit` return typeSC-W1095Consider using ADTs instead of `scala.Enumeration` for `enum`-like featuresSC-W1093Object created is neither assigned to a variable nor passed as an argument but is dropped immediatelySC-W1096Use `summon[T]` over `implicitly[T]` in Scala 3 to probe for `implicit`-sSC-W1092Methods returning `Option` should only return `Some` or `None`SC-T1005Use `.lastOption` to access the last elementSC-P1001Use `.isEmpty` or `.nonEmpty` to check if structure is emptySC-P1002Consider filtering first and then sortingSC-P1003Consider using the appropriate overloaded method when searching for a single charSC-P1004Calling `List.size` is inefficientSC-P1005Consider rewriting `filter().headOption` as `find()`SC-P1006Appending to `List` is in-efficientSC-P1007Consider combining successive `.filter()` callsSC-P1009Use anonymous pattern-matching functions instead of match blocks within iteratorsSC-R1001Consider using `.isEmpty` or `.nonEmpty` instead of `.size` for `List`sSC-R1025Use pattern matching instead of repeated calls to `isInstanceOf`SC-R1029Consider rewriting `.find().isDefined` as `.exists()`SC-R1033Consider rewriting `.reverse.tail.reverse` as `.init`SC-R1035Consider rewriting `.reverse.take().reverse` as `.takeRight()`SC-R1036Consider rewriting `.filter().lastOption` as `.findLast()`SC-R1037Duplicate key in `HashMap`SC-W1019Pattern matching may be non-exhaustiveSC-W1024Usage of reserved keywordsSC-W1030Potential resource (file handle) leakSC-W1033Variable shadows another variable with same name in the parent scopeSC-W1050Avoid nested `match` expressionsSC-W1059Consider using `flatten` to extract the required valuesSC-R1034Consider using `sys.env.get` instead of `System.getenv` when accessing environmental variablesSC-R1044`stripMargin` on a regular expression alters its behaviorSC-W1066Consider making `case objects` `final`SC-W1067Use of Yoda expressionsSC-W1068`final` modifier is redundant for `object`SC-R1053Consider explicitly defining the main method, i.e. the entry pointSC-W1062Classes should not extend `java.lang.Error`SC-R1045Exception thrown is genericSC-R1043Consider using `AutoCloseable` for closing resourcesSC-R1052Deprecated multiarg infix syntaxSC-R1041Accessor like method has return type `Unit`SC-R1042`finalize`rs should not be defined explicitlySC-R1046Explicitly defined `finalize`rs should not be publicSC-R1047`finalize`rs should call `super.finalize` for super classes to run their own finalization logicSC-R1048Overridden methods cannot simply call `super`SC-R1049Empty `finalize`rs do not add anything of value and are redundantSC-R1050Consider dropping parentheses for accessor like methodsSC-R1051Consider using `.reduceOption` over `.reduce`SC-R1054SBT: Consider using the `slash` syntax instead of `in`SC-W1064Tests should have `assert` statementsSC-W1065Sealed `trait`s descendants must be `final`SC-W1069Accessing internal APIs via `--add-exports`SC-W1063Exception is generalized in the catch clauseSC-R1055Lambda can be converted to expression bodied lambdaSC-R1063Specifying the default value for an `implicit` parameter may adversely affect readabilitySC-R1059Variable can be declared as a `val` instead of `var`SC-R1061Using of braces in `import` statements is discouraged if importing a single entitySC-R1060Empty `finally` blockSC-R1056Catch clauses should do more than just rethrow exceptionsSC-R1057Pure methods should not have side-effectsSC-R1058Unary operator is redundant due to its operandSC-R1064Consider using `uninitialized` instead of `_` for uninitialized fields in Scala 3SC-R1078Parameters with default values should always be specified at lastSC-R1074Unary methods should not have any parentheses/take any argumentsSC-R1079Consider using the new syntax for vararg splicingSC-R1080Consider using the `as` keyword for import aliasesSC-R1081Consider returning values from `if` statement where possibleSC-R1082Pattern matching only mentions wildcard patternsSC-R1066Lambda parameter is unusedSC-W1083Universal `apply` methods make the `new` keyword redundantSC-R1069Unary methods cannot have return type `Unit`SC-R1083Consider using `implicit` over view boundsSC-R1065Exception variable is declared but unusedSC-W1082Consider breaking down long literals using the underscore tokenSC-R1084An entity that was already imported was re-importedSC-R1071Consider using `?` for wildcard arguments in types instead of `_` in Scala 3SC-R1077Consider using `*` for wildcard imports instead of `_` in Scala 3SC-R1075Range's upper bound is equal to a length-like propertySC-W1084Exception is instantiated using `new` but is not thrownSC-W1085Classes that are not exceptions should not end with `Exception`SC-R1072Classes that do not receive any parameters should not define empty parameter listSC-R1073Fold expression used to sum elements can be simplifiedSC-R1067Consider using the `@targetName()` annotation for symbol-like methodsSC-R1068Using the logical not operator to invert binary expressions can affect readabilitySC-R1070Import aliases do not need to be wrapped in braces in Scala 3SC-R1076Audit required: Instance of `NotImplementedError`SC-A1005`infix` modifier is redundant for symbol-like methodsSC-R1089Consider using `.findLast()` over `.reverse.find()`SC-P1012Use prefix notation over postfix notation where possibleSC-R1090Consider turning partial function into anonymous functionSC-R1093Consider using the efficient alternative `.reverseIterator` over `.reverse.iterator`SC-P1010Consider using `.collectFirst()` over `.collect().headOption`SC-P1011Consider using `Option(...)` instead of an explicit `if` statementSC-R1092Consider using `None` instead of `Some(null)`SC-A1002Consider grouping imports from same package togetherSC-R1011Consider using the comparison operators `==` or `!=` to compare `String`sSC-R1026Consider using `.dropRight` instead of `.substring` when the lower-bound is 0SC-R1027Redundant `val` keyword for case class' constructor parameterSC-R1038Consider simplifying `if`-`else` when returning only `Boolean` valuesSC-R1040Missing package declaration for fileSC-W1045Consider dropping pointless type boundsSC-R1032Use of `TODO/FIXME` comment encounteredSC-D1000`if` condition can be moved inside the `for` loop as an enumerator guardSC-R1062Redundant brace initializer when instantiating objectSC-R1086Wrapping identifiers in braces in interpolation is redundantSC-R1088Empty interpolated stringSC-W1011Incorrect number of args to String.formatSC-W1008Missing case `None` in pattern-matchingSC-W1025Infix operator has same operand on both sidesSC-W1026Duplicated `then` and `else` blocksSC-W1027Type `T` is a potential candidate for type erasureSC-A1004Catching of ThrowableSC-W1010Detected unreachable codeSC-W1006Duplicate case in pattern-matchingSC-W1007Oddness check i % 2 == 0 fails for -ve numbersSC-W1000Missing method return typeSC-W1009Explicit trap of `NullPointerException`SC-W1021`If` condition depends on `boolean` value that is a compile time constantSC-W1022Unused method parameterSC-W1038Audit required: Insecure hash functionSC-A1001Explicitly casting an object via `.asInstanceOf`SC-T1000Explicit cast operation: `isInstanceOf`SC-T1001Method has return type `Any`SC-T1002Consider making this `case` class finalSC-W1001Exception caught is genericSC-W1005Variable assigned to itselfSC-W1014Case class should always take a parameterSC-W1077Usage of wildcard importsSC-C1001Exception naming does not follow the recommended styleSC-C1000Replace `find() [==/!=] None` with `exists()`SC-R1009Methods with single statement in body may follow single-line conventionSC-C1006Too many method parametersSC-C1002Prefer using `Option.isDefined`, `Option.isEmpty` or `Option.nonEmpty` instead of `Option.size`SC-R1004Redundant `getOrElse()` on `get()`SC-R1005Replace `filter().isEmpty` with `!exists()`SC-R1007Replace `filter().size` with `count()`SC-R1008Parameterless method has return type - UnitSC-R1014Redundant `else` in `else if`SC-R1015Use 'until n' instead of 'to n - 1' in loopsSC-R1016Replace `!isEmpty` with `nonEmpty`SC-R1017Replace `!nonEmpty` with `isEmpty`SC-R1018Simplify verbose boolean comparisonSC-R1020Prefer using `.get` and then pattern matching over `.contains` for a MapSC-R1021Consider using `.isEmpty` or `.nonEmpty` when checking for empty `String`sSC-R1022Consider rewriting this `if` condition as case's entry guardSC-R1023Prefer `String` interpolation over `String.format`SC-R1030Duplicate element in `HashSet`SC-W1020Redundant `return` keyword for the last expression of the blockSC-W1029Use pattern matching instead of calling `.get` on `Option`SC-W1049Empty statements blockSC-C1004Structure is missing mutability-prefixSC-R1010Explicit `null` in value assignmentSC-W1012Explicit `null` in method callSC-W1013Method variant that return `Option[T]` should have their names suffixed with `Option`SC-C1005Function with cyclomatic complexity higher than thresholdSC-R1091
Scala logoScala/
SC-A1003

Audit: log4j version used could lead to remote code executionSC-A1003

Critical severityCritical
Security categorySecurity
owasp, cve, sans25

The log4j library is a popular logging library used across the JVM ecosystem. However, if you are using a vulnerable version of Log4j (A version between 2.0 and 2.16.0), RCE (Remote Code Execution) as well as DoS (Denial of Service) attacks are possible through abuse of Log4j's template processing algorithm.

An attacker can perform a malicious JNDI object lookup to chain other exploits, or induce the application to process a malicious template string resulting in a DoS attack if your code logs request data (such as a user agent header).

Update your Log4j version to 2.17.0 to mitigate these vulnerabilities.

The following vulnerabilities have been discovered as of December 19, 2021:

  • The original RCE vulnerability, affecting Log4j versions 2.0 and fixed incompletely in 2.15.0.
  • A DoS vulnerability, surfaced in version 2.15.0 and affecting all 2.x versions before it. This vulnerability is possible with certain non-default pattern layouts that allow the attacker to initiate JNDI lookups by manipulating thread context data. This attack requires a custom pattern layout that uses an interpolation string like $${ctx:loginId}.
    It has been fixed in version 2.16.0; message lookup and JNDI functionality is disabled by default now.
  • Log4j 1.x is partially vulnerable with non-default configurations that use the JMSAppender class. While this is of a lower severity than the other vulnerabilities found so far, version 1.x has been deprecated since 2015 and will not receive official updates (not even security fixes); consider updating to the latest 2.x version.
  • Another severe DoS vulnerability, affecting versions 2.0 to 2.16.0. It is possible for a specially crafted self-referential lookup string (PoC example of this is ${${::-${::-$${::-j}}}}) to cause log4j to go into an infinite recursive loop, resulting in a stack overflow. NOTE: This vulnerability also requires a non-default pattern layout similar to the previously mentioned DoS attack.

This is fixed in version 2.17.0.

Update your Log4j version to the latest to avoid these vulnerabilities.

This exploit can make use of multiple RPC protocols, including LDAP, CORBA and RMI, of which LDAP is especially vulnerable due to its lack of security manager enforcement.

For an in-depth explanation of how this attack is made possible, read this article.

There are a few ways to fix this issue.

  • Upgrade to Log4j 2.17.0

Log4j's latest version, 2.17.0 fixes this bug.

Upgrade your Log4j dependency to this version if possible.

  • Remove the JndiLookup class from your application's classpath

This vulnerability exploits Log4j's ability to interpolate JNDI lookup urls into logged strings. It is safe to do so but will not protect from certain DoS vulnerabilities mentioned above.

JndiLookup.class can be removed by deleting the JndiLookup.class file from your copy of log4j-core.jar:

zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

The best method to prevent this issue is to update to the latest version of Log4j.

References