Skip to content

feat: add support for custom rules. Move rules and gitleaks logic to 2ms#367

Merged
cx-diogo-rocha merged 16 commits intomasterfrom
AST-75295-custom-rules
Jan 19, 2026
Merged

feat: add support for custom rules. Move rules and gitleaks logic to 2ms#367
cx-diogo-rocha merged 16 commits intomasterfrom
AST-75295-custom-rules

Conversation

@cx-diogo-rocha
Copy link
Copy Markdown
Contributor

@cx-diogo-rocha cx-diogo-rocha commented Jan 19, 2026

Closes #

Proposed Changes

  • Added support for custom rules, which can be defined in yaml or json files for use in cli; or directly as a list of ruledefine.Rule (new rule struct) in the interface
  • Fully moved rules from gitleaks to our own, to package ruledefine
  • Validations that previously occurred, for every rule, every time 2ms
    ran, now run in unit tests
  • Created new rule struct, replacing our previous rule struct that
    wrapped gitleaks Rule.
  • The new Rule struct has all fields that are in practice used by
    gitleaks Rules; fields which are not used by default rules of gitleaks
    were not included.
  • Breaking change: - ruleID became a uuid4 that identifies a rule
    regardless of its name. The old ruleID became ruleName, but with different casing (generic-api-key->Generic-Api-Key)
    • ignores and selects with flags --ignore-rule and -rule still work with
      old ruleIDs. Comparison of ruleNames (old ruleIDs) is performed with all characters in lower case.
  • Breaking change - ids of results have changed, now take into
    account the new uuid4 ruleID.
    • ignores on -config file or in --ignore-result will no longer
      properly ignore those results because the id of results changed
  • Added new fields to results:
    • severity - for now High as default for every rule. Rules that can
      perform validation on their results (eg, github-pat) will bump the
      severity to Critical if the secret is Valid; and lower the severity to
      Medium if the secret is Invalid
    • ruleCategory - used to classify and groups rules
    • ruleName - the exact same as old ruleID
  • Added flags for limits:
    --max-findings: Caps the total number of findings across the entire
    scan. When the limit is reached, the scan stops early and reports
    results up to that limit. Set to 0 (default) to disable.
    --max-rule-matches-per-fragment: Limits the number of regex matches per
    rule per fragment (e.g., file, chunked file, page). Useful for
    preventing excessive matches in large files. Set to 0 (default) to
    disable.
    --max-secret-size: Ignores secrets larger than the specified size in
    bytes. Helps filter out false positives from large binary blobs or
    encoded content. Set to 0 (default) to disable.

Changes to rules

  • clojars-api-token - reintroduced entropy to 2, like it is in gitleaks
  • github-app-token - reintroduced entropy to 3, like it is in gitleaks
  • plaid-client-id - updated entropy from 3 to 3.5, like it is in
    gitleaks
  • vault-service-token - updated regex according to latest version of
    gitleaks; reintroduced entropy to 3.5, like it is in gitleaks

Checklist

  • I covered my changes with tests.
  • I Updated the documentation that is affected by my changes:
    • Change in the CLI arguments
    • Change in the configuration file

I submit this contribution under the Apache-2.0 license.

cx-diogo-rocha and others added 10 commits November 6, 2025 14:21
<!--
Thanks for contributing to 2ms by offering a pull request.
-->

Closes #

**Proposed Changes**
- Fully moved rules from gitleaks to our own, to package ruledefine
- Validations that previously occurred, for every rule, every time 2ms
ran, now run in unit tests
- Created new rule struct, replacing our previous rule struct that
wrapped gitleaks Rule.
- The new Rule struct has all fields that are in practice used by
gitleaks Rules; fields which are not used by default rules of gitleaks
were not included.
- **Breaking change:** - ruleID became a uuid4 that identifies a rule
regardless of its name. The old ruleID became ruleName
- ignores and selects with flags --ignore-rule and -rule still work with
old ruleIDs.
- **Breaking change** - ids of results have changed, now take into
account the new uuid4 ruleID.
- ignores with on -config file or in --ignore-result will not longer
properly ignore those results because the id of results changed
- Added new fields to results:
- severity - for now High as default for every rule. Rules that can
perform validation on their results (eg, github-pat) will bump the
severity to Critical if the secret is Valid; and lower the severity to
Medium if the secret is Invalid
  - ruleCategory - used to classify and groups rules
  - ruleName - the exact same as old ruleID

The purpose of these changes is to allow us to have more control over
the rules, in preparation for:
1. Allowing users to create their own rules in the open source tool. In
the future the user will be able to define more fields than simply the
regex (currently supported with --regex flag)
2. Allowing query editing in Checkmarx One.

**Changes to rules**
- clojars-api-token - reintroduced entropy to 2, like it is in gitleaks
- github-app-token - reintroduced entropy to 3, like it is in gitleaks
- plaid-client-id - updated entropy from 3 to 3.5, like it is in
gitleaks
- vault-service-token - updated regex according to latest version of
gitleaks; reintroduced entropy to 3.5, like it is in gitleaks

**Checklist**

- [x] I covered my changes with tests.
- [x] I Updated the documentation that is affected by my changes:
  - [x] Change in the CLI arguments
  - [x] Change in the configuration file

I submit this contribution under the Apache-2.0 license.
<!--
Thanks for contributing to 2ms by offering a pull request.
-->

Closes #

**Proposed Changes**
- Introduced flag --custom-rules-path which supports passing a file of
type JSON or YAML. This file has to be a list of ruledefine.Rule, and
can be used to define custom rules to be used in the scan

