Skip to content
4 changes: 4 additions & 0 deletions .asist.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ dontforceignore: false
cicdrules:
- "XSSLabel"
- "XSSMergeField"
- "XSSTooltip"

# `ruleoverrides` property is used to override some properties of standard rules. The following are defined below:
# severity: Low|Medium|High|Critical
# includepattern: specify files or folders to be included from scans.
# excludepattern: specify files or folders to be excluded from scans.
# `enabled` property is used to enable/disable a particular rule. It will override `enableAllStandardRules` property.
# `maxissues` property sets maximum allowed issue count (default is 0 if not specified - no issues allowed).
# This is useful when introducing ASIST to a codebase with existing issues - you can gradually reduce maxissues.
ruleoverrides:
XSSTooltip: # Rule Id to be overriden
severity: Medium
enabled: true
maxissues: 50 # Allow up to 50 XSSTooltip issues (grandfathered existing issues)
XSSLabel:
includepattern: "\\.page$|\\.component$"
enabled: true
Expand Down
102 changes: 61 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
</div>

# ASIST (Automated Security Issue Scanning Tool)

[![Go Reference](https://pkg.go.dev/badge/github.com/certinia/asist.svg)](https://pkg.go.dev/github.com/certinia/asist)
[![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-blue)](https://opensource.org/license/bsd-3-clause)

ASIST is a regex-based, blazing-fast Static Application Security Testing (SAST) tool for securing Salesforce apps at developer speed.
ASIST is a regex-based, blazing-fast Static Application Security Testing (SAST) tool for securing Salesforce apps at developer speed.

Originally built for internal use at Certinia to support Security Reviews, we have now decided to release it to the community 🌍

Expand All @@ -25,7 +26,7 @@ Originally built for internal use at Certinia to support Security Reviews, we ha

## ▶️ VSCode extension demo

![ASIST scan via Extension](images/scan-using-extension.gif)
![ASIST scan via Extension](images/scan-using-extension.gif)

## ▶️ CLI demo

Expand Down Expand Up @@ -59,7 +60,6 @@ Alternatively:
- To just build the binary for your OS and architecture: `make`
- To cross-compile: `GOOS=windows GOARCH=amd64 go build -o asist.exe .`
- To build binaries for the most common platforms, run: `make build-binaries`


## 🕹️ Usage

Expand Down Expand Up @@ -201,12 +201,12 @@ Configuration files can also be explicitly specified using the `-c` argument (no

Within the config file, you can:

* Enable/disable all the standard rules
* Override certain properties of standard rules
* Exclude files or directories for all rules
* Exclude files or directories for specific rules
* Add custom regex rules
* Define rules to be run in CI/CD mode
- Enable/disable all the standard rules

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Enable/disable all the standard rules
- Enable/disable all the standard rules

- Override certain properties of standard rules
- Exclude files or directories for all rules
- Exclude files or directories for specific rules
- Add custom regex rules
- Define rules to be run in CI/CD mode

See our [example config file](.asist.example.yaml) for a walkthrough of all config options.

Expand All @@ -215,6 +215,7 @@ See our [example config file](.asist.example.yaml) for a walkthrough of all conf
Users can override certain properties of standard rules according to their needs, allowing them to customize the behavior of specific rules by:

- Disabling rules entirely: `enabled`
- Limiting the number of allowed rule violations: [`maxissues`](#rule-max-issues)
- Tweaking rule severity: `severity`
- Tweaking what files should be scanned: `includepattern`
- Tweaking what files should not be scanned: `excludepattern`
Expand All @@ -238,7 +239,6 @@ customregexrules:

You can test this specific rule like this:


```shell
asist -c .asist.yaml -r doNotDebug <file>
```
Expand Down Expand Up @@ -292,11 +292,33 @@ In this mode, by default, all enabled runs will be run if `cicdrules` property i
cicdrules:
- "XSSLabel"
- "XSSMergeField"
- "XSSDomHtml"
```

This allows developers to add a subset of the overall ruleset to ASIST to their CI/CD pipelines, and gradually add more rules to CI/CD as they start clearing out findings for other rules. This prevents any issues for rules defined in `cicdrules` from creeping back into the codebase.

### 📊 Baseline scans
## Rule Max Issues

When introducing ASIST to an existing codebase, you may have pre-existing security issues that you want to prevent from increasing while you work on fixing them. The `maxissues` property in [`ruleoverrides`](#-customizing-standard-rules) allows you to set maximum allowed issue counts for specific rules.

**By default, rules have a limit of 0 issues.** When a rule exceeds its `maxissues` threshold, ASIST will exit with an error code (see [Exit Codes](#-exit-codes)). You only need to set `maxissues` if you want to allow existing issues while preventing them from growing.

```yaml
ruleoverrides:
XSSLabel:
maxissues: 150 # Allow up to 150 XSSTooltip issues (grandfather existing issues)
XSSMergeField:
maxissues: 0 # Explicitly set to 0 (same as default - no issues allowed)
# XSSDomHtml has no maxissues set, defaults to 0 (no issues allowed)
```

This feature allows you to:

- Gradually introduce stricter security requirements by lowering maxissues over time
- Prevent technical debt from growing while you address existing issues
- Start enforcing security on a codebase with 150 existing issues, then reduce to 100, 50, and eventually 0

## 📊 Baseline scans

This mode is intended for SecOps teams to create benchmarks across multiple projects and measure the adoption of ASIST.

Expand All @@ -314,32 +336,32 @@ This command will output a JSON like this (when formatted):

```json
[
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "b17fe249915712219aca7e",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
},
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "3a2861bee641864816b86d",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
}
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "b17fe249915712219aca7e",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
},
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "3a2861bee641864816b86d",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
}
]
```

Expand All @@ -350,8 +372,7 @@ A few differences can be observed compared to regular scans:
- Each issue is assigned a `FindingID`, which is effectively a hash that uniquely identifies the finding based on the rule, the finding location, and if it's a false positive or not.
- A few more properties are added, such as if the rule is custom, or if the finding is marked as false positive or not.


### 🫣 .gitignore and .forceignore files
## 🫣 .gitignore and .forceignore files

By default, ASIST will ignore files and folders defined inside .gitignore and .forceignore. If you don't want ASIST to respect .gitignore and .forceignore, you can use the following properties in the config file:

Expand All @@ -367,7 +388,6 @@ By default, ASIST will ignore files and folders defined inside .gitignore and .f
| 3 | ASIST failed due to internal error (file a bug report!) |
| 4 | ASIST failed due to user error (review input and config) |


## 🏗️ [CONTRIBUTING](CONTRIBUTING.md)

## 🎫 [LICENSE](LICENSE.txt)
Expand Down Expand Up @@ -465,4 +485,4 @@ A big thank you to everyone who has contributed to ASIST!
</a>
</td>
</tr>
</table>
</table>
19 changes: 19 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,25 @@ func (c *Config) GetCICDRuleIds() []rules.RuleID {
return ruleIds
}

/**
* Returns the max allowed issues for a specific rule ID.
* Returns ruleoverrides.<rule>.maxissues if set, otherwise 0.
*/
func (c *Config) GetRuleMaxIssues(ruleId rules.RuleID) int {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure but should GetRuleMaxIssues also be renamed to GetRuleCicdMaxIssues?

@B1naryVision B1naryVision Mar 3, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind it, I think the method is clear. But happy to change it if you feel like it should be renamed

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's okay to me.

if c == nil || c.RuleOverrides == nil {
return 0
}

// Check if maxissues is explicitly set in ruleoverrides
if override, exists := c.RuleOverrides[string(ruleId)]; exists {
if override.MaxIssues != nil {
return *override.MaxIssues
}
}

return 0
}

/**
* GetEnabledOverridedStandardRuleIds - Return the standard rule Ids
* Where RuleOveride property is defined and override rules enabled property is set to true or nil
Expand Down
100 changes: 60 additions & 40 deletions docs/index.md

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future enhancement I might do, is make the index/readme copy from a central file with these details so I don't need to copy-paste across except for the headers/footers. Maybe it does and I just didn't see it?

Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ Alternatively:
- To cross-compile: `GOOS=windows GOARCH=amd64 go build -o asist.exe .`
- To build binaries for the most common platforms, run: `make build-binaries`


## 🕹️ Usage

To see the help, run:
Expand Down Expand Up @@ -198,12 +197,12 @@ Configuration files can also be explicitly specified using the `-c` argument (no

Within the config file, you can:

* Enable/disable all the standard rules
* Override certain properties of standard rules
* Exclude files or directories for all rules
* Exclude files or directories for specific rules
* Add custom regex rules
* Define rules to be run in CI/CD mode
- Enable/disable all the standard rules
- Override certain properties of standard rules
- Exclude files or directories for all rules
- Exclude files or directories for specific rules
- Add custom regex rules
- Define rules to be run in CI/CD mode

See our [example config file](https://github.com/certinia/asist/blob/main/.asist.example.yaml) for a walkthrough of all config options.

Expand All @@ -212,6 +211,7 @@ See our [example config file](https://github.com/certinia/asist/blob/main/.asist
Users can override certain properties of standard rules according to their needs, allowing them to customize the behavior of specific rules by:

- Disabling rules entirely: `enabled`
- Limiting the number of allowed rule violations: [`maxissues`](#rule-max-issues)
- Tweaking rule severity: `severity`
- Tweaking what files should be scanned: `includepattern`
- Tweaking what files should not be scanned: `excludepattern`
Expand All @@ -235,7 +235,6 @@ customregexrules:

You can test this specific rule like this:


```shell
asist -c .asist.yaml -r doNotDebug <file>
```
Expand Down Expand Up @@ -283,11 +282,33 @@ In this mode, by default, all enabled runs will be run if `cicdrules` property i
cicdrules:
- "XSSLabel"
- "XSSMergeField"
- "XSSDomHtml"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this list be alphabetical?

```

This allows developers to add a subset of the overall ruleset to ASIST to their CI/CD pipelines, and gradually add more rules to CI/CD as they start clearing out findings for other rules. This prevents any issues for rules defined in `cicdrules` from creeping back into the codebase.

### 📊 Baseline scans
## Rule Max Issues

When introducing ASIST to an existing codebase, you may have pre-existing security issues that you want to prevent from increasing while you work on fixing them. The `maxissues` property in [`ruleoverrides`](#-customizing-standard-rules) allows you to set maximum allowed issue counts for specific rules.

**By default, rules have a limit of 0 issues.** When a rule exceeds its `maxissues` threshold, ASIST will exit with an error code (see [Exit Codes](#-exit-codes)). You only need to set `maxissues` if you want to allow existing issues while preventing them from growing.

```yaml
ruleoverrides:
XSSLabel:
maxissues: 150 # Allow up to 150 XSSTooltip issues (grandfather existing issues)
XSSMergeField:
maxissues: 0 # Explicitly set to 0 (same as default - no issues allowed)
# XSSDomHtml has no maxissues set, defaults to 0 (no issues allowed)
```

This feature allows you to:

- Gradually introduce stricter security requirements by lowering maxissues over time
- Prevent technical debt from growing while you address existing issues
- Start enforcing security on a codebase with 150 existing issues, then reduce to 100, 50, and eventually 0

## 📊 Baseline scans

This mode is intended for SecOps teams to create benchmarks across multiple projects and measure the adoption of ASIST.

Expand All @@ -305,32 +326,32 @@ This command will output a JSON like this (when formatted):

```json
[
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "b17fe249915712219aca7e",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
},
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "3a2861bee641864816b86d",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
}
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "b17fe249915712219aca7e",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
},
{
"RepositoryName": "certinia/asist",
"RepositoryURL": "git@github.com:certinia/asist.git",
"RecordType": "Finding",
"Content": {
"FindingID": "3a2861bee641864816b86d",
"IsCustom": false,
"IsFalsePositive": true,
"RuleID": "LwcNonStandardPositioning",
"Severity": "Medium",
"RuleCategory": "Security"
}
}
]
```

Expand All @@ -341,15 +362,14 @@ A few differences can be observed compared to regular scans:
- Each issue is assigned a `FindingID`, which is effectively a hash that uniquely identifies the finding based on the rule, the finding location, and if it's a false positive or not.
- A few more properties are added, such as if the rule is custom, or if the finding is marked as false positive or not.


### 🫣 .gitignore and .forceignore files
## 🫣 .gitignore and .forceignore files

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some nitpicking, a H1 -> H3.

Arguably this should have stayed a H3 and CI/CD should be a H2 but...
Happy to change it up 😅


By default, ASIST will ignore files and folders defined inside .gitignore and .forceignore. If you don't want ASIST to respect .gitignore and .forceignore, you can use the following properties in the config file:

- **dontgitignore**
- **dontforceignore**

### ⍈ Exit Codes
## ⍈ Exit Codes

| Exit code | Exit Reason |
| --------- | -------------------------------------------------------- |
Expand Down Expand Up @@ -405,5 +425,5 @@ This extension is shipped with prebuilt ASIST binaries, but if you need to speci

1. Open the ASIST `Extension settings`
1. Navigate to the `Workspace` tab
2. Enable the `Custom Binary Enabled` setting
3. Provide the path to your ASIST binary in `Custom Binary Path`
1. Enable the `Custom Binary Enabled` setting
1. Provide the path to your ASIST binary in `Custom Binary Path`

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context: 1. 1. 1 etc is valid for MD, it auto-increments.

Loading