---
title: Static Code Analysis (SAST) Custom Rules
description: >-
  Write Static Analysis Custom Rules to check the security and quality of your
  code.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Static Code Analysis (SAST) > Static
  Code Analysis (SAST) Custom Rules
---

# Static Code Analysis (SAST) Custom Rules

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site). ().
{% /alert %}

{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com



{% alert level="warning" %}
Code Security is not available for the  site.
{% /alert %}


{% /callout %}

[Datadog Static Code Analysis](https://app.datadoghq.com/ci/code-analysis) lets you define static analysis rules as custom rules. You can share these custom rules within your organization.

## Rule organization{% #rule-organization %}

SAST rules are organized within rulesets. A ruleset is a collection of rules. There are no constraints on how rules are organized within a ruleset. For example, some users might want to have rulesets for a specific language and others for a category.

A ruleset must have a unique name with only letters, numbers, and hyphens (`-`). Examples of valid ruleset names are `python-security`, `cobra-team-checks`, or `my-company-security-checks`.

## Anatomy of a custom rule{% #anatomy-of-a-custom-rule %}

A custom rule is composed of three main components:

- A **tree-sitter query** that captures what AST elements to check.
- **JavaScript code** that process the AST elements reports violations.
- **Test code** to test the rule.

### Tree-sitter query{% #tree-sitter-query %}

Custom rules use [tree-sitter queries](https://tree-sitter.github.io/tree-sitter/using-parsers/queries/index.html) to query the code abstract syntax tree (AST) and retrieve elements to analyze. Elements of the AST are captured by the query using the `@` operator.

All captured nodes from the tree-sitter query are injected in the JavaScript code and further processed to produce violations.

### JavaScript code{% #javascript-code %}

The JavaScript code is defined in a `visit` function. This function is triggered at each match of the tree-sitter query. If a tree-sitter query captures a function call and the analyzed code contains 10 function calls, the `visit` function is called 10 times and each invocation has the capture of each occurrence.

The `visit` function has the signature `visit(node, path, code)`:

- `node` is the tree-sitter context being matched.
- `path` is the path under analysis (convenient for filtering violation on path or filename).
- `code` is the code under analysis.

To get a captured node, use the `captures` attribute of the first argument of the `visit` function. For example, the code below retrieves the `functionName` from a tree-sitter query. Each element contains the following attributes:

- `cstType`: the tree-sitter type of the node.
- `start`: start position of the node. The position contains `line` and `col` attributes.
- `end`: end position of the node. The position contains `line` and `col` attributes.
- `text`: the content of the node.

{% alert level="danger" %}
`line` and `col` attributes start at 1. Any result with `line` or `col` set to 0 is ignored.
{% /alert %}

```javascript
function visit(node, filename, code) {
  const functionNameNode = node.captures["functionName"];
  console.log("cst type");
  console.log(functionNameNode.cstType);
  console.log("start line");
  console.log(functionNameNode.start.line);
}
```

The analyzer includes a few helper functions to help you write rules:

- `buildError(startLine, startCol, endLine, endCol, message, severity, category)` builds an error.
  - `severity` is one of the following: `ERROR`, `WARNING`, `NOTICE` and `INFO`.
  - `category` is one of the following: `BEST_PRACTICES`, `CODE_STYLE`, `ERROR_PRONE`, `PERFORMANCE` and `SECURITY`.
- `addError(error)` reports an error.
- `ddsa.getParent(node)` returns the given node's parent, or `undefined` if the node is the root node.
- `ddsa.getChildren(node)` returns an array of the given node's children, or an empty array if the node is a leaf node.

### Rule examples{% #rule-examples %}

All Datadog default rules are available in [Code Security](https://app.datadoghq.com/ci/code-analysis/static-analysis/default-rulesets). You can easily analyze and copy them to create your own custom rules.