Custom Rules can be:
- Overrides - if a rule present in the file shares the same ruleId as a
default rule of 2ms, the rule present in the file will replace
(override) the default rule in the scan. If a rule is overridden, it
will simply take all fields from the rule as defined in the file. You
must include all fields that you want to be defined, otherwise they will
be nil/empty.
- New rules - if a rule does not share ruleId with a default rule, it
will be appended to the list of rules used in the scan.

- Rules can now be ignored by ruleId
- Custom rules work properly with --rule and --ignore-rule flags. Rules
can be selected/ignored by ruleId, ruleName and tag.

**Note:** Rules defined in the custom rules can find duplicate results
with each other or with default rules. 2ms doesn't match or correlate
results found by different rules, it will be the responsibility of the
user to avoid situations like these. **One exception** is
generic-api-key and overrides of generic-api-key, whose results will be
ignored if found by any other rule in the scan. This behavior already
happened in the default generic-api-key and was extended to overrides of
this rule.

**Checklist**

- [x] I covered my changes with tests.
- [x] I Updated the documentation that is affected by my changes:
  - [x] Change in the CLI arguments
  - [ ] Change in the configuration file

I submit this contribution under the Apache-2.0 license.
<!--
Thanks for contributing to 2ms by offering a pull request.
-->

Closes #

**Proposed Changes**

<!--
Please describe the big picture of your changes here. If it fixes a bug
or resolves a feature request, be sure to link to that issue.
-->

**Checklist**

- [x] I covered my changes with tests.
- [ ] I Updated the documentation that is affected by my changes:
  - [ ] Change in the CLI arguments
  - [ ] Change in the configuration file

I submit this contribution under the Apache-2.0 license.
…#351)

<!--
Thanks for contributing to 2ms by offering a pull request.
-->

Closes #

**Proposed Changes**

<!--
Please describe the big picture of your changes here. If it fixes a bug
or resolves a feature request, be sure to link to that issue.
-->

**Checklist**

- [ ] I covered my changes with tests.
- [ ] I Updated the documentation that is affected by my changes:
  - [ ] Change in the CLI arguments
  - [ ] Change in the configuration file

I submit this contribution under the Apache-2.0 license.
…295-custom-rules

# Conflicts:
#	README.md
#	go.mod
#	lib/reporting/report_test.go
#	lib/reporting/sarif.go
…of Rule (#356)

<!--
Thanks for contributing to 2ms by offering a pull request.
-->

Closes #

**Proposed Changes**

<!--
Please describe the big picture of your changes here. If it fixes a bug
or resolves a feature request, be sure to link to that issue.
-->

**Checklist**

- [ ] I covered my changes with tests.
- [ ] I Updated the documentation that is affected by my changes:
  - [ ] Change in the CLI arguments
  - [ ] Change in the configuration file

I submit this contribution under the Apache-2.0 license.
…ion bug (#363)

**New Limit Flags**
--max-findings: Caps the total number of findings across the entire
scan. When the limit is reached, the scan stops early and reports
results up to that limit. Set to 0 (default) to disable.
--max-rule-matches-per-fragment: Limits the number of regex matches per
rule per fragment (e.g., file, chunked file, page). Useful for
preventing excessive matches in large files. Set to 0 (default) to
disable.
--max-secret-size: Ignores secrets larger than the specified size in
bytes. Helps filter out false positives from large binary blobs or
encoded content. Set to 0 (default) to disable.

**Bug Fix**
Fixed last-line detection: Secrets on the last line of files without a
trailing newline are now correctly detected. The fix adds a virtual
newline marker in the location calculation logic, removing the previous
CxFileEndMarker workaround.
<!--
Thanks for contributing to 2ms by offering a pull request.
-->

Closes #

**Proposed Changes**
Updated version to v5.
Updated README with a better explanation of entropy
Changed jwt rule name to Jwt, now consistent with all other rules
Added test for rule naming convention
<!--
Please describe the big picture of your changes here. If it fixes a bug
or resolves a feature request, be sure to link to that issue.
-->

**Checklist**

- [ ] I covered my changes with tests.
- [ ] I Updated the documentation that is affected by my changes:
  - [ ] Change in the CLI arguments
  - [ ] Change in the configuration file

I submit this contribution under the Apache-2.0 license.
@cx-diogo-rocha cx-diogo-rocha requested a review from a team as a code owner January 19, 2026 14:11
@github-actions
Copy link
Copy Markdown

kics-logo

KICS version: v1.7.13

Category Results
HIGH HIGH 0
MEDIUM MEDIUM 0
LOW LOW 0
INFO INFO 0
TRACE TRACE 0
TOTAL TOTAL 0
Metric Values
Files scanned placeholder 16
Files parsed placeholder 16
Files failed to scan placeholder 0
Total executed queries placeholder 53
Queries failed to execute placeholder 0
Execution time placeholder 1

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 19, 2026

Logo
Checkmarx One – Scan Summary & Details994fc881-3f70-4d2a-a2a8-bb0baf0abe53

Great job! No new security vulnerabilities introduced in this pull request

@cx-diogo-rocha cx-diogo-rocha changed the title feat: Add support for custom rules. Move rules and gitleaks logic to 2ms feat: add support for custom rules. Move rules and gitleaks logic to 2ms Jan 19, 2026
Comment thread README.md
Comment thread engine/engine_test.go
Comment thread engine/engine.go
Comment thread engine/rules/ruledefine/hardcoded_password.go
@cx-diogo-rocha cx-diogo-rocha merged commit f3fdf49 into master Jan 19, 2026
13 of 14 checks passed
@cx-diogo-rocha cx-diogo-rocha deleted the AST-75295-custom-rules branch January 19, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants