constructor(readonly name: string, private age: number) { // creates 2 initialized members “name” and “age” }
Get Started
- CodeAnt AI
- Control Center
- Pull Request Review
- IDE
- Compliance
- Anti-Patterns
- Code Governance
- Infrastructure Security Database
- Application Security Database
Javascript
By convention, a file that exports only one class, function, or constant should be named for that class, function or constant. Anything else may confuse maintainers.
A complex regular expression is one that exhibits several or all of the following characteristics. It can be quite lengthy, containing multiple nested or repeated groups, numerous alternations, extensive use of backreferences and escape characters, lookaheads, lookbehinds, and other advanced features. Additionally, complex regular expressions may lack proper comments and documentation, making them challenging to comprehend and maintain. Overly complicated regular expressions are hard to read and maintain and can easily cause hard-to-find bugs.
To determine the complexity of a regular expression, each of the following operators increases the complexity by an amount equal to the current nesting level and also increases the current nesting level by one for its arguments:
Disjunctions (`|): when multiple | operators are used together, the subsequent ones only increase the complexity by 1
Quantifiers (*, +, ?, {n,m}, {n,} or {n})
Lookahead and lookbehind assertions
Additionally, each use of a character class and backreferences increase the complexity by 1 regardless of nesting.
This rule will raise an issue when total complexity is above the threshold maxComplexity` (20 by default).
Jump statements, such as return, break and continue
, are used to change the normal flow of execution in a program. They are useful because they allow for more complex and flexible code. However, it is important to use jump statements judiciously, as overuse or misuse can make code difficult to read and maintain.
Jump statements are redundant when they do not affect the program flow or behavior.
The return type any should be avoided because it prevents the type safety checks normally done by the compiler. When a function returns a primitive type (i.e. number, string or boolean) it is safe to replace any with number, string or boolean
type respectively, or remove the return type completely and let compiler infer it.
In React, the ReactDOM.render() method is used to render a React component into a DOM element. It has a return value, but it’s generally recommended not to use it. The method might return a reference to the root ReactComponent instance, but it can be unpredictable and may not always be useful. Indeed, the return value can vary depending on the version of React you’re using and the specific circumstances in which it’s called.
Comparing the value to itself may be either a refactoring error or an outdated way of checking if the value is of a numeric data type but not a valid number. This special numeric value is represented by NaN global property, where NaN stands for “Not-a-Number”. NaN is returned as a result when an arithmetic operation or mathematical function is performed, and the result is undefined or unrepresentable as a valid number.
Detecting whether a value is NaN in JavaScript was previously problematic because of the way NaN behaves in comparison operations. NaN is not equal to any value, including itself, so comparing the value to NaN will always return false. In other words, if a value is not equal to itself, it can only be NaN.
This method of detecting NaN can be confusing and should be avoided. ES6 introduced a special function Number.isNaN() which only returns true if the argument is NaN value. For clarity and consistency this function should be used to detect NaN instead of all other methods.
Prototype Pollution vulnerabilities allow to inject new properties into the built-in Object.prototype
object. Since most objects inherit from this prototype, it can result in unexpected behavior, e.g., crashes or more severe vulnerabilities.
In the past, it has led to the following vulnerabilities:
Character classes in regular expressions will match any of the characters enclosed in the square brackets ([abc] will match a, b or c).
You can specify a range of characters using a hyphen (-). If the hyphen appears as the first or last character, it will be matched as a literal hyphen.
An empty character class ([]) will not match any character because the set of matching characters is empty. So the regular expression will not work as you intended.
The use of `find allows document.getElementById() to be used for the top-level selection, and saves the jQuery Sizzle engine for where it’s really needed. That makes the query faster, and your application more responsive.
From the jQuery documentation:
JavaScript allows duplicate property names in classes and object literals. The last occurrence will overwrite previous definitions. Therefore, having more than one occurrence will have no effect and may cause misunderstandings and bugs.
In JavaScript, the super keyword is used to call the constructor and methods of an object’s parent class, and to access its properties.
The expression super(…args)
is used to call the parent’s constructor. It must be used carefully and correctly to avoid errors.
Functions that accept random numbers of arguments use a rest argument (... argname). This allows you to pass the function each relevant parameter individually. At runtime, those parameters are automatically wrapped in an array. If you pass an array to such a function, it will automatically be re-wrapped in another array, and this double-layering won’t be expected by the called function. To avoid that double-layering, use the spread operator (...
arrayToBeExpanded) in the call to expand the array.
This applies both to manually created arrays, and to arguments that were accepted as rest parameters.
Proper use of the `angular object is crucial when using the AngularJS framework. Misspell an angular function, and depending on the browser you may not get any errors at all, or the error you do get will be distinctly unhelpful.
This rule is intended to catch misspellings of the recognized angular functions. It checks that only the following functions are used:
directive
module
controller
provider
filter`
JavaScript provides built-in methods to sort arrays, making it convenient for developers to manipulate data. There are two primary ways to sort an array:
`Array.prototype.sort(): This method sorts the elements of an array in place and returns the sorted array.
Array.prototype.toSorted()`: This method is designed to return a new sorted array, leaving the original array unchanged.
The default sort order is lexicographic (dictionary) order, based on the string representation of the elements. This means that when sorting an array of strings, numbers, or other elements, they are converted to strings and sorted according to their Unicode code points (UTF-16). For most cases, this default behavior is suitable when sorting an array of strings.
However, it’s essential to be aware of potential pitfalls when sorting arrays of non-string elements, particularly numbers. The lexicographic order may not always produce the expected results for numbers:
Octal escape sequences in string literals have been deprecated since ECMAScript 5 and should not be used in modern JavaScript code.
Many developers may not have experience with this format and may confuse it with the decimal notation.
The spread operator is a more concise and more readable way to pass arguments to a function that takes a variable number of arguments (variadic function). Prior to ES2015, the only way to call such functions with a variable number of arguments was to use the .apply() method.
According to the Backbone.js docs
The changed
property is involved in decisions about whether or not a collection should be resorted when it is updated. If you modify it manually, you can break the resorting of the collection.
`null and undefined are similar but not synonymous concepts in Javascript. Use a “hard” test (=== or !==) for one, and you’ll miss the other. Soft tests (==, and !=) on the other hand, will pick up both non-values, as well as empty string.
Even if you mean to make the distinction in your code between null and undefined`, doing so is an extremely questionable practice that is likely to confuse both users and maintainers. Instead, use one or the other and test for both using soft tests.
JavaScript has special identifiers that, while not reserved, still should not be used as identifiers. They form the JavaScript standard built-in objects and global properties. They are available in all environments. Some examples are:
Global objects: Object, Function, Error, …
Global object function properties: eval(), isNan(), parseFloat(), decodeURI(), …
Global object value properties: undefined, NaN, Infinity
Identifiers with special meanings: arguments
These words should not be bound or assigned, because doing so would overwrite the original definitions of these identifiers. What’s more, assigning or binding some of these names will generate an error in JavaScript strict mode code.
The point of declaring an optional property or parameter is to make explicit the fact that it might contain no valid value, i.e. null or undefined. Using a non-null assertion (the !. operator) will lead to a runtime error if the optional does contain null or undefined
. Even if the value is tested first, it’s still considered a bad practice to use a non-null assertion.
Grouping all the shorthand declarations together in an object makes the declaration as a whole more readable. This rule accepts shorthand declarations grouped at either the beginning or end of an object.
Use a `+ with two numbers and you’ll get addition. But use it with a string and anything else, and you’ll get concatenation. This could be confusing, especially if it’s not obvious that one of the operands is a string. It is recommended to explicitly convert the non-string component to make it easier to understand to future maintainers.
This rule raises an issue when or =` is used with a string and a non-string.
When defining a union or intersection in TypeScript, it is possible to mistakenly include type constituents that encompass other constituents, that don’t have any effect, or that are more restrictive. For instance,
The type something in any | something is redundant because any covers all possible types, whatever something is.
The types never in unions like never | something or unknown in intersections like unknown & something are effectless.
More restrictive types in intersections like the literal type 1 in 1 & number reduce the set of possible values to specific ones.
Eliminating redundant types from a union or intersection type simplifies the code and enhances its readability. Moreover, it provides a clearer representation of the actual values that a variable can hold.
The for of statement can only iterate over objects that have an iterator
property.
When using Backbone.js, the use of has to check attribute existence is clearer and more readable than the use of get
, and is therefore preferred.
Variables declared with `var are function-scoped, meaning they are accessible within the entire function in which they are defined. If a variable is declared using var outside of any function, it becomes a global variable and is accessible throughout the entire JavaScript program.
let and const were introduced in ECMAScript 6 (ES6) as a block-scoped alternative to var. Variables declared with let have block scope, meaning they are limited to the block of code in which they are defined. A block is typically delimited by curly braces {}.
Variables declared with const are also block-scoped, similar to let. However, const variables are immutable, meaning their value cannot be changed after assignment. This applies to the binding between the variable name and its value, but it does not mean the value itself is immutable if it is an object or an array.
A variable declared with let or const is said to be in a “temporal dead zone”, meaning the period between entering a scope and declaring a let or const variable. During this phase, accessing the variable results in a ReferenceError. This helps catch potential errors and encourages proper variable declaration.
Unlike let and const, variables declared with var are subject to “hoisting”, which means that they are moved to the top of their scope during the compilation phase, even if the actual declaration is placed lower in the code.
Hoisting can sometimes lead to unexpected behavior. For example, variables declared with var are accessible before they are declared, although they will have the value undefined until the declaration is reached.
The distinction between the variable types created by var and by let is significant, and a switch to let will help alleviate many of the variable scope issues which have caused confusion in the past.
Because these new keywords create more precise variable types, they are preferred in environments that support ECMAScript 2015. However, some refactoring may be required by the switch from var to let, and you should be aware that they raise SyntaxErrors in pre-ECMAScript 2015 environments.
This rule raises an issue when var is used instead of const or let`.
In JavaScript, NaN stands for “Not-a-Number.” It is a special value representing a numeric data type that is not a valid number. NaN is returned as a result when an arithmetic operation or mathematical function is performed, and the result is undefined or unrepresentable as a valid number.
Comparing a value with NaN in JavaScript can be problematic because of the way NaN behaves in comparison operations. The reason is that NaN is not equal to any value, including itself, and this behavior can lead to unexpected results.
React relies on the order in which Hooks are called to correctly preserve the state of Hooks between multiple useState and useEffect calls. This means React Hooks should be called in the same order each time a component renders and should not be called inside loops, conditions, or nested functions.
Additionally, this rule ensures that the Hooks are called only from React function components or custom Hooks.
The `typeof operator returns a string indicating the type of its argument, and the set of returned values is limited:
“undefined"
"boolean"
"number"
"string"
"symbol” (since ECMAScript 2015)
“function"
"object” (for null and any other object)
“bigint” (since ECMAScript 2020)
Compare a typeof expression to anything else, and the result will always be false`.
The debugger statement can be placed anywhere in procedures to suspend execution. Using the debugger statement is similar to setting a breakpoint in the code. By definition such statement must absolutely be removed from the source code to prevent any unexpected behavior or added vulnerability to attacks in production.
React components often render HTML elements, and developers can pass various props (properties) to these elements. However, React has its own set of supported properties and attributes, and it’s essential to avoid using unknown or invalid properties when working with such elements to prevent unexpected behavior at runtime.
The rule reports any instances where you are using a property or attribute that is not recognized by React or the HTML element you are rendering.
The following order represents what is commonly expected by ReactJS developers.
Not following this convention has no technical impact, but will reduce the class’s readability because most developers are used to this standard order.
`static methods
the constructor
getChildContext()
componentWillMount()
componentDidMount()
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate()
componentWillUnmount()
clickHandlers or eventHandlers such as onClickSubmit() or onChangeDescription()
getter methods for render such as getSelectReason() or getFooterContent()
optional render methods such as renderNavigation() or renderProfilePicture()
render()`
The comma operator takes two expressions, executes them from left to right, and returns the result of the second one. The use of this operator is generally detrimental to the readability and reliability of code, and the same effect can be achieved by other means.
The \ (backslash) character indicates that the next character should be treated as a literal character rather than as a special character or string delimiter.
For instance, it is common to escape single quotes inside a string literal using the single quote delimiter like ‘It’s a beautiful day’
. Escaping is only meaningful for special characters.
Escaping non-special characters in strings, template literals, and regular expressions doesn’t affect their value.
Public static fields in TypeScript should be declared as readonly
to prevent them from being modified after their initial assignment. This is a good practice because it makes the code safer by preventing accidental changes to these fields, which could lead to bugs that are hard to detect.
TypeScript allows all sorts of expressions to initialize enum members. However, as enums create their own scope, using identifiers can lead to unexpected results. The recommendation is thus to use only literal values when defining enum members.
Variables declared with `const cannot be reassigned using the assignment operator.
The const declaration creates an immutable reference to a value. This does not mean the value it holds is immutable, but the identifier cannot be reassigned. For example, if the constant is an object, its properties can still be altered. Use Object.freeze() to make an object immutable.
You must always specify an initializer in a const declaration as it can not be changed later. Trying to declare a constant without an initializer (const foo;`) will throw a SyntaxError.
Trying to reassign a constant will throw a TypeError. In a non-ES2015 environment, it might simply be ignored.
Comparing two values of different types with operator === or !== will always return respectively true and false. The same is true for operators == and != when two objects
of unrelated types, i.e. one is not a prototype of the other, are compared.
Chai provides assertion functions which use these operators to compare two values. These assertions should not compare values of incompatible types as they would always fail or always succeed.
If the type of a props
property is not defined there is a great chance one will wrongly use the value returned by the property and generate a not expected behavior of the application.
alert(…) as well as confirm(…) and prompt(…)
can be useful for debugging during development, but in production mode this kind of pop-up could expose sensitive information to attackers, and should never be displayed.
Labels allow specifying a target statement to jump to using the break or continue statements. It’s possible to assign a label to any statement or block of statements. However, using it with any statement can create a complex control flow path, making the code harder to understand and maintain.
When merging objects or copying properties from one object to another, use the object spread syntax instead of Object.assign(). The object spread syntax was introduced in ES2018 and allows shallow-cloning or merging of objects with a more concise and readable syntax.
The Object.assign() also allows to mutate an object, which is not possible with the spread syntax, so the rule only applies to cases where the first argument of the Object.assign() is an object literal.
The object spread syntax improves clarity when you’re modifying an object, as demonstrated in this example: foo = { bar: 42, …baz }. Additionally, it provides a more concise way to perform a shallow clone. Instead of using foo = Object.assign({}, bar), you can simply write foo = { …bar }.
Having default value for optional boolean parameters makes the logic of function when missing that parameter more evident. When providing a default value is not possible, it is better to split the function into two with a clear responsibility separation.
TypeScript provides enums to allow developers to define a set of named constants under a common type. These enum constants can be assigned values, but it is not mandatory to assign all of them. Those that are not assigned get default values in increasing order starting from zero. As a result, assigning only a subset of enum members can be misleading. For numeric enums in particular, that would create a gap in the numerical order, which could lead to unfortunate bugs. In addition, adding more members or moving around existing ones might change their values.
This rule raises an issue whenever an enum assigns a subset of its members, unless the first member only is assigned a numerical literal.
A class declaration also creates a variable with the same name. It is possible to change the value of that variable but this is most likely an error. Even in the best-case scenario, where this is intentional, this is very confusing and should be avoided.
Using the output of a non-boolean assignment as a condition is highly suspicious. Either it was done accidentally, and the assignment operator = was used in place of the equality operator ==
, or it was done with the intent to rely on the automatic conversion of the non-boolean value to a boolean, which could be confusing for maintainers.
In TypeScript, there are two ways to define properties or parameters that are potentially `undefined:
Union with undefined: Adding | undefined in the property type makes the property required, but can be undefined`. Use this syntax when you want to be explicit that an object should provide that property, in which case the TypeScript compiler will not allow omitting it.
In React, the `render function is a required method in a class component that defines what will be rendered to the user interface (UI). It is responsible for returning a value, typically a JSX (JavaScript XML) expression, that describes the structure and appearance of the component’s UI.
When writing the render function in a component, it is easy to forget to return the JSX content, which means the component will render nothing. Thus having a render function without a single return` statement is usually a mistake.
Arrow functions in JavaScript provide a concise syntax to write function expressions. However, the use of braces {} and parentheses () should be consistent in arrow functions for the following reasons:
Readability: Consistent use of braces and parentheses improves the readability of the code. It makes it easier for other developers to understand the code quickly and reduces the chances of misinterpretation.
Predictability: When braces and parentheses are used consistently, it makes the code more predictable. Developers can easily predict the outcome of the function.
Avoid Errors: Inconsistent use of braces and parentheses can lead to errors. For example, if braces are omitted for a function that has more than one statement, it will result in a syntax error.
Code Maintenance: Consistent use of braces and parentheses makes the code easier to maintain. It’s easier to add or remove code lines without worrying about adjusting braces or parentheses.
Shared coding conventions allow teams to collaborate effectively. This rule raises an issue when using parentheses and curly braces with an arrow function does not conform to the configured requirements.
TypeScript allows assigning values to enum members. However, it does not enforce uniqueness between the values of such members. As a result, assigning the same value to different members is possible.
The rule raises issues on duplicate values because they are misleading and can lead to bugs that are hard to track down.
In JavaScript, the semicolon (;
) is optional as a statement separator, but omitting semicolons can be confusing, and lead to unexpected results because a semicolon is implicitly inserted at the end of each line.
React JSX differs from the HTML standard in the way it handles newline characters and surrounding whitespace. HTML collapses multiple whitespace characters (including newlines) into a single whitespace, but JSX removes such sequences completely, leaving no space between inline elements separated by the line break. This difference in behavior can be confusing and may result in unintended layout, for example, missing whitespace between the link content and the surrounding text.
To avoid such issues, you should never rely on newline characters in JSX, and explicitly specify whether you want whitespace between inline elements separated by a line break.
In JavaScript, props are typically passed as plain objects, which can lead to errors and confusion when working with components that have specific prop requirements. However, it lacks of type safety and clarity when passing props to components in a codebase.
By defining types for component props, developers can enforce type safety and provide clear documentation for the expected props of a component. This helps catch potential errors at compile-time. It also improves code maintainability by making it easier to understand how components should be used and what props they accept.
When using JSX the component children should be passed between opening and closing tags. Passing children in a children prop may work sometimes, but will lead to errors if children are passed both as nested components and children prop at the same time.
When not using JSX, the children should be passed to createElement() method as extra arguments after the props object.
The usage of non-null assertion on the left-hand side of an assignment or comparison can be misread and produce unexpected results when one would expect a negative comparator.
The strict equality operator in JavaScript is represented by three equal signs (`===), the strict inequality with (!==). It is used to compare two values for equality, but with an important difference from the regular equality operator (==). The strict equality operator compares both value and type, while the regular equality operator only compares values after performing type coercion if necessary.
The problem with using the strict equality operator (===) with operands of dissimilar types lies in the way JavaScript handles the comparison. When you use ===` to compare two values of different types, it will always return false since their types are different, regardless of whether the values could be considered equal under certain conditions.
The use of literals (primitive values such as strings, numbers, booleans, etc.) for promise rejection is generally discouraged. While it is syntactically valid to provide literals as a rejected promise value, it is considered best practice to use instances of the Error class or its subclasses instead.
Using an instance of the Error class allows you to provide more meaningful information about the error. The Error class and its subclasses provide properties such as message and stack that can be used to convey useful details about the error, such as a description of the problem, the context in which it occurred, or a stack trace for debugging.
Regular expressions in JavaScript can have a global flag (/g
) that enables global searching and matching. While this flag can be useful in certain scenarios, it should be used with caution. When a regular expression has the global flag enabled, it remembers the position of the last match and continues searching for subsequent matches from that position. This behavior can lead to unexpected results if you’re not careful and be a source of bugs that are tricky to debug.
The global flag introduces shared state within the regular expression object. This means that if you use the same regular expression object across multiple operations or functions, it maintains its internal state, such as the last match position.
Initializing a variable to undefined is unnecessary and should be avoided. A variable will automatically be set to undefined if you declare it without initialization, so the initialization code is redundant in this case.
Even though it may be a good practice to enforce JavaScript strict mode, doing so could result in unexpected behaviors on browsers that do not support it yet. Using this feature should therefore be done with caution and with full knowledge of the potential consequences on browsers that do not support it.
The var statement declares variables that are function-scoped or globally-scoped. var declarations are hoisted, meaning declaring a variable anywhere in the code is equivalent to declaring it at the top of the function or the script.
Even if hoisted, it is still recommended to declare the variable inside the block it is used. This improves readability and maintainability because it makes it clear where the variable is being used. The code then becomes easier to understand and follow, especially for other developers who may be working on the same codebase.
Assigning a value to an import variable will cause a runtime error and will raise a compilation error in TypeScript.
Defining functions inside loops in JavaScript can lead to several issues and is generally considered bad practice. The main problems associated with this approach are related to performance, scope, and potential unintended behavior:
When a function is defined inside a loop, the function is re-created on each iteration of the loop. This can cause unnecessary overhead and lead to performance issues, especially if the loop runs repeatedly. Defining the function outside the loop is more efficient so that it is created only once.
Functions defined inside loops have access to the loop’s variables and parameters. This can sometimes lead to unintended behavior or bugs due to closures. Closures in JavaScript capture the environment in which they are created, including variables and parameters, and this can cause unexpected results when those variables change during the loop.
Code that defines functions inside loops can be harder to read and maintain, especially for other developers who might not expect functions to be redefined within the loop. Keeping functions separate and clearly defined is better, improving code organization and understandability.
lnerabilities by treating all values as untrusted by default. Untrusted values are systematically sanitized by the framework before they are inserted into the DOM.
Still, developers have the ability to manually mark a value as trusted if they are sure that the value is already sanitized. Accidentally trusting malicious data will introduce an XSS vulnerability in the application and enable a wide range of serious attacks like accessing/modifying sensitive information or impersonating other users.
Renaming imports, exports, or destructuring assignments to the same name is redundant and can be safely removed. You may accidentally end up with such code if you do a refactoring and change the local name in several places.
The yield keyword is used in a generator function to return an IteratorResult to the caller. It has no other purpose, and if found outside such a function will raise a ReferenceError
because it is then treated as an identifier.
Setting timeouts with Mocha allows you to control the maximum time a test case or suite can take to execute. However, incorrect usage or excessive timeout values can lead to undesired consequences and impact the effectiveness of your test suite. For example, setting a timeout by calling this.timeout()
with a value greater than the maximum delay (2,147,483,647 ms) will cause the timeout to be disabled.
To optimize the rendering of React list components, a unique identifier (UID) is required in the key attribute for each list item. This UID lets React identify the item throughout its lifetime. Using generated values like Math.random() or Date.now() is discouraged as their return value will differ between calls, causing the keys to not match up between renders, recreating the DOM. Also, this may cause bugs if values collide.
ects or dynamically assigning object properties from strings may be prone to Prototype Pollution vulnerabilities in JavaScript. Prototype Pollution vulnerabilities allow to inject new properties into the built-in Object.prototype
object. Since most objects inherit from this prototype, it can result in unexpected behavior, e.g., crashes or more severe vulnerabilities.
Recursively merging objects or dynamically assigning object properties from strings has led in the past to the following vulnerabilities:
Creating multiline strings by using a backslash () before a newline is known as “line continuation” or “line breaking.” While it may seem like a convenient way to format multiline strings, it is generally considered bad practice.
Line continuation can make the code harder to read and understand, especially when dealing with long strings. It introduces an extra character at the end of each line, which can clutter the code and reduce its readability.
If the string content changes, it might require reformatting the entire multiline string, involving adjusting the line breaks and ensuring the backslashes are correctly placed. This can be error-prone and cumbersome, leading to maintenance issues.
Line continuation can sometimes behave unexpectedly, particularly when there are trailing spaces or tabs after the backslash. This can lead to subtle bugs that are difficult to spot and debug.
JavaScript will automatically insert semicolons when parsing the code so invalid sequences can be “fixed” to valid syntax. This behavior, called “Automatic semicolon insertion” or ASI, makes semicolons at the end of statements optional and attempts to make JavaScript more approachable and convenient.
However, sometimes, relying on ASI can lead to unexpected results. ASI will only be triggered if a line break separates tokens that would otherwise produce invalid syntax. JavaScript will not insert semicolons if the next token can be parsed as part of a valid structure.
In the case of function call arguments, they are allowed to be on a separate line. But, depending on the developer’s intent and, especially when working with IIFE (or any other design pattern using Grouping operator), it can lead to errors and most likely will lead to questions for maintainers.
What was the initial intent of the developer?
Defining a function and then executing some unrelated code inside a closure?
Passing the second function as a parameter to the first one?
The first option will be the one chosen by the JavaScript interpreter.
When an object is created with a setter for a property but without a getter for that property, the property is inaccessible and is thus useless.
This rule also enforces the reverse situation (getter but no setter).
When using an object in a string context, a developer wants to get the string representation of the state of an object, so obtaining [object Object] is probably not the intended behaviour and might even denote a bug.
The `done callback of Mocha is used to signal the end of an asynchronous test. It is called when the test is complete, either successfully or with an error. It is important not to follow the done callback with code because the test may not have completed yet, and the code may execute before the test is finished. This can lead to unpredictable results and make it difficult to debug issues.
It is recommended to use the done callback only to signal the end of the test and handle any necessary cleanup or assertions before the callback.
Here’s a bad example of using Mocha’s done` callback:
Test files in JavaScript and TypeScript are meant to contain test cases. These test cases are used to verify the functionality of your code and ensure that it behaves as expected. If a test file doesn’t contain any test cases, it’s not serving its purpose.
A test file without test cases might indicate:
An incomplete test suite: Perhaps the developer started writing tests but didn’t finish.
A mistake: The developer might have accidentally deleted the test cases or moved them to another file.
This rule flags any file that has .test or .spec as part of its suffix but does not contain any test cases defined using the different forms of the it and test
functions from Jasmine, Jest, Mocha, or Node.js testing API.
Nested functions refer to the practice of defining a function within another function. These inner functions have access to the variables and parameters of the outer function, creating a closure.
While nesting functions is a common practice in JavaScript, deeply nested functions can make the code harder to read and understand, especially if the functions are long or if there are many levels of nesting.
This can make it difficult for other developers or even yourself to understand and maintain the code.
By convention, constructor function names should start with an upper case letter as a reminder that they should be called with the new
keyword.
A function is considered to be a constructor when it sets all of its arguments as object properties, and returns no value.
When using the Backbone.js framework, the names of model attributes should not contain spaces. This is because the Events object accepts space-delimited lists of events, so an attributes with spaces in the names could be misinterpreted.
Expressions with arithmetic (/, *, %, ++, —, -, -=, *=, /=, %=, +=, +), unary (-), or comparison operators (>, <, >=, <=
) where one, or both, of the operands is a String, Boolean or Date value rely on implicit conversions. Both the maintainability and reliability levels of such a piece of code are questionable.
In React, findDOMNode is used to get the browser DOM node given a component instance. However, using findDOMNode is fragile because the connection between the JSX node and the code manipulating the corresponding DOM node is not explicit. For example, changing the external structure of returned JSX will affect the return value of findDOMNode. There are also other caveats when using findDOMNode.
There’s no reason to repeat a default type unless it is early in a list and other, non-default types come after it. Instead, leave it out and only supply type when it is something other than the default.
When a collection is empty with absolute certainty, it makes no sense to access or iterate it. Doing so can lead to unexpected behavior or errors in the code. The most common cause is that population was accidentally omitted or removed.
In React, calling setState is the primary way to update a component’s state. However, calling setState is often asynchronous. React batches state updates for performance reasons, which means that when you call setState, React doesn’t immediately update the state and trigger a re-render. Instead, it schedules the update for later, and multiple setState calls within the same event handler or function may be batched together. This can lead to unexpected behavior if you assume that state updates are immediate. Therefore, you should not rely on their values for calculating the next state.
Originally JavaScript didn’t support `classes, and class-like behavior had to be kludged using things like prototype assignments for “class” functions. Fortunately, ECMAScript 2015 added classes, so any lingering prototype uses should be converted to true classes. The new syntax is more expressive and clearer, especially to those with experience in other languages.
Specifically, with ES2015, you should simply declare a class` and define its methods inside the class declaration.
Errors should not be created without being thrown because they can confuse and make it difficult to debug code. When an error is thrown, it means that something unexpected has happened, and the program cannot continue executing as expected. By creating an error without throwing it, it may appear as if everything is working correctly, but in reality, an underlying issue must be addressed.
The .bind() method allows specifying the value of this and, optionally, the values of some function arguments. However, if this is not used in the function body, calls to .bind() do nothing and should be removed.
Calling .bind() on arrow functions is a bug because the value of this does not change when .bind() is applied to arrow functions.
When if is the only statement in the else block, it is better to use else if because it simplifies the code and makes it more readable.
When using nested if statements, it can be difficult to keep track of the logic and understand the flow of the code. Using else if makes the code more concise and easier to follow.
The use of DOM attributes that are only supported by specific browsers can doom your website to obsolescence as the browser market shifts or the vendor that introduced the extension abandons it. Instead, it’s always best to stick to standard attributes so that your site works for as broad a cross section of users as possible.
This rule raises an issue when innerText
is used.
The types of the arguments that built-in functions accept are specified in the JavaScript language specification. Calls to these functions should conform to the documented types as they are designed to work with specific data types. If the arguments passed to these functions do not match the expected types, it can lead to type errors or unexpected behavior.
Additionally, passing the correct types of arguments to built-in functions can improve performance by reducing the need for type conversions and other operations.
When using testing frameworks like Mocha and Jest, appending .only() to the test function allows running a single test case for a file. Using .only() means no other test from this file is executed. This is useful when debugging a specific use case.
In a for loop, the update clause is responsible for modifying the loop counter variable in the appropriate direction to control the loop’s iteration. It determines how the loop counter variable changes with each iteration of the loop. The loop counter should move in the right direction to prevent infinite loops or unexpected behavior.
This rule raises an issue when the loop counter is updated in the wrong direction with respect to the loop termination condition.
This rule checks that all string literals use the same kind of quotes.
The with statement introduces a new scope, where properties of an object can be accessed directly without having to specify the object’s name explicitly. However, using it is generally considered a bad practice and is strongly discouraged.
While it might seem convenient at first, it can lead to several issues:
The with statement can make code more ambiguous and harder to read. When reading the code, it becomes unclear where variables or properties are coming from, as they can be from the object in the with statement or any of its parent scopes.
The with statement negatively impacts performance. JavaScript engines have a harder time optimizing code with with because it adds uncertainty to variable lookups, which can result in slower execution.
Using with can lead to bugs that are difficult to identify and troubleshoot. If a variable is not found in the object within the with statement or its parent scopes, JavaScript will create a new global variable instead, potentially leading to unexpected behavior.
As a result of these issues, ECMAScript 5 (ES5) strict mode explicitly forbids the use of the with statement. Strict mode was introduced to enhance code safety and maintainability, and it helps to catch potential issues and discourage the use of problematic language features.
The Object.hasOwn() method was introduced in ES2022 as a replacement for the more verbose Object.prototype.hasOwnProperty.call(). These methods return true if the specified property of an object exists as its own property. If the property is only available further down the prototype chain or does not exist at all - the methods return false.
If you are still using the old method - replace it with a simpler and more concise alternative.
You should also avoid calling the obj.hasOwnProperty() method directly, without using Object.prototype as a source. This can lead to a runtime error if obj.prototype is null and therefore obj.hasOwnProperty is undefined. The static method Object.hasOwn() does not depend on the obj.prototype and is therefore safe to use in such cases.
If a local variable or a local function is declared but not used, it is dead code and should be removed. Doing so will improve maintainability because developers will not wonder what the variable or function is used for.
React’s useState
hook setter function should not be called directly in the body of a component, as it would produce an infinite render loop. A re-rendering occurs whenever the state of a component changes. Since a hook setter function changes the component’s state, it also triggers re-rendering.
The loop “state updates → triggers re-render → state updates → triggers re-render → …” will continue indefinitely.
This rule raised an issue when a component is used in the render() method and not import
ed or defined.
React works in two phases: render and commit.
The render phase determines what changes need to be made to e.g. the DOM. During this phase, React calls render and then compares the result to the previous render.
The commit phase is when React applies any changes. (In the case of React DOM, this is when React inserts, updates, and removes DOM nodes.) React also calls lifecycles like componentDidMount and componentDidUpdate during this phase.
Render phase lifecycles include among others, the following lifecycle methods:
componentWillMount (or its alias UNSAFE_componentWillMount)
componentWillReceiveProps (or its alias UNSAFE_componentWillReceiveProps)
componentWillUpdate (or its alias UNSAFE_componentWillUpdate)
These are considered unsafe and also happen to be the lifecycles that cause the most confusion within the React community and tend to encourage unsafe coding practices.
An exception thrown inside a promise will not be caught by a nesting try
block due to the asynchronous nature of execution.
Promises are designed to propagate errors to the next error handler or catch() block in the promise chain. Promises are asynchronous and operate outside of the normal call stack. When a Promise is created, it is added to the microtask queue, which is processed after the current call stack has completed. This means that the try-catch block surrounding the Promise will have already completed by the time the Promise is resolved or rejected. Therefore, any error occurring within the Promise will not be caught by the try-catch block.
Once you’ve made a selection, you typically want to know whether it actually found anything. Since selectors always return an object (the set of selected DOM elements), the best way to see whether your selection found anything is to test the returned object’s .length
property.
Loop counters, such as variables used to track the iteration count in loops, should not be assigned from within the loop body to avoid unexpected behavior and bugs. It can inadvertently lead to an infinite loop or make the loop behavior more complex and harder to reason about.
The private class members were introduced in ES2022 and use # (hash) symbol prefix. It is possible to declare private fields, methods, getters and setters as well as their static counterparts. The private members are only accessible from within the current class body and aren’t inherited by subclasses. They also cannot be removed with delete operator.
ermissions/#powerful-feature[Powerful features] are browser features (geolocation, camera, microphone …) that can be accessed with JavaScript API and may require a permission granted by the user. These features can have a high impact on privacy and user security thus they should only be used if they are really necessary to implement the critical parts of an application.
This rule highlights intrusive permissions when requested with the future standard (but currently experimental) web browser query API and specific APIs related to the permission. It is highly recommended to customize this rule with the permissions considered as intrusive in the context of the web application.
React components have built-in state data. This data is used to store component property values. When state changes, the component is re-rendered. React provides the useState hook to manage the state. useState returns a state variable retaining the data and a state setter function to update its value.
React will skip re-rendering the component and its children if the new value you provide is identical to the current state, as determined by an Object.is comparison. When the setter function is called with the state variable as a parameter, that comparison will always be true, and the component will never be re-rendered. This can happen by mistake when attempting to reset a default value or invert a boolean, among others.
This rule raises an issue when calling the setter function with the state variable provided by the same useState React hook.
When either the equality operator in a test for null or undefined, or the logical operator that follows it is reversed, the code has the appearance of safely null-testing the object before dereferencing it. Unfortunately the effect is just the opposite - the object is null-tested and then dereferenced only if it is null/undefined, leading to a guaranteed TypeError
.
The magic of JavaScript is that you can pass arguments to functions that don’t declare parameters, and on the other side, you can use those passed-in arguments inside the no-args `function.
But just because you can, that does’t mean you should. The expectation and use of arguments inside functions that don’t explicitly declare them is confusing to callers. No one should ever have to read and fully understand a function to be able to use it competently.
If you don’t want to name arguments explicitly, use the …` syntax to specify that an a variable number of arguments is expected. Then inside the function, you’ll be dealing with a first-class array, rather than an array-like structure.
eval is used to evaluate a string as JavaScript code, and arguments is used to access function arguments through indexed properties. As a consequence, eval and arguments
should not be bound or assigned, because doing so would overwrite the original definitions of those two reserved words.
What’s more, using either of those two names to assign or bind will generate an error in JavaScript strict mode code.
Assigning `this to a local variable is a way to reference parent context inside inner functions. In TypeScript when using arrow functions this happens automatically.
This rule raises an issue when this` is assigned to a local variable.
Having the same module imported multiple times can affect code readability and maintainability. It makes hard to identify which modules are being used.
Both `if-else chains and switch statements are used for conditional branching, but they differ in their syntax and the way they handle multiple conditions.
In an if-else chain, each condition is checked in order, and only the block associated with the first true condition is executed. If no condition is true, the code inside the else block (if present) will be executed.
In a switch statement, the expression is evaluated once, and its value is compared against each case. If a matching case is found, the corresponding block of code is executed. The break statement is used to exit the switch block after a match. If no case matches the expression, the code inside the default block (if present) will be executed.
Having the same condition in both if-else chains and switch` cases can lead to unreachable code and a potential source of bugs. It defeats the purpose of conditional branching and can make the code harder to read and maintain.
Regular expressions are used for pattern matching within strings. They can be defined upon special characters, meaning symbols or metacharacters with a reserved meaning that convey specific instructions to the regex engine. These characters are not treated as literals but have special functions in defining patterns, among which stand out anchors and disjunctions.
An anchor allows you to match positions in the input string rather than matching specific characters. Anchors help you identify specific locations within the string where a pattern should start (`^) or end ($).
A disjunction, also known as alternatives, represented by the vertical bar (|) allows you to specify multiple alternative patterns that the regex engine will attempt to match in the input string.
Mixing anchors with alternatives in regular expressions can lead to confusion due to their precedence rules. Alternatives (|) have a lower precedence than anchors (^ and $). As a result, if you don’t use non-capturing groups (?:…)` to group the alternatives properly, the anchors might apply to the ends only rather than the entire disjunction, which could not be the initial intent.
The void operator evaluates its argument and always returns undefined. void allows using any expression where an undefined is expected. However, using void makes code more difficult to understand, as the intent is often unclear.
Assertions are statements that check whether certain conditions are true. They are used to validate that the actual results of a code snippet match the expected outcomes. By using assertions, developers can ensure that their code behaves as intended and identify potential bugs or issues early in the development process.
An incomplete assertion refers to a situation where an assertion is written but lacks some necessary components or conditions, making it insufficient to fully validate the expected behavior of the code being tested. Writing incomplete assertions can lead to false positives or false negatives in your test suite, making it less reliable.
This rule checks for incomplete assertions with Chai.js in the following cases:
When `assert.fail, expect.fail or should.fail are present but not called.
When an expect(…) or should assertion is not followed by an assertion method, such as equal.
When an expect or should assertion ends with a chainable getters, such as .that, or a modifier, such as .deep.
When an expect or should assertion function, such as .throw`, is not called.
In such cases, what is intended to be an assertion doesn’t actually assert anything.
Debug statements are always useful during development. But include them in production code - particularly in code that runs client-side - and you run the risk of inadvertently exposing sensitive information, slowing down the browser, or even erroring-out the site for some users.
A `switch statement is a control flow statement that allows you to execute different blocks of code based on the value of an expression. It provides a more concise way to handle multiple conditions compared to using multiple if-else statements.
If you only have a single condition to check, using an if statement is simpler and more concise. switch statements are designed for handling multiple cases, so using them for a single condition can be overkill and less readable.
This rule raises an issue when a switch statement has only one case clause and possibly a default` one.
Variable declaration is the process of creating a new variable and specifying its name. JavaScript provides three ways to declare variables: using the var, let, and const keywords.
The var keyword is used to declare function-scoped or global-scoped variables, i.e. they are accessible throughout the function or the entire program, respectively.
The let keyword is used to declare block-scoped variables, that is, variables accessible only within the nearest curly braces block where it is defined.
The const keyword is used to declare variables that are constant, meaning their values cannot be reassigned.
Explicitly declaring variables improves code readability and maintainability. It makes it clear to other developers that you are creating a new variable and sets expectations about its scope. It also helps catch typos and avoid potential issues caused by accidentally reusing variable names.
If you assign a value to a variable without declaring it with var, let, or const, JavaScript treats it as an implicit global variable. Implicit globals can lead to unintended consequences and make it difficult to track and manage variables. They can cause naming conflicts, make code harder to understand, and introduce bugs that are hard to trace.
Methods that are never executed are dead code and should be removed. Cleaning out dead code decreases the size of the maintained codebase, making it easier to understand the program and preventing bugs from being introduced.
When using React class components, all non-React lifecycle methods should be called within the scope of the component. If a method is only called from outside the class, consider using props to interact with the component and re-render if needed, as React encourages data-driven components.
In the constructor of a derived class, accessing this or super before super() is called raises a reference error. super()
should always be called first.
`isMounted() is generally used before calling setState to avoid changing the state on an already unmounted component. A user should never be able to do an action on an unmount component unless the component is having a bug in its unmount phase.
This rule raises an issue on each use of isMounted().
isMounted() is not longer available in ES6. Use of isMounted()` must be avoided to ease the upgrade to ES6.
If JSX special characters (>, }) appear unescaped in the element body, this may be either because you simply forgot to escape them or because there is a problem with the JSX tag or expression (for example, misplaced or duplicate closing > or } brackets).
Re-exporting is a feature that allows a file to import a component (object, function or primitive) from a module and add it to the exported components of the file’s module. However, as the language allows a file to export a component without explicitly importing it, a reader may mistake a re-export with a simple export.
Promises are objects that represent the eventual completion or failure of an asynchronous operation. They provide a way to handle asynchronous operations in a more organized and manageable manner. To use await, you need to ensure that you are calling a function or an expression that returns a promise.
The reason await should only be used on a promise is that it expects the operand to be a promise object. When you use await, it waits for the promise to be resolved or rejected and then returns the resolved value or throws the rejection reason, respectively. If the operand of await is not a promise, awaiting it is redundant and might not have been the developer’s intent.
If you try to use await on a non-promise value, such as a regular object or a primitive type, it will not pause the execution of the function because there is no asynchronous behavior involved. Instead, await will convert the value to a resolved promise, and waits for it.
When a given “props” is used more than once in a component, there is great chance it’s a mistake and so the behavior of the application won’t be the one expected.
Unreachable code is the code whose statements cannot be executed under any circumstances. Jump statements, like return, break, continue, and throw
, alter the normal flow of control within a program, making it possible to skip certain parts of the code, terminate loops prematurely, or exit from functions. So any statements that come after a jump are effectively unreachable.
Unreachable statements can be a sign of a logical error or oversight in the program’s design, leading to unexpected behavior at runtime.
Element selections that could be matched anywhere in the document can be very slow. That’s why use of the universal selector, *
, should be limited; it explicitly specifies that the match could be anywhere.
Union types represent a value that can be one of the several types. When a union type is used for a function parameter and it is accepting too many types, it may indicate the function is having too many responsibilities. Sometimes it’s worth creating a type alias for this union type. In all cases, the code should be reviewed and refactored to make it more maintainable.
Shared naming conventions allow teams to collaborate effectively. This rule raises an issue when the brace-style is not respecting the convention setup in parameter:
1tbs (default)
While `:<element_type> and [type=“<element_type>”] can both be used in jQuery to select elements by their type, [type=“<element_type>”] is far faster because it can take advantage of the native DOM querySelectorAll() method in modern browsers.
This rule raises an issue when following selectors are used:
:checkbox
:file
:image
:password
:radio
:reset
:text`
Arrow functions => use a syntax similar to certain comparison operators (<=, >=
). This can create confusion when used in certain contexts.
In JavaScript, labels are identifiers that allow you to name blocks of code, such as loops and conditional statements. They are used in conjunction with statements like break and continue to control the flow of execution within nested loops and conditionals.
It’s worth noting that labels are not widely used in modern JavaScript programming because they can lead to complex and hard-to-maintain code. In most cases, there are better alternatives to achieve the desired control flow without resorting to labels.
The size of a collection and the length of an array are always greater than or equal to zero. Testing it doesn’t make sense, since the result is always true
.
When an object method is assigned to a variable, it is most likely a mistake: the parentheses have been left off the method invocation. When this is actually done on purpose, it will llikely yield unpredictable results since the method will have been designed to work in a different scope (the scope of the object) than it will execute in (the global scope).
Ignoring function parameters or overwriting them with a new value without reading them can lead to confusion and errors in the code. Developers won’t be able to tell whether the original parameter or some temporary variable is being accessed without going through the whole function. It may indicate that the function is not properly designed or that there is a mistake in the code.
Moreover, some developers might also expect assignments of function parameters to be visible to callers, which is not the case. Arguments are always passed by value and never passed by reference. If a function reassigns a parameter, the value won’t change outside the function. It is not possible to simulate an assignment on that variable in the caller’s scope. However, objects are passed by value to their reference (passed by sharing), which means if the object’s properties are mutated, the change will impact the outside of the function.
The same logic applies to caught exceptions and variable declarations inside for…in and for…of
statements: their initial values should not be ignored.
In React, useState is a hook that allows functional components to manage and update state in a manner similar to class components. When you use the useState hook, it returns an array with two values: the current state value and a function to update that state value.
Destructuring these values and naming them symmetrically (i.e., using consistent variable names for both the current state and the update function) is a recommended best practice:
When you destructure and name the values symmetrically, it makes your code more readable and self-explanatory. Other developers can quickly understand the purpose of each variable without needing to refer back to the useState function call.
Following a naming convention where the state variable and its corresponding update function have similar names is a common practice in the React community. It helps maintain consistency and makes it easier for others to understand your code.
If you don’t name the variables symmetrically, it can lead to confusion, especially in larger components or when multiple state variables are involved. You might accidentally use the wrong variable when updating the state, which can result in bugs that are hard to track down.
Type assertion can be done in two ways: with as MyType or with <MyType>. But since there is an ambiguity in the latter when using JSX and there is no ambiguity in the former, as
is preferred.
Calling a literal throws a TypeError, and is likely the result of an unintentional error in the code.
This rule raises an issue when an attempt is made to use a literal as a function.
Destructuring is a convenient way of extracting multiple values from data stored in (possibly nested) objects and arrays. It can make code more concise and expressive by directly extracting values or properties needed from arrays or objects. However, it is possible to define an empty pattern that has no effect, where no variables are bound to the destructured values.
Using the this
keyword inside the scope of an object to refer to the object’s properties and methods yields cleaner, clearer code, and helps avoid confusion when there are variables or functions outside the object scope with the same or similar names.
The ECMAScript specification defines a set of special words as future keywords of the language. They don’t have particular meaning for now, but they might at some future time.
The list contains the following words:
`await
class
const
enum
export
extends
implements
import
interface
let
package
private
protected
public
static
super
yield`
Some of these words have already been adopted by current versions of ECMAScript, but they are kept to consider legacy JavaScript codebases as well. Others are only reserved when used in strict mode.
These future reserved words should be avoided because they may cause syntax errors if they are ever adopted.
Shared coding conventions allow teams to collaborate effectively. This rule raises an issue when the use of spaces in a rest parameter or with a spread operator does not conform to the configured requirements.
Function parameter names should be unique in JavaScript. Unique parameter names ensure that there is no ambiguity in referring to specific parameters within the function body. If multiple parameters share the same name, it becomes unclear which parameter is being referred to when using that name within the function.
Unique parameter names improve the readability and maintainability of code. When parameter names are descriptive and distinct, it becomes easier for other developers (including yourself) to understand the purpose and functionality of the function.
When parameter names are not unique, the later occurrence of a parameter will overwrite the earlier occurrence, potentially leading to unintended consequences or bugs. This behavior can cause confusion and make the code harder to debug.
The in
operator is used to check if a property is in an object or its prototype chain.
When used on an array, it will compare against the indexes of the array, not the values. This is likely not to be the expected behavior.
The `alt, aria-label and aria-labelledby attributes provide a textual alternative to an image.
It is used whenever the actual image cannot be rendered.
Common reasons for that include:
The image can no longer be found
Visually impaired users using a screen reader software
Image loading is disabled, to reduce data consumption on mobile phones
It is also very important not to set an alternative text attribute to a non-informative value. For example, <img … alt=“logo”> is useless as it doesn’t give any information to the user. In this case, as for any other decorative image, it is better to use a CSS background image instead of an <img> tag. If using CSS background-image is not possible, an empty alt="" is tolerated. See Exceptions below.
This rule raises an issue when:
An <img> element has no alt attribute.
An <input type=“image”> element has no alt, aria-label or aria-labelledby attribute or they hold an empty string.
An <area> element within an image map has no alt, aria-label or aria-labelledby attribute.
An <object> element has no inner text, title, aria-label or aria-labelledby` attribute.
Variables declared with `var have the special property that regardless of where they’re declared in a function they “float” to the top of the function and are available for use even before they’re declared. That makes scoping confusing, especially for new coders.
To keep confusion to a minimum, var` declarations should happen before they are used for the first time.
The value of this depends on which context it appears:
Function: The value of this will depend on how a function was called. The value of this is not always the object that has the function as an own property, but the object that is used to call the function. The methods Function.prototype.call(), Function.prototype.apply(), or Reflect.apply() can be used to explicitly set the value of this. Is it also possible to create a new function with a specific value of this that doesn’t change regardless of how the function is called with Function.prototype.bind(). In non-strict mode, this will always be an object and will default to globalThis if set to undefined or null.
Arrow function: The value of this will be the same as the enclosing context. Arrow functions will not create a new this binding. When invoking arrow functions using call(), bind(), or apply(), the thisArg parameter is ignored.
Class: Class methods behave like methods in other objects: the this value is the object that the method was accessed on. If the method is not transferred to another object, this is generally an instance of the class. However, for static methods, the value of this is the class instead of the instance.
Global: outside of any functions or classes (also inside blocks or arrow functions defined in the global scope), the value of this depends on what execution context the script runs in.
When a function is called without an explicit object context, the this keyword refers to the global object. This also applies when it is used outside of an object or function. The global this object refers to the global context in which the JavaScript code is executed. This can cause problems when the code is executed in different contexts, such as in a browser or in a Node.js environment, where the global object is different. Such uses could confuse maintainers as the actual value depends on the execution context, and it can be unclear what object the `this keyword is referring to.
In JavaScript’s “strict mode”, using this in the global context will always be undefined`.
User-defined JSX components should use Pascal case because it is a widely accepted convention in the React community. Using Pascal case for component names helps to distinguish them from HTML elements and built-in React components, which are typically written in lowercase. It also improves code readability and makes it easier to differentiate between components and regular HTML tags.
Additionally, adhering to this convention ensures consistency and makes it easier for other developers to understand and work with your code. It is considered a best practice in React development and is recommended by the official React documentation.
Including content in your site from an untrusted source can expose your users to attackers and even compromise your own site. For that reason, this rule raises an issue for each non-relative URL.
The use of comparison operators (<, <=, >=, >
) with strings is not likely to yield the expected results. Make sure the intention was to compare strings and not numbers.
The unary operators + and - can be used to convert some value types to numeric values. But not every value can be converted to a Number type; use it with an object, and result will be NaN
(Not A Number). This can be confusing to maintainers.
Even if your document is arranged in many layers, you don’t have to step through those layers explicitly to select an element. In fact, it’s more efficiently to skim over some of those layers rather than making the JQuery selector engine explicitly step through each one.
Template strings allow developers to embed variables or expressions in strings using template literals, instead of string concatenation. This is done by using expressions like ${variable} in a string between two back-ticks (`
). However, when used in a regular string literal (between double or single quotes) the template will not be evaluated and will be used as a literal, which is probably not what was intended.
Internet Explorer offers a way to change the JavaScript code at runtime using conditional comments (activated by a @cc_on statement found in a comment). Using this preprocessing feature decreases readability and maintainability, and can hinder automated tools. What’s more, it is specific to Internet Explorer and won’t work for other browsers.
Most of the time, using those conditional comments can be easily avoided with some refactoring - using modern cross-browsers JavaScript frameworks and libraries.
In JavaScript, object shorthand syntax is a more concise way to define properties on objects. It was introduced to make object literals more readable and expressive.
In the shorthand syntax, if a variable exists in the scope with the same name as the object key you’re defining, you can omit the key-value pair and just write the variable name. The interpreter will automatically understand that the key and the variable are linked.
Using object shorthand syntax can make your code cleaner and easier to read. It can also reduce the chance of making errors, as you don’t have to repeat yourself by writing the variable name twice.
Session storage and local storage are HTML 5 features which allow developers to easily store megabytes of data client-side, as opposed to the 4Kb cookies can accommodate. While useful to speed applications up on the client side, it can be dangerous to store sensitive information this way because the data is not encrypted by default and any script on the page may access it.
This rule raises an issue when the localStorage and sessionStorage
API’s are used.
In JavaScript, `arguments is a built-in array-like object automatically available within the scope of all non-arrow functions. It allows you to access the arguments the function was called with, even if the number of arguments passed during the function call does not match the number declared in the function signature. arguments has entries for each argument, with the first entry’s index at 0.
The arguments object has two deprecated properties called arguments.caller and arguments.callee, which were used to refer to functions involved in the function invocation chain:
The arguments.callee property contains the currently executing function that the arguments belong to.
The arguments.caller property returns the function that invoked the currently executing function. It was replaced by Function.prototype.caller, which provides the same functionality.
Both arguments.caller and arguments.callee are non-standard, deprecated, and leak stack information, which poses security risks and severely limits the possibility of optimizations.
Accessing arguments.callee, Function.prototype.caller and Function.prototype.arguments in strict mode will throw a TypeError`.
In a Zen-like manner, `NaN isn’t equal to anything, even itself. So comparisons (>, <, >=, <=) where one operand is NaN or evaluates to NaN always return false. Specifically, undefined and objects that cannot be converted to numbers evaluate to NaN when used in numerical comparisons.
This rule raises an issue when there is at least one path through the code where one of the operands to a comparison is NaN, undefined or an Object` which cannot be converted to a number.
TypeScript supports type inference, a mechanism that automatically infers the type of a variable based on its initial value. This means that if you initialize a variable with a particular value, TypeScript will assume that this variable should always hold that type of value.
Unnecessarily verbose declarations and initializations make it harder to read the code and should be simplified. Therefore, type annotations should be omitted from variable and parameter declarations when they can be easily inferred from the initialized or defaulted value.
Shared naming conventions allow teams to collaborate efficiently.
This rule raises an issue when a function or a method name does not match a provided regular expression.
For example, with the default regular expression ^[a-z][a-zA-Z0-9]*$
, the function:
Before ECMAScript 2015, module management had to be ad-hoc or provided by 3rd-party libraries such as Node.js, Webpack, or RequireJS. Fortunately, ES2015, provides language-standard mechanisms for module management, import and export
, and older usages should be converted.
Assertions are statements that check whether certain conditions are true. They are used to validate that the actual results of a code snippet match the expected outcomes. By using assertions, developers can ensure that their code behaves as intended and identify potential bugs or issues early in the development process.
When the unit test is executed, the assertions are evaluated. If all the assertions in the test pass, it means the unit is functioning correctly for that specific set of inputs. If any of the assertions fail, it indicates that there is a problem with the unit’s implementation, and the test case helps identify the issue.
It is not good enough to test if an exception is raised, without checking which exception it is. Such tests will not be able to differentiate the expected exception from an unexpected one.
This rule raises an issue in the following cases:
When an asynchronous Mocha test calls the `done() callback, without parameters, in a catch block, and there is no reference to the caught exception in this block. Either the error should be passed to done() or the exception should be checked further.
When Chai assertions are used to test if a function throws any exception, or an exception of type Error without checking the message.
When Chai assertions are used to test if a function does not throw an exception of type Error` without checking the message.
This rule doesn’t raise an issue when an assertion is negated. In such a case, the exception doesn’t need to be specific.
In Node.js, it’s possible to import modules by specifying an absolute path, such as /lib/foo/bar.js. However, this approach can limit the portability of your code, as it becomes tied to your computer’s file system. This could potentially lead to problems when the code is distributed, for instance, via NPM packages. Therefore, it’s advisable to use relative paths or module names for importing modules to enhance the portability and compatibility of your code across different systems.
Ternary operator should not be used to select between two boolean values, or instead of a logical OR operation. Ternary expressions are often difficult to read, so if a simpler syntax exists, it should be used instead of a ternary expression. This happens when
the expression returns two boolean values
Optional chaining allows to safely access nested properties or methods of an object without having to check for the existence of each intermediate property manually. It provides a concise and safe way to access nested properties or methods without having to write complex and error-prone null/undefined checks.
This rule flags logical operations that can be safely replaced with the ?. optional chaining operator.
When using regular expressions, a capturing group provides extra information about the matched pattern. Named groups will store the matched contents on the groups property of the returned matches.
In TypeScript, a type alias is a way to give a name to a specific type. It allows you to create a new name for an existing type, making your code more expressive and readable. This is especially useful when you are working with complex or lengthy types that you use frequently.
Type aliases should be preferred over complex types like unions or intersections for several reasons:
Type aliases can make your code more readable and maintainable by giving meaningful names to complex types. When you use a type alias, it becomes clear what the type represents, making it easier for other developers (including your future self) to understand the code.
Type aliases promote code reusability. When you define a type alias for a complex type, you can use that alias in multiple places throughout your codebase, reducing duplication and promoting consistency.
Type aliases allow you to abstract away the underlying complexity of types. This promotes encapsulation by hiding implementation details behind a well-named alias, allowing you to change the underlying type in the future without affecting the code that uses the alias.
If you need to modify a complex type, using a type alias means you only need to change the type definition in one place. This change will automatically apply to all usages of the alias.
Type aliases communicate the intent of the type, making it easier for other developers to understand what the type represents. Complex unions and intersections, on the other hand, might require additional comments or documentation to explain their purpose.
Using type aliases can help you avoid excessive nesting of complex types. Nested unions and intersections can quickly become hard to read and maintain, and type aliases can simplify the type definitions.
This rule enforces the rule of three for code refactoring and reports unions and intersections with three or more constituents appearing at least three times in the codebase.
Creating an object without assigning it to a variable or using it in any function means the object is essentially created for no reason and may be dropped immediately without being used. Most of the time, this is due to a missing piece of code and could lead to an unexpected behavior.
If it’s intended because the constructor has side effects, that side effect should be moved into a separate method and called directly. This can help to improve the performance and readability of the code.
This rule enforces the idea to use ES6 style to create React Component instead of the ES5 way.
Unlike strongly typed languages, JavaScript does not enforce a return type on a function. This means that different paths through a function can return different types of values.
Returning different types from a function can make the code less readable and harder to understand. Maintainers may have to spend more time figuring out how the function works and what it returns. Additionally, it can be harder to ensure that the code is free of type-related errors.
In TypeScript, casts and non-null assertions are two mechanisms used to inform the TypeScript compiler about the intended types of variables, expressions, or values in the code. They are used to help the compiler understand the types more accurately and to handle certain situations where type inference might not be sufficient:
A type assertion tells the compiler to treat the value as the specified type, even if the compiler’s type inference suggests a different type.
A non-null assertion is a way to tell the TypeScript compiler explicitly that you are certain that a variable will not be `null or undefined, and you want to access its properties or methods without any null checks.
However, a redundant cast occurs when you perform a type assertion that is not needed because the compiler already knows the type based on the context or explicit type declarations. Similarly, a redundant non-null assertion occurs when you use the non-null assertion operator ! to assert that a variable is not null or undefined`, but the compiler already knows that based on the context.
Both redundant casts and redundant non-null assertions should be avoided in TypeScript code, as they add unnecessary noise, clutter the code, and lead to confusion.
Any variable or function declared in the global scope implicitly becomes attached to the global object (the window object in a browser environment). To make it explicit this variable or function should be a property of window. When it is meant to be used just locally, it should be declared with the const or let
keywords (since ECMAScript 2015) or within an Immediately-Invoked Function Expression (IIFE).
This rule should not be activated when modules are used.
`for…of statements are used to iterate over the values of an iterable object. Iterables are objects implementing the @@iterator method, which returns an object conforming to the iterator protocol. JavaScript provides many built-in iterables that can and should be used with this looping statement.
The use of the for…of statement is recommended over the for` statement when iterating through iterable objects as simplifies the syntax and eliminates the need for a counter variable.
A sparse array is an array in which the elements do not occupy a contiguous range of indices. In other words, there are gaps (or “holes”) between the elements in the array, where some indices have no corresponding value assigned to them.
Including an extra comma in an array literal signifies an empty slot in the array, thus creating a sparse array. An empty slot is not the same as a slot filled with the undefined value. In some operations, empty slots behave as if they are filled with undefined but are skipped in others.
While this is a well-defined behavior, it can be misleading and raises suspicions about the original intent: an extra comma was intentionally inserted, or perhaps the developer meant to insert the missing value but forgot.
Doing an operation on a string without using the result of the operation is useless and is certainly due to a misunderstanding.
Entries in the ASCII table below code 32 are known as control characters or non-printing characters. As they are not common in JavaScript strings, using these invisible characters in regular expressions is most likely a mistake.
In TypeScript, unions and intersections are used to combine multiple types into a single type, allowing you to create more flexible and powerful type definitions.
A union type is represented using the pipe symbol `|. It allows you to declare a variable or parameter that can hold values of different types. The variable can be assigned a value of any type listed in the union.
An intersection type is represented using the ampersand symbol &`. It allows you to combine multiple types into a single type that includes all the properties and methods from each type.
Having duplicated constituents in TypeScript unions and intersections can lead to undesirable behavior and potential issues in your code. TypeScript’s type system aims to provide a strong and sound static type checking to catch errors during development and improve code reliability. Including duplicate constituents in unions or intersections can make the type definitions unnecessarily verbose and redundant. This makes the code harder to read and maintain.
TypeScript provides the type mechanism to create a type alias, that is, a new name to refer to an existing type. It is a nice feature to improve code readability and can be used as documentation. However, aliasing a primitive type, another alias or everyday types like any or unknown is useless and goes against the idea of readable code. As a result, a reader needs to go through the mental exercise of remembering the underlying type behind the alias and loses track of the code’s primary purpose.
Common types come with relevant names and should be used as they are.
The nullish coalescing operator ?? allows providing a default value when dealing with null or undefined. It only coalesces when the original value is null or undefined. Therefore, it is safer and shorter than relying upon chaining logical || expressions or testing against null or undefined explicitly.
This rule reports when disjunctions (||) and conditionals (?) can be safely replaced with coalescing (??).
The TSConfig needs to set strictNullChecks to true for the rule to work properly.
When using the Backbone.js framework, the array of models inside a collection, `collection.models, should not be accessed directly. Doing so bypasses the listeners set on the collection and could put your application in a bad state.
Instead, use get, at` or the underscore methods.
TypeScript provides both numeric and string-based enums. Members of enums can be assigned strings, numbers, both, or none, which default to numbers starting from zero. Although it is possble to mix the types of enum member values, it is generally considered confusing and a bad practice.
Enum members should be consistently assigned values of the same type, that is, strings or numbers.
When a function has multiple return statements and returns the same value in more than one of them, it can lead to several potential problems:
It can make the code more difficult to understand and maintain, as the reader may be unsure why the same value is being returned multiple times. This can introduce ambiguity and increase the chances of misunderstanding the function’s intent.
The use of multiple return statements with the same value might lead someone to assume that each return corresponds to a distinct case or outcome. However, if they all return the same value, it can be misleading and may indicate an oversight or mistake in the code.
When the function needs to be modified or extended in the future, having multiple identical return statements can make it harder to implement changes correctly across all occurrences. This can introduce bugs and inconsistencies in the codebase.
Code readability is crucial for maintainability and collaboration. Having repetitive return statements can lead to unnecessary code duplication, which should be avoided in favor of creating modular and clean code.
This rule raises an issue when a function contains several return
statements that all return the same value.
React props should be read-only because it helps to enforce the principle of immutability in React functional components. By making props read-only, you ensure that the data passed from a parent component to a child component cannot be modified directly by the child component. This helps maintain a clear data flow and prevents unexpected side effects.
If props were mutable, child components could modify the props directly, leading to unpredictable behavior and making it harder to track down bugs. By enforcing read-only props, React promotes a more predictable and maintainable codebase. Additionally, read-only props enable performance optimizations in React’s rendering process by avoiding unnecessary re-renders of components.
Overall, enforcing read-only props in React helps improve code reliability, maintainability, and performance.
JavaScript regular expressions provide Unicode character classses and Unicode property escapes for matching characters based on their Unicode values and Unicode properties respectively. When using Unicode property escapes like \p{Alpha} without the u flag, the regular expression will not match alphabetic characters but rather the ‘\p{Alpha}’ string literal, which is likely a mistake.
This rules raises an issue when Unicode character classses and Unicode property escapes are used without the u flag.
When using the Backbone.js framework, the internal hash containing the model’s state, `model.attributes, should not be accessed directly. Doing so bypasses the listeners set on the model and could put your application in a bad state.
Instead, you should use set to update, get to read, and _.clone(model.attributes)` to obtain a copy.
Parameter properties let you both create and initialize a member in one place, and omit an explicit member declaration and the assignment of the constructor parameter to the member. To use a parameter property, add an accessibility modifier or readonly
, or both in front of the constructor parameter.
While this syntax is very concise it might be confusing for developers who are new to TypeScript.
Shared conventions allow teams to collaborate efficiently. This rule checks that either parameter properties are used everywhere or not at all.
ECMAScript 2015 introduced the ability to extract and assign multiple data points from an object or array simultaneously. This is called “destructuring”, and it allows you to condense boilerplate code so you can concentrate on logic.
This rule raises an issue when multiple pieces of data are extracted out of the same object or array and assigned to variables.
Getters and setters provide a way to enforce encapsulation by providing methods that give controlled access to class fields. However, in classes with multiple fields, it is not unusual that copy and paste is used to quickly create the needed getters and setters, which can result in the wrong field being accessed by a getter or setter.
This rule raises an issue in the following cases:
A setter does not update the field with the corresponding name (if it exists).
A getter:
does not return any value
does not access the field with the corresponding name (if it exists).
Underscore prefixes for fields are supported, so setX() can assign a value to `_x.
The following type of getters and setters are supported:
getX() and setX()`
The contract and expectation of a get
function is that it will return something. Failing to return a value on all paths is surely an error.
Operator precedence determines the order in which different operators are evaluated when an expression contains multiple ones. It helps determine how the expression is parsed and executed. JavaScript follows a specific set of rules to determine operator precedence.
Not being aware of JavaScript’s operator precedence rules can lead to unexpected and potentially incorrect results when evaluating expressions. This is common when misapplying the logical negation operator (`!). For instance, consider the difference between !key in dict and !(key in dict). The first looks for a boolean value (!key) in dict, and the other looks for a string and inverts the result. The same applies for !obj instanceof SomeClass.
This rule raises an issue when the left operand of an in or instanceof operator is negated with !`.
In React, a PureComponent is a class component that is optimized for performance by implementing a shallow comparison of props and state. It is a subclass of the regular React Component class and provides a default implementation of the shouldComponentUpdate method.
The shouldComponentUpdate method is responsible for determining whether a component should re-render or not. By default, it returns true and triggers a re-render every time the component receives new props or state. However, PureComponent overrides this method and performs a shallow comparison of the current and next props and state. If there are no changes, it prevents unnecessary re-renders by returning false.
Therefore, defining a shouldComponentUpdate method while extending PureComponent is redundant and should be avoided. By not defining shouldComponentUpdate, you allow React.PureComponent to handle the optimization for you.
While most script engines support function declarations within blocks, from browser to browser, the implementations are inconsistent with each other.
In TypeScript, optional and default parameters are features that enhance the flexibility and usability of functions by allowing you to define parameters that can be omitted during function calls or have default values assigned to them when not provided explicitly:
Optional parameters are denoted by adding a question mark (`?) after the parameter name in the function declaration. These parameters can be omitted when calling the function, and TypeScript will assign them a value of undefined if they are not provided.
Default parameters are used to assign a default value to a parameter in case the caller does not provide a value for that parameter. Default values are specified in the function declaration using the assignment operator (=) followed by the default value.
When a parameter is defined as optional, it automatically allows that parameter to be omitted during function calls. If you explicitly pass undefined as the value for an optional parameter, it contradicts the purpose of making the parameter optional, making the code less readable and maintainable.
Similarly, when a parameter has a default value, it means that if the caller omits the argument during function calls, the default value will be used automatically. There is no need to pass undefined` explicitly for default parameters, except when they come before a required parameter.
This rule checks that the last argument of a function call is not redundant with regard to the function’s signature.
Most checks against an indexOf value compare it with -1 because 0 is a valid index. Checking against > 0 ignores the first element, which is likely a bug.
ts XSS vulnerabilities by automatically escaping HTML contents with the use of native API browsers like `innerText instead of innerHtml.
It’s still possible to explicity use innerHtml` and similar APIs to render HTML. Accidentally rendering malicious HTML data will introduce an XSS vulnerability in the application and enable a wide range of serious attacks like accessing/modifying sensitive information or impersonating other users.
jQuery doesn’t cache elements for you. If you’ve made a selection that you might need to make again, you should save the selection in a variable rather than making the selection repeatedly.
React components should not be nested, as their state will be lost on each re-render of their parent component, possibly introducing bugs. This will also impact performance as child components will be recreated unnecessarily.
If the goal is to have the state reset, use a key instead of relying on a parent state.
Bitwise operations are operations that manipulate individual bits in binary representations of numbers. These operations work at the binary level, treating numbers as sequences of 32 bits (in 32-bit environments) or 64 bits (in 64-bit environments). However, they should not be used in a boolean context because they have different behaviors compared to logical operators when applied to boolean values:
When applied to boolean values, bitwise AND (&) and OR (`|) perform bitwise operations on the binary representation of the numbers. They treat the operands as 32-bit signed integers and manipulate their individual bits.
Logical AND (&&) and OR (||) are specifically designed for boolean operations. They return a boolean value based on the truthiness or falsiness of the operands.&& returns true if both operands are truthy; otherwise, it returns false. || operator returns true if at least one of the operands is truthy; otherwise, it returns false.
Bitwise operators & and | can be easily mistaken for logical operators && and ||, especially for those who are not familiar with the distinction between them or their specific use cases.
This rule raises an issue when & or |` is used in a boolean context.
The result of an expression with an arithmetic operator /, *, %, ++, —, -, +=, -=, *=, /=, %=, + or unary operator +, - when at least one operand is Object or Undefined will be always a NaN
(Not a Number).
In JavaScript, a setter is a special type of function that is used to set the value of a property on an object. Setters are defined using the `set keyword followed by the name of the property that the setter is associated with.
To set the property, we simply assign a value to it as if it were a regular property. The setter function is automatically called with the value that we assign to the property.
Functions declared with the set` keyword will automatically return the values they were passed. Thus any value explicitly returned from a setter will be ignored, and explicitly returning a value is a mistake.
In TypeScript, intersections are used to combine multiple types into a single one. An intersection type is represented using the ampersand symbol `&. It allows you to combine multiple types into a single type that includes all the properties and methods from each type, thus creating more flexible and powerful type definitions.
However, some of the basic types of TypeScript should not be used with intersections:
The never type represents the type of values that never occur. Intersecting any type with never will always result in type never.
The any type allows to opt-out of type checking during compilation. Expressions of type any allow you to access arbitrary properties, even ones that don’t exist. any comes at the cost of losing type safety, which is one of the main motivations for using TypeScript. Avoid using any when not necessary. Intersecting any type with any will always result in type any.
The undefined and null types are the types for their respective value. Intersecting any type with them will always result in type never.
The void type implies the absence of a type. Intersecting any type with void will always result in type never.
Additionally, an intersection with a type without members (for example, {}`) doesn’t change the resulting type, is redundant, and can be safely removed from the intersection.
Referring to this in React functional components would be an error because the components are just regular JavaScript functions and do not have an object associated with them. Functional components receive their props as a first argument to the component function, so you can access them directly, and it is a common practice to destructure them right away.
When a function is called, it executes its block of code and uses a `return statement within the function to specify the value that the function will produce as its result. This returned value can then be used or assigned to a variable in the calling code.
If a function returns a value that is not used or assigned to a variable, it may indicate that the function is not being used correctly or that there is a mistake in the code. This can make the code harder to understand and maintain, and can also lead to errors if the return value is needed later in the code.
Ignoring the return value of a function can be a sign of poor coding practices. It can indicate that the developer did not fully understand the purpose of the function or did not take the time to properly integrate it into the code.
This rule triggers an issue only on a predefined list of methods from built-in objects (String, Number, Date, Array, Math, and RegExp`) to prevent generating any false-positives.
In addition to being obtuse from a syntax perspective, function constructors are also dangerous: their execution evaluates the constructor’s string arguments similar to the way eval
works, which could expose your program to random, unintended code which can be both slow and a security risk.
In general it is better to avoid it altogether, particularly when used to parse JSON data. You should use ECMAScript 5’s built-in JSON functions or a dedicated library.
The meaning of a boolean parameter may seem perfectly clear when you first write a method call, but that meaning is likely to fade for you over time, and could be completely opaque to those who come behind you.
Instead, object literals should be used.
ECMAScript 2015 added the ability to use template literals instead of concatenation. Since their use is clearer and more concise, they are preferred in environments that support ECMAScript 2015.
Shared coding conventions allow teams to collaborate efficiently. This rule checks that all members of a propTypes
structure match a provided regular expression.
The Array.prototype.reduce() method in JavaScript is used to apply a function against an accumulator and each element in the array (from left to right) to reduce it to a single output value. It is a convenient method that can simplify logic in your code.
However, it’s important to always provide an initial value as the second argument to reduce(). The initial value is used as the first argument to the first call of the callback function. If no initial value is supplied, JavaScript will use the first element of the array as the initial accumulator value and start iterating at the second element.
This can lead to runtime errors if the array is empty, as reduce() will throw a TypeError.
On the principle that clearer code is better code, you should explicitly import the things you want to use in a module. Using import * imports everything in the module and risks confusing maintainers. Similarly, export * from “module”;
imports and then re-exports everything in the module and risks confusing not just maintainers but also the module’s users.
When you call a function in JavaScript and provide more arguments than the function expects, the extra arguments are simply ignored by the function.
Every call to a function with a non-void return type is expected to return some value. If there is no value that’s valid, you should `return undefined; rather than using a void return (return;). Conversely, every call to a function with a void return type is expected to not return any value, even undefined.
This rule raises an issue when undefined` is returned from a void function, and when void is returned from a non-void function.
Assertions are statements that check whether certain conditions are true. They are used to validate that the actual results of a code snippet match the expected outcomes. By using assertions, developers can ensure that their code behaves as intended and identify potential bugs or issues early in the development process.
In Chai.js, there is no inherent problem with giving the same argument twice in an assertion. It won’t cause any errors or issues in the test execution itself. The test will still run and pass as long as the assertion is correct.
However, having the same argument twice in an assertion might indicate a design issue or a potential mistake in your test. In most cases, you don’t need to compare a variable to itself in a test, as it doesn’t provide any meaningful validation and is likely to be a bug due to the developer’s carelessness.
This rule raises an issue when a Chai assertion is given twice the same argument.
React has a special prop called dangerouslySetInnerHTML that allows you to assign a raw HTML string to the underlying DOM innerHTML property. Changing innerHTML will replace the element’s child nodes or text content. For this reason, dangerouslySetInnerHTML should never be used together with component children as they will conflict with each other, both trying to set the inner content of the same element.
Call a non-callable symbol will result in a TypeError at execution.
An empty interface is equivalent to an empty object (’{}’). Normally you cannot directly assign an object literal to a type when the object literal contains more properties than are specified in the type. But in the case of an empty interface, this check is not done, and such assignments will be successful. The result is highly likely to confuse maintainers.
In JavaScript, the `String.prototype.replace() method is used to replace parts of a string with new substrings. It allows you to perform simple to complex string replacements based on either a static string or a regular expression pattern.
When the first argument is a regular expression, the method will use the regular expression to search for matches within the original string and then replace those matches with the specified replacement. If the second argument is a string, the method will use it as the static replacement for the matched substrings found by the regular expression.
Within the replacement string, the function supports special placeholders to insert the matched values of capturing groups from the regular expression:
The $n syntax allows you to reference capturing groups by their numerical index. The number n corresponds to the order in which the capturing group appears in the regular expression, starting from 1 for the first capturing group.
The $<Name> syntax allows you to reference capturing groups by their name. Instead of using numerical indices, you can assign a name to a capturing group using ?<Name> within the regular expression.
If the second argument of String.prototype.replace() references non-existing groups (capturing groups that do not exist in the regular expression), the behavior of the replacement will depend on the specific references made. It won’t cause an error, but the replacement will not be based on any captured values, potentially leading to unexpected results in the replaced string:
If the replacement string contains references like 1,2, etc., to capturing groups that don’t exist in the regular expression, those references will be treated as literals. In other words, the nwillbereplacedwiththeliteraltextn itself.
If the replacement string contains references like $<Name>, they will also be treated as literals, but only if there are no named captures in the regular expression; otherwise, they will be replaced with the empty string.
This rule checks that all referenced groups exist when replacing a pattern with a replacement string using String.prototype.replace() or String.prototype.replaceAll()` methods.
A for loop is a type of loop construct that allows a block of code to be executed repeatedly for a fixed number of times. The for loop is typically used when the number of iterations is known in advance, and consists of three parts:
The initialization statement is executed once at the beginning of the loop, and is used to initialize the loop counter or any other variables that may be used in the loop.
The loop condition is evaluated at the beginning of each iteration, and if it is true, the code inside the loop is executed.
The update statement is executed at the end of each iteration, and is used to update the loop counter or any other variables that may be used in the loop.
JavaScript has the new keyword that is used in conjunction with constructor functions to create new instances of objects. When you use the new
keyword with a function, it signifies that the function is intended to be used as a constructor function to create objects.
Any function can be used as a constructor function by convention. Constructor functions are used to create new objects with the same structure or properties. They are typically named with an initial capital letter to distinguish them from regular functions.
In JavaScript, a generator is a special type of function that can be paused and resumed during its execution. It allows you to define an iterative algorithm by writing a function that can maintain its internal state and produce a sequence of values over time.
Generators are defined using a function syntax with an asterisk () appended to the function keyword (function). Within the generator function, you can use the yield
keyword to produce a value and temporarily pause the execution of the function, returning that value to the consumer.
HTML5’s cross-window messaging adds the ability to send messages directly from one window (or iframe) to another, without having to go through a server. This makes it easier to write interesting and responsive web sites, but adds vulnerability as well, since the same-origin policy does not apply here. For that reason, cross-window messaging listeners should always check message origins and use only those from trusted sites.
This rule raises an issue on each cross-window messaging listener that does not check message origins.
HTML-style comments are not part of EcmaScript specification, and should not be used.
The `delete operator can be used to remove a property from any object. Arrays are objects, so the delete operator can be used on them too.
When you delete an element from an array using the delete keyword, it will remove the value but still leave behind an empty slot at that index. Therefore, a hole will be created in the array because the indexes won’t be shifted to reflect the deletion. This means that the array will still have that index, but the value will be undefined`.
Arrays that have gaps or missing indexes between elements are known as sparse arrays.
The TypeScript programming language supports generics, a programming construct for creating reusable components, that is, components that can work over various types rather than a single one. Sometimes, we need to limit this genericity to a specific set of types, typically when we know these types share common capabilities, e.g., a length property. To this end, the language provides the extends clause to describe type constraints on type parameters, whether for classes, interfaces, type aliases, or functions.
By default, a type parameter extends the any type. It is therefore redundant to explicitly extend from any and should be removed accordingly.
If you have an iterable, such as an array, set, or list, your best option for looping through its values is the for of syntax. Use for in
and you’ll iterate the properties, rather than the values.
In TypeScript, any is a type that is used when the type of a variable is unknown or could be of any type. It allows you to opt-out of type-checking and let the values pass through compile-time checks. In other words, it prevents the compiler from reporting type errors, which can lead to runtime errors.
On the other hand, unknown is a type-safe alternative to any. It forces you to perform certain checks before performing operations on variables of type unknown. This means you can’t accidentally perform arbitrary operations on variables of type unknown, which helps prevent runtime errors.
It’s generally recommended to avoid using any when possible, and instead use more specific types or generics for better type safety. If you want to maintain type safety, it’s better to use unknown instead of any.
In JavaScript, some `Array methods do not mutate the existing array that the method was called on, but instead return a new array. Other methods mutate the array, and their return value differs depending on the method.
reverse and sort` are mutating methods and, in addition, return the altered version. This rule raises an issue when the return values of these methods are assigned, which could lead maintainers to overlook the fact that the original array has been modified.
When loading modules dynamically, malicious user input could find its way to the parameter specifying the module path and name. This could allow an attacker to load and run arbitrary code, or access arbitrary files.
This rule raises an issue for each use of dynamic module loading.
A unit test assertion should have only one reason to succeed because it helps to ensure that the test is focused and specific. When a test has multiple reasons to succeed, it becomes difficult to determine the root cause of a failure if the test fails. This can lead to confusion and wasted time trying to debug the test.
This rule raises an issue when the following Chai.js assertions are found:
When `.not and .throw are used together and at least one argument is provided to .throw. Such assertions succeed when the target either does not throw any exception, or when it throws an exception different from the one provided.
When .not and .include are used together and an object is given to .include. Such assertions succeed when one or multiple key/values are missing.
When .not and .property are used together and .property is given at least two arguments. Such assertions succeed when the target either doesn’t have the requested property, or when this property exists but has a different value.
When .not and .ownPropertyDescriptor are used together and .ownPropertyDescriptor is given at least two arguments. Such assertions succeed when the target either doesn’t have the requested property descriptor, or its property descriptor is not deeply equal to the given descriptor
When .not and .members are used together. Such assertions succeed when one or multiple members are missing.
When .change and .by are used together. Such assertions succeed when the target either decreases or increases by the given delta
When .not and .increase are used together. Such assertions succeed when the target either decreases or stays the same.
When .not and .decrease are used together. Such assertions succeed when the target either increases or stays the same.
When .not negates .by. Such assertions succeed when the target didn’t change by one specific delta among all the possible deltas.
When .not and .finite are used together. Such assertions succeed when the target either is not a number, or is one of Nan, positive Infinity, negative Infinity`.
The Web SQL Database standard never saw the light of day. It was first formulated, then deprecated by the W3C and was only implemented in some browsers. (It is not supported in Firefox or IE.)
Further, the use of a Web SQL Database poses security concerns, since you only need its name to access such a database.
JavaScript has the `new keyword that is used in conjunction with constructor functions to create new instances of objects. When you use the new keyword with a function, it signifies that the function is intended to be used as a constructor function to create objects.
Any function can be used as a constructor function by convention. Constructor functions are used to create new objects with the same structure or properties. They are typically named with an initial capital letter to distinguish them from regular functions.
To create a new instance of an object using the constructor function, you use the new keyword before the function call.
The new keyword should only be used with objects that define a constructor function. Attempting to use it with an object or a variable that is not a constructor will raise a TypeError`.
Numbers in JavaScript are stored in double-precision 64-bit binary format IEEE 754. Like any other number encoding occupying a finite number of bits, it is unable to represent all numbers.
The values are stored using 64 bits in the following form:
1 bit for the sign (positive or negative)
11 bits for the exponent (2n). -1022 ≤ n ≤ 1023
52 bits for the significand (or mantissa)
The actual value of the stored number will be (-1)sign * (1 + significand) * 2 exponent
Given this structure, there are limits in both magnitude and precision.
Due to the 52 bits used for the significand, any arithmetic in need of more precision than 2-52 (provided by Number.EPSILON) is subject to rounding.
In terms of magnitude, the largest number the 64 bits of the format can store is 21024 - 1 (Number.MAX_VALUE).
However, because the 52 bits of the significand, only integers between -(253 - 1) (Number.MIN_SAFE_INTEGER) and 253 - 1 (Number.MAX_SAFE_INTEGER) can be represented exactly and be properly compared.
In JavaScript, the `in operator is primarily used to check if a property exists in an object or if an index exists in an array. However, it is not suitable for use with primitive types such as numbers, strings, or booleans because they are not objects and do not have properties.
If the right operand is of primitive type, the in operator raises a TypeError`.
In JavaScript, throwing literals (primitive values like strings, numbers, booleans, etc.) as exceptions is generally discouraged. While it is syntactically valid to throw literals, it is considered a best practice to throw instances of the `Error class or its subclasses instead.
Throwing an instance of the Error class allows you to provide more meaningful information about the error.
The Error class and its subclasses provide properties like message and stack` that can be used to convey useful details about the error, such as a description of the problem, the context in which it occurred, or a stack trace for debugging.
Defining a object’s methods inside the object itself means that a new instance of the function is created for each instantiation of the object, bloating the instances.
Instead, it is more efficient to define the functions outside the object using the prototype
keyword. This yields a single instance of each function, to which all the objects of that type refer.
Object literal syntax, which initializes an object’s properties inside the object declaration is cleaner and clearer than the alternative: creating an empty object, and then giving it properties one by one.
An issue is raised when the following pattern is met:
An empty object is created.
A consecutive single-line statement adds a property to the created object.
Default parameter values allow callers to specify as many or as few arguments as they want while getting the same functionality and minimizing boilerplate, wrapper code, making a function easier to use.
All function parameters with default values should be declared after the function parameters without default values. Otherwise, it makes it impossible for callers to take advantage of defaults; they must re-specify the defaulted values or pass undefined
to be able to specify the non-default parameters.
If a class method doesn’t access properties of that class (i.e. it doesn’t use this), it should be made static
.
An async function always wraps the return value in a Promise. Using return await
is not required and comes at an extra performance cost.
However, you might wish to keep it as it preserves the function call in the stack trace in case an error is thrown asynchronously.
If the class declaration does not include a constructor, one is automatically created, so there is no need to provide an empty constructor, or one that just delegates to the parent class.
Initially, TypeScript defined “internal modules” and “external modules”:
Internal modules: The module keyword was introduced in TypeScript to define internal modules. Internal modules were used to group classes, interfaces, and functions into logical units.
External modules refer to JavaScript modules, introduced in ECMAScript 2015. In TypeScript, just as in JavaScript (after ECMAScript 2015), any file containing a top-level import or export is considered a module.
However, in order to avoid confusion with similarly named terms, module was deprecated in favor of the namespace keyword, and “external modules” became simply “modules”, as to align with ECMAScript 2015’s terminology.
Now that namespace is available, the use of module is deprecated because it does the same thing, and its use could confuse maintainers unaware of the history of the language. Therefore, the use of module
is discouraged in TypeScript code.
If the function call can be written in a normal way, then calling that function with .call() or .apply() methods is redundant and can be removed without affecting the behavior of the code.
The .call() and .apply() methods are traditionally used to explicitely set the value of this keyword when executing a function or an object method. When calling a method of an object the value of this by default will be the reference to that object. But if you call a function or a method using .call() and .apply() you can set the value of this to any object, whatever you put into the first argument.
Deprecated methods are functions or properties that are no longer recommended and are likely to be removed in future updates of the library. They are often replaced with newer methods that offer better performance, security, or usability.
Using deprecated methods in React can lead to the following issues:
Code Maintainability: As deprecated methods are removed in future versions, the code will break if not updated. This can lead to increased time and effort in code maintenance.
Performance: Newer methods often come with performance improvements. Using deprecated methods can lead to slower app performance.
Security: Deprecated methods may have known security issues that are fixed in newer methods.
In JavaScript, a mutable variable is one whose value can be changed after it has been initially set. This is in contrast to immutable variables, whose values cannot be changed once they are set.
Exporting mutable variables can lead to unpredictable behavior and bugs in your code. This is because any module that imports the variable can change its value. If multiple modules import and change the value of the same variable, it can become difficult to track what the current value of the variable is and which module changed it last.
Using Function.prototype.bind and arrows functions as attributes will negatively impact performance in React. Each time the parent is rendered, the function will be re-created and trigger a render of the component causing excessive renders and more memory use. Wrapping the function in a useCallback hook will avoid additional renders. This rule ignores Refs. This rule does not raise findings on DOM nodes since that may require wrapping the DOM in a component. Still, better performance can be achieved if this rule is respected in DOM nodes too.
React isMounted() is primarily used to avoid calling setState() after a component has unmounted, because calling setState() after a component has unmounted will emit a warning. Checking isMounted() before calling setState() does eliminate the warning, but it also defeats the purpose of the warning, which is raising awareness that the app is still holding a reference to the component after the component has been unmounted.
When using ES6 classes, using isMounted() is already prohibited.
Nested code blocks can be used to create a new scope: variables declared within that block cannot be accessed from the outside, and their lifetime end at the end of the block. However, this only happens when you use ES6 let or const keywords, a class declaration or a function declaration (in strict mode). Otherwise, the nested block is redundant and should be removed.
In JavaScript, array indexes should be numeric because arrays are implemented as objects with numeric keys. When an array is created, it is actually an object with properties that are numeric keys. These keys are used to access and assign values stored in the array.
If an array index is not numeric, it will be converted to a string and used as a property name. This can lead to unexpected behavior, as properties are not guaranteed to be ordered in the same way as numeric indexes. For example, if an array has both numeric and non-numeric keys, the non-numeric keys may appear in a different order than the numeric keys.
JavaScript and TypeScript classes may define a constructor method that is executed when a new instance is created. TypeScript allows interfaces that describe a static class object to define a new() method. Using these terms to name methods in other contexts can lead to confusion and make the code unclear and harder to understand.
This rule reports when:
A class defines a method named new. The new keyword is used to create new instances of the class. If a method with the same name is defined, it can be unclear whether the method is intended to create new instances or perform some other action.
An interface defines a method named constructor. The constructor method is used to define the constructor function for a class that implements the interface. If a method with the same name is defined in the interface, it can be unclear whether the method is intended to define the constructor function or perform some other action.
The assignment of default parameter values is generally intended to help the caller. But when a default assignment causes side effects, the caller may not be aware of the extra changes or may not fully understand their implications. I.e. default assignments with side effects may end up hurting the caller, and for that reason, they should be avoided.
The delete operator is used to remove a property from an object. It only affects its own properties. There are two valid ways to remove a property:
Using the dot notation: delete object.property
Using the bracket notation: delete object[property]
delete will throw a TypeError in strict mode if the property is a non-configurable property.
delete identifier may work if identifier is a configurable property of the global object. For identifier to be configurable, it should have been declared directly as a globalThis property (globalThis.identifier = 1). This form is not common practice and should be avoided. Use delete globalThis.identifier instead if needed.
Aside from that case, deleting variables, including function parameters, never works:
Variables declared with var cannot be deleted from the global or a function’s scope, because while they may be attached to the global object, they are non-configurable. In CommonJS and ECMAScript modules, top-level variable declarations are scoped to the module and not attached to the global object.
Variables declared with let or const are not attached to any object.
When using the Backbone.js framework with model defaults that contain arrays or objects, defaults should be defined as a function rather than an object. This is because objects and arrays are passed by reference in JavaScript. So a defaults
object that contains arrays or objects is going to set the default value of every instance to point to the same shared object or array.
Use a function instead and a fresh copy of the object or array will be peeled off for each instance.
Using an empty class serves no purpose and can hinder the readability of the code.
An iframe, or inline frame, is an HTML document embedded inside another HTML document on a website. The iframe HTML element is often used to insert content from another source, such as an advertisement, into a web page.
In the context of web accessibility, <iframe>‘s should have a title
attribute. This is because screen readers for the visually impaired use this title to help users understand the content of the iframe.
Without a title, it can be difficult for these users to understand the context or purpose of the iframe’s content.
When a method return type is the declaring class name in a hierarchy of classes, it is impossible to chain methods defined in the superclass with methods defined in subclasses.
TypeScript provides two ways to tell the compiler that a literal value should be typed as a literal type like 42 rather than the primitive one number:
as const tells TypeScript to infer the literal type automatically
as T where T denotes a literal type to instruct TypeScript to infer the literal type explicitly
In practice, as const is preferred because the type checker doesn’t need re-typing the literal value.
Therefore, the rule flags occurrences of explicit literal types that can be replaced with an as const assertion.
In JavaScript, there are two types of comparison operators: strict and non-strict.
Strict operators: These operators compare both value and type. They are represented as === (strict equality) and !== (strict inequality). For example, `5 =
React does not always propagate component state changes to the underlying DOM elements immediately. If you modify the state during an already ongoing update cycle, the change may be delayed until the next update. React tries to keep this.state in sync with what is currently in the DOM, so you should never directly modify this.state yourself. Instead, use the asynchronous setState method instead, which allows React to properly manage the current state, trigger the new update cycle, or batch the updates together if necessary.
Note that setState() is a request to change the state, not an immediate update. For example, if multiple components are changing the state in response to a user event, React will wait until the event handler has finished executing and then render all the changes in a single update. In other cases, the updates may be executed one at a time, so you should never make assumptions about how the component state will change in response to your request.
If your next state is a function of the current state, you should pass an updater function to the setState() that will give you access to the correct component state at the time of the execution.
The only place where you should directly modify the state is during the component initialization in a constructor function.
Using the new operator with Symbol and BigInt will throw a TypeError because they are not intended to be used as constructors. Symbol and BigInt are primitive types in JavaScript and should be used as such.
This is different from the other primitive types, such as string, number or boolean, where it was possible to call global String or Number as functions that return primitive types, but also use them as constructors with the new operator to create wrapper objects. This confusing double behavior is not implemented for Symbol and BigInt types that were introduced later in the language.
This behavior would be especially problematic for symbols that have reference identity and already behave like objects in some way. For example, they are garbage collectable and therefore can be used as keys in WeakMap and WeakSet objects.
While named function expressions might be useful for debugging purposes, some browsers do not support them correctly (for example Internet Explorer 8).
Screen readers require a specified language to function correctly. Without it, they default to the user’s set language, causing issues for multilingual users. Specifying a valid language ensures correct pronunciation and a less confusing experience.
ARIA properties, also known as “aria-* properties”, are special attributes used in HTML to enhance the accessibility of web elements. They provide additional semantics to help assistive technologies, like screen readers, interpret the element.
Roles, on the other hand, define what an element is or does in the context of a web page. Some elements have explicit roles, which are directly defined by the developer. For example, a div element might be given a role of “button”. Other elements have implicit roles, which are inferred based on the type of the element. For example, an anchor tag <a href=”#” /> has an implicit role of “link”.
This rule ensures that the ARIA properties used on an element are ones that are supported by the role of that element. For instance, the ARIA property aria-required is not supported by the role link. Therefore, using aria-required on an anchor tag would violate this rule.
In JavaScript, every value can be coerced into a boolean value: either `true or false. Values that are coerced into true are said to be truthy, and those coerced into false are said to be falsy.
Explicit conversion to a boolean can be done with double negation (!!) or a Boolean` call. Depending on the context, this may be redundant as JavaScript uses implicit type coercion and automatically converts values to booleans when used with logical operators, conditional statements, or any boolean context.
The ECMAScript specification allows for creating block-level lexical declarations (let, const, function, and class) in any block statement or expression. However, when these declarations are made inside the case or default clause of a switch statement, they are not confined to the block of that case or default clause. Instead, they apply to the whole switch block but only get initialized when the cases are reached, which can lead to unexpected behavior.
Extra semicolons (`;) are usually introduced by mistake, for example because:
It was meant to be replaced by an actual statement, but this was forgotten.
There was a typo which lead the semicolon to be doubled, i.e. ;;`.
There was a misunderstanding about where semicolons are required or useful.
The fact that JavaScript is not a strongly typed language allows developers a lot of freedom, but that freedom can be dangerous if you go too far with it.
Specifically, it is syntactically acceptable to invoke any expression as though its value were a function. But a TypeError
may be raised if you do.
In JavaScript, a promise is an object representing the eventual completion or failure of an asynchronous operation. It is a way to handle asynchronous operations more elegantly and avoid the “callback hell”.
A promise can be in one of three states:
Pending: The initial state of a promise. It represents that the asynchronous operation is still ongoing and has not yet been fulfilled or rejected.
Fulfilled: The state of a promise when the asynchronous operation has been successfully completed. It represents that the promised value is available and can be consumed.
Rejected: The state of a promise when the asynchronous operation encounters an error or fails to complete. It represents that an error has occurred and the promised value is not available.
The basic syntax for creating a promise in JavaScript is as follows:
When writing code, it is quite common to test patterns against string ends. For a long time, JavaScript did not provide proper support for this use case. As a result, developers have been relying on various programming subtleties to check the start or end of a string. Examples are getting the index of a substring, slicing the beginning of a string, extracting a substring from the head, matching a regular expression beginning or ending with a pattern, and so on.
While these approaches are all technically valid, they look more like hacking than anything else, blur the developer’s intent, but more importantly affect code readability.
Since ES2015, JavaScript provides String#startsWith and String#endsWith, which are the preferred ways to test patterns against string ends.
When a function in JavaScript does not have a return statement or if it has a return statement without a value, it implicitly returns undefined. This means that a function without a return statement or with an empty return statement is, in a way, a “void” function, as it doesn’t return any specific value.
Therefore, attempting to use the return value of a void function in JavaScript is meaningless, and it can lead to unexpected behavior or errors.
React Legacy APIs provide a way to define the default values for props and check the prop types at runtime. This rule verifies if a defaultProps definition does have a corresponding propTypes definition. If it is missing, this could be the result of errors in refactoring or a spelling mistake.
It is also an error if a defaultProp has propType that is marked as isRequired.
Logical AND (&&) operator is sometimes used to conditionally render in React (aka short-circuit evaluation). For example, myCondition && <MyElement /> will return <MyElement /> if myCondition is true and false otherwise.
React considers false as a ‘hole’ in the JSX tree, just like null or undefined, and doesn’t render anything in its place. But if the condition has a falsy non-boolean value (e.g. 0), that value will leak into the rendered result.
This rule will report when the condition has type number or bigint.
In the case of React Native, the type string will also raise an error, as your render method will crash if you render 0, ”, or NaN.
ARIA (Accessible Rich Internet Applications) roles are used to make web content and web applications more accessible to people with disabilities. However, you should not use an ARIA role on a generic element (like span or div) if there is a semantic HTML tag with similar functionality, just use that tag instead.
For example, instead of using a div element with a button role (<div role=“button”>Click me</div>), you should just use a button element (<button>Click me</button>).
Semantic HTML tags are generally preferred over ARIA roles for accessibility due to their built-in functionality, universal support by browsers and assistive technologies, simplicity, and maintainability. They come with inherent behaviors and keyboard interactions, reducing the need for additional JavaScript. Semantic HTML also enhances SEO by helping search engines better understand the content and structure of web pages. While ARIA roles are useful, they should be considered a last resort when no suitable HTML element can provide the required behavior or semantics.
React Refs provide a way to access DOM nodes or React elements created in the render method.
Older React versions allowed the ref attribute to be a string, like “textInput”, later accessible as this.refs.textInput. This is considered legacy code due to multiple reasons:
String refs make React slower as they force React to keep track of what component is currently executing.
String refs are not composable: if a library puts a ref on the passed child, the user can’t put another ref on it.
The owner of a string ref is determined by the currently executing component.
The parseInt
function has two versions, one that takes a base value as a second argument, and one that does not. Unfortunately using the single-arg version can result in unexpected results on older browsers.
Offering the same experience with the mouse and the keyboard allow users to pick their preferred devices.
Additionally, users of assistive technology will also be able to browse the site even if they cannot use the mouse.
This rules detects the following issues:
when onClick is not accompanied by at least one of the following: onKeyUp, onKeyDown, onKeyPress.
when onmouseover/onmouseout are not paired by onfocus/onblur.
Consistent naming between arguments and parameters reduces the chances of making mistakes, such as passing the wrong value to a parameter or omitting an argument in a function call. When the names of arguments in a function call match the names of the function parameters, it contributes to clearer, more readable code.
However, when the names match but are passed in a different order than their declaration in the function signature, it may indicate a mistake in the parameter order, likely leading to unexpected results.
Leaving unused props in a React component can make the code harder to understand and maintain. Other developers may wonder why certain props are passed to a component if they are not used. Unused props can also increase the size of the component’s memory footprint and impact performance. This is especially true if the unused props are large objects or arrays. Furthermore, if a prop is unused, it may indicate that the developer did not complete the implementation as he intended initially or made a mistake while writing the component.
To avoid these issues, you should remove any unused props from React components. This helps keep the codebase clean, improves performance, and enhances code readability.
Template literals, also known as template strings, allow for string interpolation and multiline strings in JavaScript. They provide a more convenient and flexible way to work with strings compared to traditional string concatenation or manipulation.
Template literals are delimited with the backtick ()
character. They are a convenient way to include variables or expressions within a string using placeholders ${expression}` in the string and evaluate them dynamically.
However, nesting template literals can make the code less readable. With each nested template literal, the code becomes more complex and harder to understand. It can be challenging to keep track of the opening and closing backticks and properly escape characters if needed.
Unnecessary imports refer to importing modules, libraries, or dependencies that are not used or referenced anywhere in the code. These imports do not contribute to the functionality of the application and only add extra weight to the JavaScript bundle, leading to potential performance and maintainability issues.
The `for…in statement allows you to loop through the names of all of the properties of an object. The list of properties includes all those properties that were inherited through the prototype chain. This has the side effect of serving up functions when the interest is in data properties. Programs that don’t take this into account can fail.
Therefore, the body of every for…in statement should be wrapped in an if` statement that filters which properties are acted upon. It can select for a particular type or range of values, or it can exclude functions, or it can exclude properties from the prototype.
Using element type in class selectors is slower than using only the class selector.
Instead of creating an array and then setting its items one by one, creation an initialization can - and should - happen all in one step. Doing so results in clearer code and eliminates the possibility that an item might be accidentally overwritten or left uninitialized.
The `if…else statement is used to make decisions based on the truthiness of a boolean expression, and the if block executes when the expression is truthy, while the else block executes when the expression is falsy.
Wrapping a boolean expression in an if…else statement and returning true or false` in the respective blocks is redundant and unnecessary. It can also make the code harder to maintain, as it adds unnecessary lines of code that need to be read and understood.
Array literals should always be preferred to Array constructors.
Array constructors are error-prone due to the way their arguments are interpreted. If more than one argument is used, the array length will be equal to the number of arguments. However, using a single argument will have one of three consequences:
If the argument is a number and it is a natural number the length will be equal to the value of the argument.
let arr = new Array(3); // [empty × 3]
If the argument is a number, but not a natural number an exception will be thrown.
let arr = new Array(3.14); // RangeError: Invalid array length
Otherwise the array will have one element with the argument as its value.
let arr = new Array(“3”); // [“3”]
Note that even if you set the length of an array, it will be empty. That is, it will have the number of elements you declared, but they won’t contain anything, so no callbacks will be applied to the array elements.
For these reasons, if someone changes the code to pass 1 argument instead of 2 arguments, the array might not have the expected length. To avoid these kinds of weird cases, always use the more readable array literal initialization format.
The optional chaining operator ?. allows to access a deeply nested property, returning undefined if the property or any intermediate object is undefined.
This usually means that the expression is expected to evaluate as undefined in some cases. Therefore, using the optional chaining operator in a context where returning undefined throws an error can lead to runtime exceptions.
undefined is the value you get for variables and properties which have not yet been created. Use the same value to reset an existing variable and you lose the ability to distinguish between a variable that exists but has no value and a variable that does not yet exist. Instead, null
should be used, allowing you to tell the difference between a property that has been reset and one that was never created.
Shared coding conventions allow teams to collaborate effectively. This rule checks that classes extending React.PureComponent or React.Component
are named with UpperCamelCase (aka PascalCase).
To optimize the rendering of React list components, a unique identifier (UID) is required for each list item. This UID lets React identify the item throughout its lifetime. To provide it, use the key attribute of the list item. When the key attribute is missing, React will default to using the item’s index inside the list component. If the element ordering changes, it will cause keys to not match up between renders, recreating the DOM. It can negatively impact performance and may cause issues with the component state.
A loop is a control structure that allows a block of code to be executed repeatedly until a certain condition is met. The basic idea behind a loop is to automate repetitive tasks, such as iterating over a collection of data or performing a calculation multiple times with different inputs.
An infinite loop is a loop that runs indefinitely without ever terminating. In other words, the loop condition is always true, and the loop never exits. This can happen when the loop condition is not defined or when the loop condition is never met.
Infinite loops can cause a program to hang or crash, as the program will continue to execute the loop indefinitely.
This rule will raise an issue on for, while and do…while
loops where no clear exit condition has been found.
There are some known limitations for this rule:
False positives: when an exception is raised by a function invoked within the loop.
False negatives: when a loop condition is based on an element of an array or object.
React fragments are a feature in React that allows you to group multiple elements together without adding an extra DOM element. They are a way to return multiple elements from a component’s render method without requiring a wrapping parent element.
However, a fragment is redundant if it contains only one child, or if it is the child of an HTML element.
The JavaScript wrapper objects Number, String, and Boolean provide a way to work with their respective primitive types (number, string and boolean) as objects.
Using wrapper can lead to unexpected behavior due to the differences in how they are compared and used in operations compared to primitive types. It can also lead to unnecessary memory allocation and slower code execution.
Captions in HTML media elements are text versions of the audio content, synchronized with the video. They are essential for individuals who are deaf or hard of hearing, as they provide a text alternative for the audio information. They can also be beneficial for individuals who are not native speakers of the language of the video, or for situations where the audio cannot be heard.
In the context of accessibility, providing captions for media elements is a requirement under the Web Content Accessibility Guidelines (WCAG). Without captions, you are excluding a portion of your audience who rely on them to understand the content of your media.
Shared coding conventions allow teams to collaborate effectively. This rule raises an issue when the use of spaces within a template does not conform to the configured style.
When a non-existent variable is referenced a `ReferenceError is raised.
Due to the dynamic nature of JavaScript this can happen in a number of scenarios:
When typo was made in a symbol’s name.
When using variable declared with let or const before declaration (unlike var-declarations, they are not hoisted to the top of the scope).
Due to confusion with scopes of let- and const-declarations (they have block scope, unlike var-declarations, having function scope).
When accessing a property in the wrong scope (e.g. forgetting to specify this.).
This rule does not raise issues on global variables which are defined with sonar.javascript.globals and sonar.javascript.environments` properties.
In JavaScript, null and undefined are primitive values that do not have properties or methods. When accessing a property on a null or undefined value, JavaScript tries to access the property of an object that does not exist, which results in a TypeError.
This can cause the program to crash or behave unexpectedly, which can be difficult to debug.
A type guard is a TypeScript feature that allows you to narrow the type of a variable within a conditional block of code. It is a way to tell the TypeScript compiler that an expression is of a certain type, based on some condition that you check at runtime.
To optimize the rendering of React list components, a unique identifier (UID) is required for each list item. This UID lets React identify the item throughout its lifetime. Avoid array indexes since the order of the items may change, which will cause keys to not match up between renders, recreating the DOM. It can negatively impact performance and may cause issues with the component state.
By default, JavaScript allows you to modify native object prototypes, such as Array, String, Object, and so on. This means you can add new properties or methods to native objects or override existing ones. While this flexibility can be useful in some instances, it can lead to unexpected behavior, bugs, and compatibility issues.
The rule forbids extending or modifying native JavaScript objects or prototypes, as prototypes of builtin objects should not be modified altogether.
Reading a non-existent property on an object always returns `undefined. Doing so is usually an error; either in the name of the property or the type of the variable being accessed.
If an attempt is made to access properties of a primitive, the primitive is automatically encased in a primitive-wrapper object for the operation. But being “promoted” to an object doesn’t mean that the primitive will actually have properties to access. The wrapper object still won’t have the non-existent property and undefined will be returned instead.
This rule raises an issue when an attempt is made to access properties of a primitive. Thus this rule should only be activated when you don’t use monkey patching for standard objects, like Number, Boolean and String`.
An expression that always produces the same result, regardless of the inputs, is unnecessary and likely indicates a programmer’s error. This can come from
confusing operator precedence
expecting strict equality between different types
expecting objects to be compared by value
expecting empty objects to be false or null
mistyping >= for ⇒
This can also happen when you put an assignment in a logical sub-expression. While not strictly a bug, this practice is confusing and should be avoided.
String.match() behaves the same way as RegExp.exec() when the regular expression does not include the global flag g. While they work the same, RegExp.exec() can be slightly faster than String.match(). Therefore, it should be preferred for better performance.
The rule reports an issue on a call to String.match() whenever it can be replaced with semantically equivalent RegExp.exec().
The use of the comma operator and logical OR (||) operator within switch cases is not recommended. The switch statement is designed to evaluate a single expression and compare it against multiple values. When you use the comma operator or logical OR operator within a case, you’re essentially trying to match multiple values or conditions simultaneously: only the rightmost value will ever be considered with the comma operator, and the first truthy operand will be handled with the logical OR operator.
This behavior is not well-defined and can lead to unexpected results.
Promises need to be resolved or awaited to return the expected value, otherwise, they return the promise object.
Unresolved promises:
Forgetting to await a promise is a frequent mistake. There are places where the use of a promise object is confusing or unclear because the developer forgot to resolve it.
This rule forbids returning promises where another type is expected such as in:
conditionals
void returns
spread operators
In JavaScript, many array methods take a callback function as an argument. These methods are designed to transform or filter arrays based on the logic provided in the callback function. The callback function is called sequentially, and the return value of the callback function is used to determine the return value of the Array method.
If the callback function does not return a value, the array method may not work as expected and is most likely a mistake.
This rule applies to the following methods of an array:
If there is no return, the callback will implicitly return undefined`, which may cause unexpected behavior or errors in the code.
Unlike strongly typed languages, JavaScript does not enforce a return type on a function. This means that different paths through a function can return different types of values, which can be very confusing to the user and significantly harder to maintain.
In particular a function, in JavaScript, will return `undefined in any of the following cases:
It exits without a return statement.
It executes a return` with no value.
This rule verifies that return values are either always or never specified for each path through a function.
An assertion is a statement within the unit test that checks whether a particular condition is true or false. It defines the expected behavior of the unit being tested. Assertions are used to express the test’s expected outcome, and they are the criteria against which the actual output of the unit is evaluated.
When the unit test is executed, the assertions are evaluated. If all the assertions in the test pass, it means the unit is functioning correctly for that specific set of inputs. If any of the assertions fail, it indicates that there is a problem with the unit’s implementation, and the test case helps identify the issue.
Without assertions, a unit test doesn’t actually verify anything, making it ineffective in catching potential bugs or regressions. It will always pass, regardless of the implementation of the unit. This can lead to a false sense of security, as you may believe that your code is working correctly when it might not be.
This rule raises an issue when the assertion library chai,sinon or vitest
is imported but no assertion is used in a test.
Using regular expression literals is recommended over using the RegExp constructor calls if the pattern is a literal. Regular expression literals are shorter, more readable, and do not need to be escaped like string literals. They can also be more performant because regular expression literals are compiled only once when the script is loaded.
JavaScript allows returning a value from a class constructor. This obscure feature is rarely used and is more likely a bug than the developer’s intention.
JavaScript has a prototypal inheritance model. Each object has an internal property that points to another object, called a prototype. That prototype object has a prototype of its own, and the whole sequence is called a prototype chain. When accessing a property or a method of an object, if it is not found at the top level, the search continues through the object’s prototype and then further down the prototype chain. This feature allows for very powerful dynamic inheritance patterns but can also lead to confusion when compared to the classic inheritance.
To simplify the access to the prototype of an object some browsers introduced the proto property, which was later deprecated and removed from the language. The current ECMAScript standard includes Object.getPrototypeOf and Object.setPrototypeOf static methods that should be used instead of the proto
property.
A collection is a data structure that holds multiple values, such as an array or a map. If a collection is declared and populated, but its values are never read anywhere in the code, it can be considered unused code. This can be due to some refactoring, copy-pasting, or typing errors.
Unused collections can waste memory usage and slow down the application’s performance. Additionally, they can make the code harder to read and understand, especially for other developers working on the same codebase.
Whenever the value property of React context changes, React will rerender the context and all its child nodes and consumers. In JavaScript, things like object literals or function expressions will create a new identity every time they are evaluated. Such constructions should not be directly used as context value because React will always consider they have changed. This can significantly impact performance.
The finally block is a part of a try…catch…finally statement, which allows you to handle errors and perform cleanup operations regardless of whether an exception is thrown or not. The finally block is executed regardless of whether an exception occurs or not, and it is placed after the try and catch blocks.
Having a jump statement, such as return, break, continue, or throw, inside a finally block can lead to unexpected and undesirable behavior, making your code difficult to understand and maintain. While it’s not inherently forbidden to use jump statements in finally blocks, it is generally discouraged for the following reasons:
The primary purpose of the finally block is to ensure cleanup operations and code that must run regardless of the outcome, such as releasing resources or closing connections. If you use a return statement inside the finally block, it will override any previous return statements in the try or catch blocks. This can lead to unexpected values being returned from a function.
Jump statements like break, continue, or even another throw inside the finally block can alter the normal control flow of the program. This can make it difficult to reason about the behavior of the code and may introduce subtle bugs that are hard to detect.
If a return or throw statement inside the finally block causes a new exception or alters the return value, it can hide or suppress the original exception or return value from the try or catch blocks. This can make it challenging to identify the actual cause of an error.
Code that uses jump statements in finally blocks can be hard to read and understand, especially for other developers who might not be familiar with the unusual control flow. Such code can lead to maintenance issues and make it harder to debug and maintain the application in the long run.
This rule reports on all usages of jump statements from a finally block. Even if it’s guaranteed that no unhandled exception can happen in try or catch blocks, it’s not recommended to use any jump statements inside the finally
block to have the logic there limited to the “cleanup”.
TypeScript allows declaring the type of a function in two different ways:
Function type: () ⇒ number
Object type with a call signature: { (): number }
The function type syntax is generally preferred for being more concise.
Web browsers, CDNs or similar proxy-servers can cache HTTP responses (especially large content such as images, scripts etc) to improve web browsing performance and to not overload the application serving the resources. However this may lead to privacy issues if a private web page containing personal user information is cached and served to another user. A different type of attacks allowed when caching resources at the web-browser level is cross-site leak attacks/side-channel attacks, here the attacker infers information about an user (for instance, web page he is visiting) by observing timing responses or other relevant data when requesting private resources that may be cached.
Example of a side channel attack:
The attacker wants to known if a user is involved in a confidential agreement between two companies A and B.
If it is the case, the user can access to the resource contract-between-A-and-B.png after being authenticated on a website.
The attacker tricks the user to visit a malicious website containing the below code in order to determine the desired information:
`<img id=“leakyimage” src=""> <script language=“javascript”> leakyimage.src = “https://targetexample.com/private/contract-between-A-and-B.png”;
leakyimage.onload = function SideChannelObservations() { // compare timing between a cached image and not cached image // or success of load // in order to determine if the image is cached and so if the user has right to access to this image } </script>`
It is needlessly complex to invert the result of a boolean comparison. The opposite comparison should be made instead.
Regular expressions have their own syntax that is understood by regular expression engines. Those engines will throw an exception at runtime if they are given a regular expression that does not conform to that syntax.
To avoid syntax errors, special characters should be escaped with backslashes when they are intended to be matched literally and references to capturing groups should use the correctly spelled name or number of the group.
Operating systems have global directories where any user has write access. Those folders are mostly used as temporary storage areas like `/tmp in Linux based systems. An application manipulating files from these folders is exposed to race conditions on filenames: a malicious user can try to create a file with a predictable name before the application does. A successful attack can result in other files being accessed, modified, corrupted or deleted. This risk is even higher if the application runs with elevated permissions.
In the past, it has led to the following vulnerabilities:
This rule raises an issue whenever it detects a hard-coded path to a publicly writable directory like /tmp (see examples bellow). It also detects access to environment variables that point to publicly writable directories, e.g., TMP and TMPDIR.
/tmp
/var/tmp
/usr/tmp
/dev/shm
/dev/mqueue
/run/lock
/var/run/lock
/Library/Caches
/Users/Shared
/private/tmp
/private/var/tmp
\Windows\Temp
\Temp
\TMP`
Trailing whitespaces bring no information, they may generate noise when comparing different versions of the same file, and they can create bugs when they appear after a \ marking a line continuation. They should be systematically removed.
An automated code formatter allows to completely avoid this family of issues and should be used wherever possible.
Putting multiple statements on a single line lowers the code readability and makes debugging the code more complex.
Unresolved directive in <stdin> - include::{noncompliant}[]
Write one statement per line to improve readability.
Unresolved directive in <stdin> - include::{compliant}[]
Resource-based policies granting access to all users can lead to information leakage.
Most of the regular expression engines use backtracking to try all possible execution paths of the regular expression when evaluating an input, in some cases it can cause performance issues, called catastrophic backtracking situations. In the worst case, the complexity of the regular expression is exponential in the size of the input, this means that a small carefully-crafted input (like 20 chars) can trigger catastrophic backtracking
and cause a denial of service of the application. Super-linear regex complexity can lead to the same impact too with, in this case, a large carefully-crafted input (thousands chars).
This rule determines the runtime complexity of a regular expression and informs you of the complexity if it is not linear.
Note that, due to improvements to the matching algorithm, some cases of exponential runtime complexity have become impossible when run using JDK 9 or later. In such cases, an issue will only be reported if the project’s target Java version is 8 or earlier.
HTTP header referer contains a URL set by web browsers and used by applications to track from where the user came from, it’s for instance a relevant value for web analytic services, but it can cause serious privacy and security problems if the URL contains confidential information. Note that Firefox for instance, to prevent data leaks, removes path information in the Referer header while browsing privately.
Suppose an e-commerce website asks the user his credit card number to purchase a product:
<html> <body> <form action=“/valid_order” method=“GET”> Type your credit card number to purchase products: <input type=text id=“cc” value=“1111-2222-3333-4444”> <input type=submit> </form> </body>
When submitting the above HTML form, a HTTP GET request will be performed, the URL requested will be https://example.com/valid_order?cc=1111-2222-3333-4444 with credit card number inside and it’s obviously not secure for these reasons:
URLs are stored in the history of browsers.
URLs could be accidentally shared when doing copy/paste actions.
URLs can be stolen if a malicious person looks at the computer screen of an user.
In addition to these threats, when further requests will be performed from the “valid_order” page with a simple legitimate embedded script like that:
<script src=“https://webanalyticservices_example.com/track”>
The referer header which contains confidential information will be send to a third party web analytic service and cause privacy issue:
GET /track HTTP/2.0 Host: webanalyticservices_example.com Referer: https://example.com/valid_order?cc=1111-2222-3333-4444
A cross-site request forgery (CSRF) attack occurs when a trusted user of a web application can be forced, by an attacker, to perform sensitive actions that he didn’t intend, such as updating his profile or sending a message, more generally anything that can change the state of the application.
The attacker can trick the user/victim to click on a link, corresponding to the privileged action, or to visit a malicious web site that embeds a hidden web request and as web browsers automatically include cookies, the actions can be authenticated and sensitive.
Alternation is used to match a single regular expression out of several possible regular expressions. If one of the alternatives is empty it would match any input, which is most probably a mistake.
By default, S3 buckets can be accessed through HTTP and HTTPs protocols.
As HTTP is a clear-text protocol, it lacks the encryption of transported data, as well as the capability to build an authenticated connection. It means that a malicious actor who is able to intercept traffic from the network can read, modify or corrupt the transported content.
Hidden files are created automatically by many tools to save user-preferences, well-known examples are .profile, .bashrc, .bash_history or .git. To simplify the view these files are not displayed by default using operating system commands like ls
.
Outside of the user environment, hidden files are sensitive because they are used to store privacy-related information or even hard-coded secrets.
When executing an OS command and unless you specify the full path to the executable, then the locations in your application’s PATH environment variable will be searched for the executable. That search could leave an opening for an attacker if one of the elements in PATH
is a directory under his control.
Having a permissive Cross-Origin Resource Sharing policy is security-sensitive. It has led in the past to the following vulnerabilities:
Same origin policy in browsers prevents, by default and for security-reasons, a javascript frontend to perform a cross-origin HTTP request to a resource that has a different origin (domain, protocol, or port) from its own. The requested target can append additional HTTP headers in response, called CORS, that act like directives for the browser and change the access control policy / relax the same origin policy.
The use of break and continue statements increases the complexity of the control flow and makes it harder to understand the program logic. In order to keep a good program structure, they should not be applied more than once per loop.
This rule reports an issue when there is more than one break or continue statement in a loop. The code should be refactored to increase readability if there is more than one.
Character classes in regular expressions are a convenient way to match one of several possible characters by listing the allowed characters or ranges of characters. If a character class contains only one character, the effect is the same as just writing the character without a character class.
Thus, having only one character in a character class is usually a simple oversight that remained after removing other characters of the class.
continue is an unstructured control flow statement. It makes code less testable, less readable and less maintainable. Structured control flow statements such as if
should be used instead.
Enabling public network access to cloud resources can affect an organization’s ability to protect its data or internal operations from data theft or disruption.
Depending on the component, inbound access from the Internet can be enabled via:
a boolean value that explicitly allows access to the public network.
the assignment of a public IP address.
database firewall rules that allow public IP ranges.
Deciding to allow public access may happen for various reasons such as for quick maintenance, time saving, or by accident.
This decision increases the likelihood of attacks on the organization, such as:
data breaches.
intrusions into the infrastructure to permanently steal from it.
and various malicious traffic, such as DDoS attacks.
Declaring a variable only to immediately return or throw it is considered a bad practice because it adds unnecessary complexity to the code. This practice can make the code harder to read and understand, as it introduces an extra step that doesn’t add any value. Instead of declaring a variable and then immediately returning or throwing it, it is generally better to return or throw the value directly. This makes the code cleaner, simpler, and easier to understand.
Clickjacking attacks occur when an attacker try to trick an user to click on certain buttons/links of a legit website. This attack can take place with malicious HTML frames well hidden in an attacker website.
For instance, suppose a safe and authentic page of a social network (https://socialnetworkexample.com/makemyprofilpublic) which allows an user to change the visibility of his profile by clicking on a button. This is a critical feature with high privacy concerns. Users are generally well informed on the social network of the consequences of this action. An attacker can trick users, without their consent, to do this action with the below embedded code added on a malicious website:
<html> <b>Click on the button below to win 5000$</b> <br> <iframe src=“https://socialnetworkexample.com/makemyprofilpublic” width=“200” height=“200”></iframe> </html>
Playing with the size of the iframe it’s sometimes possible to display only the critical parts of a page, in this case the button of the makemyprofilpublic page.
A loop with at most one iteration is equivalent to the use of an `if statement to conditionally execute one piece of code. No developer expects to find such a use of a loop statement. If the initial intention of the author was really to conditionally execute one piece of code, an if statement should be used instead.
At worst that was not the initial intention of the author and so the body of the loop should be fixed to use the nested return, break or throw` statements in a more appropriate way.
A newly opened window having access back to the originating window could allow basic phishing attacks (the window.opener object is not null and thus window.opener.location
can be set to a malicious website by the opened page).
For instance, an attacker can put a link (say: “http://example.com/mylink”) on a popular website that changes, when opened, the original page to “http://example.com/fake_login”. On “http://example.com/fake_login” there is a fake login page which could trick real users to enter their credentials.
Using unencrypted RDS DB resources exposes data to unauthorized access. This includes database data, logs, automatic backups, read replicas, snapshots, and cluster metadata.
This situation can occur in a variety of scenarios, such as:
A malicious insider working at the cloud provider gains physical access to the storage device.
Unknown attackers penetrate the cloud provider’s logical infrastructure and systems.
After a successful intrusion, the underlying applications are exposed to:
theft of intellectual property and/or personal data
extortion
denial of services and security bypasses via data corruption or deletion
AWS-managed encryption at rest reduces this risk with a simple switch.
Development tools and frameworks usually have options to make debugging easier for developers. Although these features are useful during development, they should never be enabled for applications deployed in production. Debug instructions or error messages can leak detailed information about the system, like the application’s path or file names.
In software development, logs serve as a record of events within an application, providing crucial insights for debugging. When logging, it is essential to ensure that the logs are:
easily accessible
uniformly formatted for readability
properly recorded
securely logged when dealing with sensitive data
Those requirements are not met if a program directly writes to the standard outputs (e.g., {language_std_outputs}). That is why defining and using a dedicated logger is highly recommended.
Magic numbers make the code more complex to understand as it requires the reader to have knowledge about the global context to understand the number itself. Their usage may seem obvious when writing the code, but it may not be the case for another developer or later once the context faded away. -1, 0, and 1 are not considered magic numbers.
A boolean literal can be represented in two different ways: {true} or {false}. They can be combined with logical operators ({ops}) to produce logical expressions that represent truth values. However, comparing a boolean literal to a variable or expression that evaluates to a boolean value is unnecessary and can make the code harder to read and understand. The more complex a boolean expression is, the harder it will be for developers to understand its meaning and expected behavior, and it will favour the introduction of new bugs.
Amazon SageMaker is a managed machine learning service in a hosted production-ready environment. To train machine learning models, SageMaker instances can process potentially sensitive data, such as personal information that should not be stored unencrypted. In the event that adversaries physically access the storage media, they cannot decrypt encrypted data.
Integer literals starting with a zero are octal rather than decimal values. While using octal values is fully supported, most developers do not have experience with them. They may not recognize octal values as such, mistaking them instead for decimal values.
Using pseudorandom number generators (PRNGs) is security-sensitive. For example, it has led in the past to the following vulnerabilities:
When software generates predictable values in a context requiring unpredictability, it may be possible for an attacker to guess the next value that will be generated, and use this guess to impersonate another user or access sensitive information.
When exceptions occur, it is usually a bad idea to simply ignore them. Instead, it is better to handle them properly, or at least to log them.
Successful Zip Bomb attacks occur when an application expands untrusted archive files without controlling the size of the expanded data, which can lead to denial of service. A Zip bomb is usually a malicious archive file of a few kilobytes of compressed data but turned into gigabytes of uncompressed data. To achieve this extreme compression ratio, attackers will compress irrelevant data (eg: a long string of repeated bytes).
A policy that grants all permissions may indicate an improper access control, which violates the principle of least privilege. Suppose an identity is granted full permissions to a resource even though it only requires read permission to work as expected. In this case, an unintentional overwriting of resources may occur and therefore result in loss of information.
Nested code - blocks of code inside blocks of code - is eventually necessary, but increases complexity. This is why keeping the code as flat as possible, by avoiding unnecessary nesting, is considered a good practice.
Merging if statements when possible will decrease the nesting of the code and improve its readability.
An empty {operationName} is generally considered bad practice and can lead to confusion, readability, and maintenance issues. Empty {operationName}s bring no functionality and are misleading to others as they might think the {operationName} implementation fulfills a specific and identified requirement.
There are several reasons for a {operationName} not to have a body:
It is an unintentional omission, and should be fixed to prevent an unexpected behavior in production.
It is not yet, or never will be, supported. In this case an exception should be thrown.
The method is an intentionally-blank override. In this case a nested comment should explain the reason for the blank override.
S3 buckets can be in three states related to versioning:
unversioned (default one)
enabled
suspended
When the S3 bucket is unversioned or has versioning suspended it means that a new version of an object overwrites an existing one in the S3 bucket.
It can lead to unintentional or intentional information loss.
Clear-text protocols such as `ftp, telnet, or http lack encryption of transported data, as well as the capability to build an authenticated connection. It means that an attacker able to sniff traffic from the network can read, modify, or corrupt the transported content. These protocols are not secure as they expose applications to an extensive range of risks:
sensitive data exposure
traffic redirected to a malicious endpoint
malware-infected software update or installer
execution of client-side code
corruption of critical information
Even in the context of isolated networks like offline environments or segmented cloud environments, the insider threat exists. Thus, attacks involving communications being sniffed or tampered with can still happen.
For example, attackers could successfully compromise prior security layers by:
bypassing isolation mechanisms
compromising a component of the network
getting the credentials of an internal IAM account (either from a service account or an actual person)
In such cases, encrypting communications would decrease the chances of attackers to successfully leak data or steal credentials from other network components. By layering various security practices (segmentation and encryption, for example), the application will follow the defense-in-depth principle.
Note that using the http` protocol is being deprecated by major web browsers.
In the past, it has led to the following vulnerabilities:
When a cookie is configured with the HttpOnly attribute set to true, the browser guaranties that no client-side script will be able to read it. In most cases, when a cookie is created, the default value of HttpOnly is false and it’s up to the developer to decide whether or not the content of the cookie can be read by the client-side script. As a majority of Cross-Site Scripting (XSS) attacks target the theft of session-cookies, the HttpOnly
attribute can help to reduce their impact as it won’t be possible to exploit the XSS vulnerability to steal session-cookies.
Users often connect to web servers through HTTP proxies.
Proxy can be configured to forward the client IP address via the X-Forwarded-For or Forwarded
HTTP headers.
IP address is a personal information which can identify a single user and thus impact his privacy.
When a reluctant (or lazy) quantifier is followed by a pattern that can match the empty string or directly by the end of the regex, it will always match zero times for *? or one time for +?. If a reluctant quantifier is followed directly by the end anchor ($), it behaves indistinguishably from a greedy quantifier while being less efficient.
This is likely a sign that the regex does not work as intended.
The use of parentheses, even those not required to enforce a desired order of operations, can clarify the intent behind a piece of code. However, redundant pairs of parentheses could be misleading and should be removed.
A regular expression is a sequence of characters that specifies a match pattern in text. Among the most important concepts are:
Character classes: defines a set of characters, any one of which can occur in an input string for a match to succeed.
Quantifiers: used to specify how many instances of a character, group, or character class must be present in the input for a match.
Wildcard (.): matches all characters except line terminators (also matches them if the s flag is set).
Many of these features include shortcuts of widely used expressions, so there is more than one way to construct a regular expression to achieve the same results. For example, to match a two-digit number, one could write [0-9]{2,2} or \d{2}. The latter is not only shorter but easier to read and thus to maintain.
This rule recommends replacing some quantifiers and character classes with more concise equivalents:
\d for [0-9] and \D for [^0-9]
\w for [A-Za-z0-9_] and \W for `[^A-Za-z0-9_]
. for character classes matching everything (e.g. [\w\W], [\d\D], or [\s\S] with s flag)
x? for x{0,1}, x* for x{0,}, x+ for x{1,}, x{N} for x{N,N}`
Server-side encryption (SSE) encrypts an object (not the metadata) as it is written to disk (where the S3 bucket resides) and decrypts it as it is read from disk. This doesn’t change the way the objects are accessed, as long as the user has the necessary permissions, objects are retrieved as if they were unencrypted. Thus, SSE only helps in the event of disk thefts, improper disposals of disks and other attacks on the AWS infrastructure itself.
There are three SSE options:
Server-Side Encryption with Amazon S3-Managed Keys (SSE-S3)
AWS manages encryption keys and the encryption itself (with AES-256) on its own.
Server-Side Encryption with Customer Master Keys (CMKs) Stored in AWS Key Management Service (SSE-KMS)
AWS manages the encryption (AES-256) of objects and encryption keys provided by the AWS KMS service.
Server-Side Encryption with Customer-Provided Keys (SSE-C)
AWS manages only the encryption (AES-256) of objects with encryption keys provided by the customer. AWS doesn’t store the customer’s encryption keys.
Arbitrary OS command injection vulnerabilities are more likely when a shell is spawned rather than a new process, indeed shell meta-chars can be used (when parameters are user-controlled for instance) to inject OS commands.
Even if it is legal, mixing case and non-case labels in the body of a switch statement is very confusing and can even be the result of a typing error.
Using the same value on both sides of a binary operator is a code defect. In the case of logical operators, it is either a copy/paste error and, therefore, a bug, or it is simply duplicated code and should be simplified. In the case of bitwise operators and most binary mathematical operators, having the same value on both sides of an operator yields predictable results and should be simplified as well.
Rejecting requests with significant content length is a good practice to control the network traffic intensity and thus resource consumption in order to prevent DoS attacks.
A common code smell that can hinder the clarity of source code is making assignments within sub-expressions. This practice involves assigning a value to a variable inside a larger expression, such as within a loop or a conditional statement.
This practice essentially gives a side-effect to a larger expression, thus making it less readable. This often leads to confusion and potential errors.
Amazon Simple Notification Service (SNS) is a managed messaging service for application-to-application (A2A) and application-to-person (A2P) communication. SNS topics allows publisher systems to fanout messages to a large number of subscriber systems. Amazon SNS allows to encrypt messages when they are received. In the case that adversaries gain physical access to the storage medium or otherwise leak a message they are not able to access the data.
Formatted SQL queries can be difficult to maintain, debug and can increase the risk of SQL injection when concatenating untrusted values into the query. However, this rule doesn’t detect SQL injections (unlike rule S3649), the goal is only to highlight complex/formatted queries.
A typical code smell known as unused function parameters refers to parameters declared in a function but not used anywhere within the function’s body. While this might seem harmless at first glance, it can lead to confusion and potential errors in your code. Disregarding the values passed to such parameters, the function’s behavior will be the same, but the programmer’s intention won’t be clearly expressed anymore. Therefore, removing function parameters that are not being utilized is considered best practice.
When placing Unicode Grapheme Clusters (characters which require to be encoded in multiple Code Points) inside a character class of a regular expression, this will likely lead to unintended behavior.
For instance, the grapheme cluster c̈ requires two code points: one for ‘c’, followed by one for the umlaut modifier ‘\u{0308}’. If placed within a character class, such as [c̈], the regex will consider the character class being the enumeration [c\u{0308}] instead. It will, therefore, match every ‘c’
and every umlaut that isn’t expressed as a single codepoint, which is extremely unlikely to be the intended behavior.
This rule raises an issue every time Unicode Grapheme Clusters are used within a character class of a regular expression.
There’s no reason to use literal boolean values in assertions. Doing so is at best confusing for maintainers, and at worst a bug.
A regex should never include a repetitive pattern whose body would match the empty string. This is usually a sign that a part of the regex is redundant or does not do what the author intended.
Conditional expressions which are always true or false can lead to unreachable code.
Constructing arguments of system commands from user input is security-sensitive. It has led in the past to the following vulnerabilities:
Arguments of system commands are processed by the executed program. The arguments are usually used to configure and influence the behavior of the programs. Control over a single argument might be enough for an attacker to trigger dangerous features like executing arbitrary commands or writing files into specific directories.
There is no reason to re-assign a variable to itself. Either this statement is redundant and should be removed, or the re-assignment is a mistake and some other value or variable was intended for the assignment instead.
This rule applies whenever an `if statement is followed by one or more else if statements; the final else if should be followed by an else statement.
The requirement for a final else statement is defensive programming.
The else statement should either take appropriate action or contain a suitable comment as to why no action is taken. This is consistent with the requirement to have a final default clause in a switch` statement.
To reduce the risk of cross-site scripting attacks, templating systems, such as `Twig, Django, Smarty, Groovy’s template engine, allow configuration of automatic variable escaping before rendering templates. When escape occurs, characters that make sense to the browser (eg: <a>) will be transformed/replaced with escaped/sanitized values (eg: & lt;a& gt; ).
Auto-escaping is not a magic feature to annihilate all cross-site scripting attacks, it depends on the strategy applied and the context, for example a “html auto-escaping” strategy (which only transforms html characters into html entities) will not be relevant when variables are used in a html attribute because ’:’ character is not escaped and thus an attack as below is possible:
<a href=”{{ myLink }}“>link</a> // myLink = javascript:alert(document.cookie) <a href=“javascript:alert(document.cookie)“>link</a> // JS injection (XSS attack)
A `for loop stop condition should test the loop counter against an invariant value (i.e. one that is true at both the beginning and ending of every loop iteration). Ideally, this means that the stop condition is set to a local variable just before the loop begins.
Stop conditions that are not invariant are slightly less efficient, as well as being difficult to understand and maintain, and likely lead to the introduction of errors in the future.
This rule tracks three types of non-invariant stop conditions:
When the loop counters are updated in the body of the for` loop
When the stop condition depend upon a method call
When the stop condition depends on an object property, since such properties could change during the execution of the loop.
Multiple spaces in a regular expression can make it hard to tell how many spaces should be matched. It’s more readable to use only one space and then indicate with a quantifier how many spaces are expected.
Amazon Elastic Block Store (EBS) is a block-storage service for Amazon Elastic Compute Cloud (EC2). EBS volumes can be encrypted, ensuring the security of both data-at-rest and data-in-transit between an instance and its attached EBS storage. In the case that adversaries gain physical access to the storage medium they are not able to access the data. Encryption can be enabled for specific volumes or for all new volumes and snapshots. Volumes created from snapshots inherit their encryption configuration. A volume created from an encrypted snapshot will also be encrypted by default.
When a cookie is protected with the secure
attribute set to true it will not be send by the browser over an unencrypted HTTP request and thus cannot be observed by an unauthorized person during a man-in-the-middle attack.
MIME confusion attacks occur when an attacker successfully tricks a web-browser to interpret a resource as a different type than the one expected. To correctly interpret a resource (script, image, stylesheet …) web browsers look for the Content-Type header defined in the HTTP response received from the server, but often this header is not set or is set with an incorrect value. To avoid content-type mismatch and to provide the best user experience, web browsers try to deduce the right content-type, generally by inspecting the content of the resources (the first bytes). This “guess mechanism” is called MIME type sniffing.
Attackers can take advantage of this feature when a website (“example.com” here) allows to upload arbitrary files. In that case, an attacker can upload a malicious image fakeimage.png (containing malicious JavaScript code or a polyglot content file) such as:
<script>alert(document.cookie)</script>
When the victim will visit the website showing the uploaded image, the malicious script embedded into the image will be executed by web browsers performing MIME type sniffing.
Amazon Elastic File System (EFS) is a serverless file system that does not require provisioning or managing storage. Stored files can be automatically encrypted by the service. In the case that adversaries gain physical access to the storage medium or otherwise leak a message they are not able to access the data.
Nested control flow statements such as if, for, while, switch, and try
are often key ingredients in creating
what’s known as “Spaghetti code”. This code smell can make your program difficult to understand and maintain.
When numerous control structures are placed inside one another, the code becomes a tangled, complex web. This significantly reduces the code’s readability and maintainability, and it also complicates the testing process.
Nested ternaries are hard to read and can make the order of operations complex to understand.
Unresolved directive in <stdin> - include::{noncompliant}[]
Instead, use another line to express the nested operation in a separate statement.
Unresolved directive in <stdin> - include::{compliant}[]
When writing code, it is important to ensure that each statement serves a purpose and contributes to the overall functionality of the program. When they have no side effects or do not change the control flow, they can either indicate a programming error or be redundant:
The code does not behave as intended: The statements are expected to have an effect but they do not. This can be caused by mistyping, copy-and-paste errors, etc.
The statements are residual after a refactoring.
Creating APIs without authentication unnecessarily increases the attack surface on the target infrastructure.
Unless another authentication method is used, attackers have the opportunity to attempt attacks against the underlying API. This means attacks both on the functionality provided by the API and its infrastructure.
Duplicated string literals make the process of refactoring complex and error-prone, as any change would need to be propagated on all occurrences.
A function that grows too large tends to aggregate too many responsibilities.
Such functions inevitably become harder to understand and therefore harder to maintain.
Above a specific threshold, it is strongly advised to refactor into smaller functions which focus on well-defined tasks.
Those smaller functions will not only be easier to understand, but also probably easier to test.
When the modulus of a negative number is calculated, the result will either be negative or zero. Thus, comparing the modulus of a variable for equality with a positive number (or a negative one) could result in unexpected results.
Disclosure of version information, usually overlooked by developers but disclosed by default by the systems and frameworks in use, can pose a significant security risk depending on the production environement.
Once this information is public, attackers can use it to identify potential security holes or vulnerabilities specific to that version.
Furthermore, if the published version information indicates the use of outdated or unsupported software, it becomes easier for attackers to exploit known vulnerabilities. They can search for published vulnerabilities related to that version and launch attacks that specifically target those vulnerabilities.
Predefined permissions, also known as canned ACLs, are an easy way to grant large privileges to predefined groups or users.
The following canned ACLs are security-sensitive:
`PublicRead, PublicReadWrite grant respectively “read” and “read and write” privileges to everyone in the world (AllUsers group).
AuthenticatedRead grants “read” privilege to all authenticated users (AuthenticatedUsers` group).
The MD5 algorithm and its successor, SHA-1, are no longer considered secure, because it is too easy to create hash collisions with them. That is, it takes too little computational effort to come up with a different input that produces the same MD5 or SHA-1 hash, and using the new, same-hash value gives an attacker the same access as if he had the originally-hashed value. This applies as well to the other Message-Digest algorithms: MD2, MD4, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160.
Consider using safer alternatives, such as SHA-256, SHA-512 or SHA-3.
A value that is incremented or decremented and then not stored is at best wasted code and at worst a bug.
Code is sometimes annotated as deprecated by developers maintaining libraries or APIs to indicate that the method, class, or other programming element is no longer recommended for use. This is typically due to the introduction of a newer or more effective alternative. For example, when a better solution has been identified, or when the existing code presents potential errors or security risks.
Deprecation is a good practice because it helps to phase out obsolete code in a controlled manner, without breaking existing software that may still depend on it. It is a way to warn other developers not to use the deprecated element in new code, and to replace it in existing code when possible.
Deprecated classes, interfaces, and their members should not be used, inherited or extended because they will eventually be removed. The deprecation period allows you to make a smooth transition away from the aging, soon-to-be-retired technology.
Check the documentation or the deprecation message to understand why the code was deprecated and what the recommended alternative is.
This rule verifies that single-line comments are not located at the ends of lines of code. The main idea behind this rule is that in order to be really readable, trailing comments would have to be properly written and formatted (correct alignment, no interference with the visual structure of the code, not too long to be visible) but most often, automatic code formatters would not handle this correctly: the code would end up less readable. Comments are far better placed on the previous empty line of code, where they will always be visible and properly formatted.
{upper_function}s with a long parameter list are difficult to use because maintainers must figure out the role of each parameter and keep track of their position.
Unresolved directive in <stdin> - include::{language}/noncompliant.adoc[]
The solution can be to:
Split the {function} into smaller ones
Unresolved directive in <stdin> - include::{language}/split-example.adoc[]
Find a better data structure for the parameters that group data in a way that makes sense for the specific application domain
Unresolved directive in <stdin> - include::{language}/struct-example.adoc[]
This rule raises an issue when a {function} has more parameters than the provided threshold.
Shared coding conventions allow teams to collaborate efficiently. This rule checks that all function names match a provided regular expression.
Two {func_name}s having the same implementation are suspicious. It might be that something else was intended. Or the duplication is intentional, which becomes a maintenance burden.
Hardcoding IP addresses is security-sensitive. It has led in the past to the following vulnerabilities:
Today’s services have an ever-changing architecture due to their scaling and redundancy needs. It is a mistake to think that a service will always have the same IP address. When it does change, the hardcoded IP will have to be modified too. This will have an impact on the product development, delivery, and deployment:
The developers will have to do a rapid fix every time this happens, instead of having an operation team change a configuration file.
It misleads to use the same address in every environment (dev, sys, qa, prod).
Last but not least it has an effect on application security. Attackers might be able to decompile the code and thereby discover a potentially sensitive address. They can perform a Denial of Service attack on the service, try to get access to the system, or try to spoof the IP address to bypass security checks. Such attacks can always be possible, but in the case of a hardcoded IP address solving the issue will take more time, which will increase an attack’s impact.
Developers often use TODO tags to mark areas in the code where additional work or improvements are needed but are not implemented immediately. However, these TODO tags sometimes get overlooked or forgotten, leading to incomplete or unfinished code. This rule aims to identify and address unattended TODO tags to ensure a clean and maintainable codebase. This description explores why this is a problem and how it can be fixed to improve the overall code quality.
Having all branches of a switch or if chain with the same implementation indicates a problem.
In the following code:
Unresolved directive in <stdin> - include::{example}[]
Either there is a copy-paste error that needs fixing or an unnecessary switch or if chain that should be removed.
Overriding a variable declared in an outer scope can strongly impact the readability, and therefore the maintainability, of a piece of code. Further, it could lead maintainers to introduce bugs because they think they’re using one variable but are really using another.
A mixed-content is when a resource is loaded with the HTTP protocol, from a website accessed with the HTTPs protocol, thus mixed-content are not encrypted and exposed to MITM attacks and could break the entire level of protection that was desired by implementing encryption with the HTTPs protocol.
The main threat with mixed-content is not only the confidentiality of resources but the whole website integrity:
A passive mixed-content (eg: <img src=“http://example.com/picture.png”>) allows an attacker to access and replace only these resources, like images, with malicious ones that could lead to successful phishing attacks.
With active mixed-content (eg: <script src=“http://example.com/library.js”>) an attacker can compromise the entire website by injecting malicious javascript code for example (accessing and modifying the DOM, steal cookies, etc).
A policy that allows identities to access all resources in an AWS account may violate the principle of least privilege. Suppose an identity has permission to access all resources even though it only requires access to some non-sensitive ones. In this case, unauthorized access and disclosure of sensitive information will occur.
Character classes in regular expressions are a convenient way to match one of several possible characters by listing the allowed characters or ranges of characters. If the same character is listed twice in the same character class or if the character class contains overlapping ranges, this has no effect.
Thus duplicate characters in a character class are either a simple oversight or a sign that a range in the character class matches more than is intended or that the author misunderstood how character classes work and wanted to match more than one character. A common example of the latter mistake is trying to use a range like [0-99] to match numbers of up to two digits, when in fact it is equivalent to [0-9]. Another common cause is forgetting to escape the - character, creating an unintended range that overlaps with other characters in the character class.
By default, web browsers perform DNS prefetching to reduce latency due to DNS resolutions required when an user clicks links from a website page.
For instance on example.com the hyperlink below contains a cross-origin domain name that must be resolved to an IP address by the web browser:
<a href=“https://otherexample.com”>go on our partner website</a>
It can add significant latency during requests, especially if the page contains many links to cross-origin domains. DNS prefetch allows web browsers to perform DNS resolving in the background before the user clicks a link. This feature can cause privacy issues because DNS resolving from the user’s computer is performed without his consent if he doesn’t intent to go to the linked website.
On a complex private webpage, a combination “of unique links/DNS resolutions” can indicate, to a eavesdropper for instance, that the user is visiting the private page.
In Unix file system permissions, the “others
” category refers to all
users except the owner of the file system resource and the members of the group
assigned to this resource.
Granting permissions to this category can lead to unintended access to files or directories that could allow attackers to obtain sensitive information, disrupt services or elevate privileges.
When implementing the HTTPS protocol, the website mostly continue to support the HTTP protocol to redirect users to HTTPS when they request a HTTP version of the website. These redirects are not encrypted and are therefore vulnerable to man in the middle attacks. The Strict-Transport-Security policy header (HSTS) set by an application instructs the web browser to convert any HTTP request to HTTPS.
Web browsers that see the Strict-Transport-Security policy header for the first time record information specified in the header:
the `max-age directive which specify how long the policy should be kept on the web browser.
the includeSubDomains optional directive which specify if the policy should apply on all sub-domains or not.
the preload optional directive which is not part of the HSTS specification but supported on all modern web browsers.
With the preload` directive the web browser never connects in HTTP to the website and to use this directive, it is required to submit the concerned application to a preload service maintained by Google.
`if statements with conditions that are always false have the effect of making blocks of code non-functional. if statements with conditions that are always true are completely redundant, and make the code less readable.
There are three possible causes for the presence of such code:
An if statement was changed during debugging and that debug code has been committed.
Some value was left unset.
Some logic is not doing what the programmer thought it did.
In any of these cases, unconditional if` statements should be removed.
Using remote artifacts without integrity checks can lead to the unexpected execution of malicious code in the application.
On the client side, where front-end code is executed, malicious code could:
impersonate users’ identities and take advantage of their privileges on the application.
add quiet malware that monitors users’ session and capture sensitive secrets.
gain access to sensitive clients’ personal data.
deface, or otherwise affect the general availability of the application.
mine cryptocurrencies in the background.
Likewise, a compromised software piece that would be deployed on a server-side application could badly affect the application’s security. For example, server-side malware could:
access and modify sensitive technical and business data.
elevate its privileges on the underlying operating system.
Use the compromised application as a pivot to attack the local network.
By ensuring that a remote artifact is exactly what it is supposed to be before using it, the application is protected from unexpected changes applied to it before it is downloaded. Especially, integrity checks will allow for identifying an artifact replaced by malware on the publication website or that was legitimately changed by its author, in a more benign scenario.
Important note: downloading an artifact over HTTPS only protects it while in transit from one host to another. It provides authenticity and integrity checks for the network stream only. It does not ensure the authenticity or security of the artifact itself.
When the execution is not explicitly terminated at the end of a switch case, it continues to execute the statements of the following case. While this is sometimes intentional, it often is a mistake which leads to unexpected behavior.
Testing for loop termination using an equality operator (== and !=
) is dangerous, because it could set up an infinite loop. Using a broader relational operator instead casts a wider net, and makes it harder (but not impossible) to accidentally write an infinite loop.
Cryptographic hash algorithms such as MD2, MD4, MD5, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160 and SHA-1 are no longer considered secure, because it is possible to have collisions
(little computational effort is enough to find two or more different inputs that produce the same hash).
Ternary expressions, while concise, can often lead to code that is difficult to read and understand, especially when they are nested or complex. Prioritizing readability fosters maintainability and reduces the likelihood of bugs. Therefore, they should be removed in favor of more explicit control structures, such as if/else statements, to improve the clarity and readability of the code.
Certificate Transparency (CT) is an open-framework to protect against identity theft when certificates are issued. Certificate Authorities (CA) electronically sign certificate after verifying the identify of the certificate owner. Attackers use, among other things, social engineering attacks to trick a CA to correctly verifying a spoofed identity/forged certificate.
CAs implement Certificate Transparency framework to publicly log the records of newly issued certificates, allowing the public and in particular the identity owner to monitor these logs to verify that his identify was not usurped.
Amazon Simple Queue Service (SQS) is a managed message queuing service for application-to-application (A2A) communication. Amazon SQS can store messages encrypted as soon as they are received. In the case that adversaries gain physical access to the storage medium or otherwise leak a message from the file system, for example through a vulnerability in the service, they are not able to access the data.
By default S3 buckets are private, it means that only the bucket owner can access it.
This access control can be relaxed with ACLs or policies.
To prevent permissive policies to be set on a S3 bucket the following settings can be configured:
`BlockPublicAcls: to block or not public ACLs to be set to the S3 bucket.
IgnorePublicAcls: to consider or not existing public ACLs set to the S3 bucket.
BlockPublicPolicy: to block or not public policies to be set to the S3 bucket.
RestrictPublicBuckets`: to restrict or not the access to the S3 endpoints of public policies to the principals within the bucket owner account.
There are several reasons to use a group in a regular expression:
to change the precedence (e.g. do(g|or) will match ‘dog’ and ‘door’)
to remember parenthesised part of the match in the case of capturing group
to improve readability
In any case, having an empty group is most probably a mistake. Either it is a leftover after refactoring and should be removed, or the actual parentheses were intended and were not escaped.
The requirement for a final default
clause is defensive programming. The clause should either take appropriate action, or contain a suitable comment as to why no action is taken.
Because it is easy to extract strings from an application source code or binary, credentials should not be hard-coded. This is particularly true for applications that are distributed or that are open-source.
In the past, it has led to the following vulnerabilities:
Credentials should be stored outside of the code in a configuration file, a database, or a management service for secrets.
This rule flags instances of hard-coded credentials used in database and LDAP connections. It looks for hard-coded credentials in connection strings, and for variable names that match any of the patterns from the provided list.
It’s recommended to customize the configuration of this rule with additional credential words such as “oauthToken”, “secret”, …
Nested `switch structures are difficult to understand because you can easily confuse the cases of an inner switch as belonging to an outer statement. Therefore nested switch statements should be avoided.
Specifically, you should structure your code to avoid the need for nested switch statements, but if you cannot, then consider moving the inner switch` to another function.
Log management is an important topic, especially for the security of a web application, to ensure user activity, including potential attackers, is recorded and available for an analyst to understand what’s happened on the web application in case of malicious activities.
Retention of specific logs for a defined period of time is often necessary to comply with regulations such as GDPR, PCI DSS and others. However, to protect user’s privacy, certain informations are forbidden or strongly discouraged from being logged, such as user passwords or credit card numbers, which obviously should not be stored or at least not in clear text.
Content security policy (CSP) (fetch directives) is a W3C standard which is used by a server to specify, via a http header, the origins from where the browser is allowed to load resources. It can help to mitigate the risk of cross site scripting (XSS) attacks and reduce privileges used by an application. If the website doesn’t define CSP header the browser will apply same-origin policy by default.
Content-Security-Policy: default-src ‘self’; script-src ‘self ‘ http://www.example.com
In the above example, all resources are allowed from the website where this header is set and script resources fetched from example.com are also authorized:
<img src=“selfhostedimage.png></script> <!— will be loaded because default-src ‘self’; directive is applied —> <img src=“http://www.example.com/image.png></script> <!— will NOT be loaded because default-src ‘self’; directive is applied —> <script src=“http://www.example.com/library.js></script> <!— will be loaded because script-src ‘self ‘ http://www.example.comdirective is applied —> <script src=“selfhostedscript.js></script> <!— will be loaded because script-src ‘self ‘ http://www.example.com directive is applied —> <script src=“http://www.otherexample.com/library.js></script> <!— will NOT be loaded because script-src ‘self ‘ http://www.example.comdirective is applied —>
Cloud platforms such as AWS, Azure, or GCP support virtual firewalls that can be used to restrict access to services by controlling inbound and outbound traffic. Any firewall rule allowing traffic from all IP addresses to standard network ports on which administration services traditionally listen, such as 22 for SSH, can expose these services to exploits and unauthorized access.
Dead stores refer to assignments made to local variables that are subsequently never used or immediately overwritten. Such assignments are unnecessary and don’t contribute to the functionality or clarity of the code. They may even negatively impact performance. Removing them enhances code cleanliness and readability. Even if the unnecessary operations do not do any harm in terms of the program’s correctness, they are - at best - a waste of computing resources.
Cognitive Complexity is a measure of how hard it is to understand the control flow of a unit of code. Code with high cognitive complexity is hard to read, understand, test, and modify.
As a rule of thumb, high cognitive complexity is a sign that the code should be refactored into smaller, easier-to-manage pieces.
readonly fields can only be assigned in a class constructor. If a class has a field that’s not marked readonly but is only set in the constructor, it could cause confusion about the field’s intended use. To avoid confusion, such fields should be marked readonly to make their intended use explicit, and to prevent future maintainers from inadvertently changing their use.
If a variable that is not supposed to change is not marked as const, it could be accidentally reassigned elsewhere in the code, leading to unexpected behavior and bugs that can be hard to track down.
By declaring a variable as const, you ensure that its value remains constant throughout the code. It also signals to other developers that this value is intended to remain constant. This can make the code easier to understand and maintain.
In some cases, using const can lead to performance improvements. The compiler might be able to make optimizations knowing that the value of a const variable will not change.
Control flow constructs like if-statements allow the programmer to direct the flow of a program depending on a boolean expression. However, if the condition is always true or always false, only one of the branches will ever be executed. In that case, the control flow construct and the condition no longer serve a purpose; they become gratuitous.
A naming convention in software development is a set of guidelines for naming code elements like variables, functions, and classes. {identifier_capital_plural} hold the meaning of the written code. Their names should be meaningful and follow a consistent and easily recognizable pattern. Adhering to a consistent naming convention helps to make the code more readable and understandable, which makes it easier to maintain and debug. It also ensures consistency in the code, especially when multiple developers are working on the same project.
This rule checks that {identifier} names match a provided regular expression.
DOM elements with ARIA roles should have a valid non-abstract role
DOM elements with ARIA roles should have the required properties
Variables should not be shadowed
No ARIA role or property for unsupported DOM elements
No redundant ARIA role
JSX lets you write HTML-like markup inside a JavaScript file, commonly used in React.
Adding comments inside JSX might be tricky as JSX code is neither a plain HTML nor JavaScript.
HTML comments (
<!— comment here —>
) are not valid syntax in JSX.JavaScript-style comments, single or multiline, will create an additional text node in the browser, which is probably not expected.