Giter VIP home page Giter VIP logo

secretlint's Introduction

Secretlint Actions Status

Secretlint is that Pluggable linting tool to prevent committing credential.

Secretlint is that Pluggable linting tool to prevent committing credential.

Features

  • Scanner: Found credentials in a project and report these
  • Project Friendly: Easy to set up your project and integrate CI services
  • Pre-Commit Hook: Prevent committing credential files
  • Pluggable: Allow creating custom rule and flexible configuration
  • Documentation: Describe the reason that rule detect it as secret

Quick Demo

You can view secretlint linting result on https://secretlint.github.io/.

Quick Start

You can try to use Secretlint on your project at one command.

If you already have installed Docker:

docker run -v `pwd`:`pwd` -w `pwd` --rm -it secretlint/secretlint secretlint "**/*"

If you already have installed Node.js:

npx @secretlint/quick-start "**/*"

After running, If you got empty result and exit status is 0, your project is secure. Otherwise, you got some error report, your project includes credential as raw data.

An example of secretlint results

You want to get continuous security, Please see following installation guide and setup pre-commit hook and CI.

Installation

Using Docker

Prerequisites: Require Docker

Use our Docker container to get an environment with Node.js and secretlint and running as fast as you can download them.

You can check all files under the current directory with secretlint by following command:

docker run -v `pwd`:`pwd` -w `pwd` --rm -it secretlint/secretlint secretlint "**/*"

secretlint/secretlint docker container work without configuration by design.

This Docker Image has built-in packages:

For more details, please see secretlint's Dockerfile.

Using Node.js

Prerequisites: Require Node.js 18+.

Secretlint is written by JavaScript. You can install Secretlint using npm:

npm install secretlint @secretlint/secretlint-rule-preset-recommend --save-dev

You should then set up a configuration file:

npx secretlint --init

Finally, you can run Secretlint on any file or directory like this:

npx secretlint "**/*"

๐Ÿ“ Secretlint support glob pattern and glob pattern should be wrapped by a double quote.

It is also possible to install Secretlint globally using npm install --global. But, We do not recommended it, some rules may be broken in globally.

Usage

secretlint --help show Usage.

  Secretlint CLI that scan secret/credential data.

  Usage
    $ secretlint [file|glob*]

  Note
    supported glob syntax is based on microglob
    https://github.com/micromatch/micromatch#matching-features

  Options
    --init             setup config file. Create .secretlintrc.json file from your package.json
    --format           [String] formatter name. Default: "stylish". Available Formatter: checkstyle, compact, jslint-xml, json, junit, pretty-error, stylish, table, tap, unix, mask-result
    --output           [path:String] output file path that is written of reported result.
    --no-color         disable ANSI-color of output.
    --no-terminalLink  disable terminalLink of output.
    --maskSecrets      enable masking of secret values. replace actual secrets with "***".
    --secretlintrc     [path:String] path to .secretlintrc config file. Default: .secretlintrc.*
    --secretlintignore [path:String] path to .secretlintignore file. Default: .secretlintignore

  Options for Developer
    --profile          Enable performance profile.
    --secretlintrcJSON [String] a JSON string of .secretlintrc. use JSON string instead of rc file.

  Experimental Options
    --locale            [String] locale tag for translating message. Default: en

  Examples
    $ secretlint ./README.md
    # glob pattern should be wrapped with double quote
    $ secretlint "**/*"
    $ secretlint "source/**/*.ini"
    # found secrets and mask the secrets
    $ secretlint .zsh_history --format=mask-result --output=.zsh_history

Exit Status
  Secretlint exits with the following values:

  - 0: 
    - Linting succeeded, no errors found. 
    - Found lint error but --output is specified.
  - 1: 
    - Linting failed, errors found.
  - 2: 
    - Unexpected error occurred, fatal error.

Configuration

Secretlint has a configuration file .secretlintrc.{json,yml,js}.

After running secretlint --init, you'll have a .secretlintrc.json file in your directory.

In it, you'll see some rules configured like this:

{
  "rules": [
    {
      "id": "@secretlint/secretlint-rule-preset-recommend"
    }
  ]
}

The id property is the name of secretlint rule package.

Secretlint does not have built-in rule. You want to add some rule and You should install the package and add the rule to .secretlintrc file.

Each rule has same configuration pattern:

  • options: Option definition for the rule. For more details, see each rule documentation
  • disabled: If disabled is true, disable the rule
  • allowMessageIds: allowMessageIds is an array of message id that you want to suppress error report
    • message id is defined in each rule and please see the rule documentation

Example: options

For example, @secretlint/secretlint-rule-example has allows in options. This allows option define a list of RegExp-like String that you want to ignore.

{
  "rules": [
    {
      "id": "@secretlint/secretlint-rule-example",
      "options": {
        "allows": [
          "/dummy_secret/i"
        ]
      }
    }
  ]
}

When you use a preset like @secretlint/secretlint-rule-preset-recommend, you need to put the option in rules.

For example, an option for @secretlint/secretlint-rule-preset-recommend > @secretlint/secretlint-rule-aws

{
  "rules": [
    {
      "id": "@secretlint/secretlint-rule-preset-recommend",
      "rules": [
        {
          "id": "@secretlint/secretlint-rule-aws",
            "options": {
              "allows": [
	            // it will be ignored
                "xxxx-xxxx-xxxx-xxxx-xxxx"
              ]
            }
        }
      ]
    }
  ]
}

Example: allowMessageIds

For example, you have got following error report by run secretlint:

$ secretlint "**/*"

SECRET.txt
  1:8  error  [EXAMPLE_MESSAGE] found secret: SECRET  @secretlint/secretlint-rule-example

โœ– 1 problem (1 error, 0 warnings)

This error's message id is EXAMPLE_MESSAGE in @secretlint/secretlint-rule-example.

If you want to ignore this error, please use allowMessageIds.

{
  "rules": [
    {
      "id": "@secretlint/secretlint-rule-example",
      "allowMessageIds": ["EXAMPLE_MESSAGE"]
    }
  ]
}

When you use a preset like @secretlint/secretlint-rule-preset-recommend, you need to put the option in rules.

For example, If you want to ignore "AWSAccountID" and "AWSAccessKeyID" of "@secretlint/secretlint-rule-aws", you can write following.

{
  "rules": [
    {
      "id": "@secretlint/secretlint-rule-preset-recommend",
      "rules": [
        {
          "id": "@secretlint/secretlint-rule-aws",
          "allowMessageIds": ["AWSAccountID", "AWSAccessKeyID"]
        }
      ]
    }
  ]
}

Ignoring by comment

@secretlint/secretlint-rule-filter-comments supports ignoring comment like secretlint-disable.

// secretlint-disable

THIS IS SECRET, BUT IT WILL BE IGNORED

// secretlint-enable

For more details, please see Configuring Secretlint.

Use Cases

Hide secrets in lint error message

Secretlint support --maskSecrets option that mask secrets in lint error message. It is useful that you want to hide secrets in CI logs.

$ secretlint --maskSecrets "**/*"

Fix secrets

Secretlint can not fix the secrets automatically. However, It is useful that --format=mask-result mask the secrets of input file.

For example, you can mask the secrets of .zsh_history file and overwrite it.

$ secretlint .zsh_history --format=mask-result --output=.zsh_history

Rule Packages

Secretlint rules has been implemented as separated modules.

Also, Secretlint provide rule preset that includes recommened rule set.

Custom Rules

You can create own secretlint rule.

You want to get a secretlint rule for suitable your project and you can create it! A secretlint rule is a just npm package.

If you want to know creating secretlint rule, please see docs/secretlint-rule.md.

Integrations

Pre-commit Hook per project

You can use Secretlint with some pre-commit tool. This can prevent to commit secret data by linting with Secretlint.

Applying secretlint to the project and improve security on team developing.

Use Case: If you want to introduce secretlint to Node.js project, this combination is useful.

Install Husky and lint-staged:

npx husky-init && npm install lint-staged --save-dev

Add hooks to .husky/pre-commit:

npx husky add .husky/pre-commit "npx --no-install lint-staged"

Edit package.json:

{
  // add "lint-staged" field
  "lint-staged": {
    "*": [
      "secretlint"
    ]
  }
}

This means that check each staged file by Secretlint before commit.

Use Case: You have a project that is developing with Docker. Easy to integrate to secretlint.

Install pre-commit

# macOS. see also https://pre-commit.com/#install
brew install pre-commit

Create .pre-commit-config.yaml:

-   repo: local
    hooks:
    -   id: secretlint
        name: secretlint
        language: docker_image
        entry: secretlint/secretlint:latest secretlint

Example setup repository:

Bash Script

Alternately you can save this script as .git/hooks/pre-commit and give it execute permission(chmod +x .git/hooks/pre-commit):

#!/bin/sh
FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0

# Secretlint all selected files
echo "$FILES" | xargs ./node_modules/.bin/secretlint
# If you using docker
# echo "$FILES" | xargs docker run -v `pwd`:`pwd` -w `pwd` --rm secretlint/secretlint secretlint
RET=$?
if [ $RET -eq 0 ] ;then
    exit 0
else
    exit 1
fi

Pre-commit Hook globally

Use Case: If you want to check any project by secretlint, you can use global git hooks.

Git 2.9+ supports core.hooksPath. It allow to integrate secretlint globally.

We have created example git hooks project using secretlint + Docker.

You can set up by following steps:

# clone this repository
git clone https://github.com/secretlint/git-hooks git-hooks
cd git-hooks
# integrate secretlint to git hook globally
git config --global core.hooksPath $(pwd)/hooks

After setup of core.hooksPath, secretlint check any file before you commit it.

For more details, see secretlint/git-hooks project.

Node.js version also can be used for global git hook. If you interesting in it, please see @azu/git-hooks.

CI

GitHub Actions

If you already set secretlint Using Node.js, you can run secretlint with your configuration on GitHub Actions.

Put .github/workflows/secretlint.yml in your repository.

name: Secretlint
on: [push, pull_request]
permissions:
  contents: read
jobs:
  test:
    name: "Secretlint"
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v3
      - name: setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 20
      - name: Install
        run: npm ci
      - name: Lint with Secretlint
        run: npx secretlint "**/*"

This configuration also integrate Pull Request review comment via actions/setup-node.

github-actions.png

If you want to only check diff files, please see following example:

name: test-diff
on:
  push:
  pull_request:
jobs:
  test-diff:
    permissions:
      contents: read
    name: "Run secretlint to diff files"
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v4
        with:
          # fetch history to get all changed files on push or pull_request event
          fetch-depth: 0
      - name: Get changed files
        id: changed-files
        uses: tj-actions/changed-files@v44
      - name: setup Node ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Show changed files
        run: echo "${{ steps.changed-files.outputs.all_changed_files }}"
      - name: Install
        if: steps.changed-files.outputs.any_changed == 'true'
        run: npm ci
      - name: Run secretlint
        if: steps.changed-files.outputs.any_changed == 'true'
        run: npx secretlint ${{ steps.changed-files.outputs.all_changed_files }}

Mega-Linter

Mega-Linter is a linters aggregator natively compliant with any CI tool, embedding 80+ linting apps, including secretlint by default.

You can install it on any repository project using the following command (Node.js must be installed previously)

npx mega-linter-runner --install

megalinter-secretlint-failure.png

Browser

Secretlint WebExtension works on your browser.

This web extension aim to founds credentials that are included in your request/response.

Secretlint WebExtension

Secretlint WebExtension integrate to DevTools in Chrome/Firefox. This extension help web developer to notice exposed credential.

Others

SARIF format support

Please use @secretlint/secretlint-formatter-sarif.

npm install @secretlint/secretlint-formatter-sarif --dev
secretlint --format @secretlint/secretlint-formatter-sarif "**/*"

Semantic Versioning Policy

Secretlint project follow Semantic Versioning(secretlint-rule-preset-canary is exception).

  • Patch release (intended to not break your lint build)
    • A bug fix to the CLI or core (including formatters).
    • Improvements to documentation.
    • Non-user-facing changes such as refactoring.
    • Re-releasing after a failed release (i.e., publishing a release that doesn't work for anyone).
  • Minor release (might break your lint build)
    • A new option.
    • An existing rule is deprecated.
    • A new CLI capability is created.
    • New public API are added (new classes, new methods, new arguments to existing methods, etc.).
      • It might break TypeScript definitions
    • A new formatter is created.
  • Major release (break your lint build)
    • A new option to an existing rule that results in secretlint reporting more errors by default.
    • An existing formatter is removed.
    • Add new default rule to rule preset.
    • Part of the public API is removed or changed in an incompatible way.

Motivation

Philosophy

  • Reduce false-positive of linting
  • Integration to developing workflow
  • Empower Users to Contribute

Opt-in instead of Opt-out

Secretlint adopt opt-in approach.

In our experience, linting tools that report various errors by default is difficult to use. Opt-in approach help to introduce Secretlint increasing.

It will help to reduce false-positive by configuration.

Rule as Documentation

We think a rule as a documentation. So, Each rule should have reasonable documentation.

We need to describe why this file is error. A rule that has not documentation, It is just a opinionated.

Describe the reason of error and then it will lead to reduce false-positive error.

Also, Secretlint CLI support hyperlink in Terminal. It means that you can jump to rule documentation from lint error message directly.

clickable link in output

Example on iTerm 2: Cmd + Click error's messageId and open AWSSecretAccessKey on your browser.

If you want to know support terminal, please see Hyperlinks in Terminal Emulators.

Also, Welcome to Contribution about secretlint documentation!

Why Node.js?

  • Package Manager
    • Require package manager to realize flexible pluggable system
    • Node.js has npm and yarn as package manager
    • Package manager help to install custom plugin/rule by user
  • Exist Reference Implementation
    • Node.js already has pluggable linting tools like ESLint, textlint, stylelint etc
    • So Node.js user familiar with pluggable linting tools
    • Previously, I created textlint as same approach, so I familiar with Node.js
  • Users
    • JavaScript is Popular language
    • It means that empower Users to Contribute
    • Users can create own rule by own hand

Of course, secretlint also support Docker.

Changelog

See Releases page.

Contributing

Pull requests and stars are always welcome.

For bugs and feature requests, please create an issue.

See also, CONTRIBUTING.md and CODE_OF_CONDUCT.md

Add New Rule

You can use npm run gen:rule command to create new rule.

npm run gen:rule

For more details, please see CONTRIBUTING.md

Benchmark

Benchmark workflow is run on every commit.

Author

License

MIT ยฉ azu

secretlint's People

Contributors

azu avatar bittrance avatar camelmasa avatar cm-dyoshikawa avatar dependabot[bot] avatar deviouslab avatar eccentricexit avatar github-actions[bot] avatar gkzz avatar hotoolong avatar hritikr avatar k-hal avatar korosuke613 avatar ksato9700 avatar kyontan avatar munierujp avatar numb86 avatar nvuillam avatar pseudocoding avatar renovate-bot avatar renovate[bot] avatar rhysd avatar risu729 avatar siketyan avatar slarwise avatar susam-projects avatar teppeis avatar thinca avatar uki1014 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

secretlint's Issues

rule: secretlint-rule-slack

Detect slack token

"slack_token":
  lib: cribl
  description: Slack Token
  regex: /xox[p|b|o|a][\s\S]*/g
  sampleData: xoxp-23984754863-2348975623103

    xoxa-23984754863-2348975623103

    xoxb-23984754863-2348975623103

    xoxo-23984754863-2348975623103
  tags: slack,token
...

via https://docs.cribl.io/docs/regexesyml

docs: Why raw token is secret?

It common case, secretlint disallow to embed token string in plain text.
We should add documentaion about this case.

  • Common Problems
  • Resolve Patterns

1.0.0 roadmap

TODO

  • README
    • Getting Started
    • Commit Hooks
  • Consider Ignoring by default #22
  • Config validation #23
  • Docker #7

Docker support

Secretlint is written by Node.js

Why Node.js?

  • Package Manager
    • Require pacakge manager to realize flexible pluggable system
    • Node.js has npm and yarn as package manager
    • Package manger help to install custom plugin/rule by user
  • Exist Reference Implementaion
    • Node.js already has pluggable linting tools like ESLint, textlint, stylelint etc
    • So Node.js user familiar with pluggable linting tools
    • Previously, I created textlint as same approach, so I familiar with Node.js

For Non Node.js user

Probably, secretlint's setting is less than ESLint, textlint.
We can provide official docker support that includes commonly presets. #6

It help to use non-Node.js user.

node: ignore by default

We need to discuss about default ignore

  • .git
  • node_modules
  • .secretlintrc
  • .secretlintignore

We want to prevent secret in .secretlintrc.
To ignore .secretlintrc is correct?

rule: .env

.env (dot env) is set of credential.
In sometimes, user commit this file by error.

We think about a rule for .env.

CI: Publish secretlint package and Docker Image from CI

Current Problem: We must build docker image after publishing npm package.
Because, Dockerfile install the published version from npm reigstry.

RUN npm install -g secretlint@${SECRETLINT_VERSION} @secretlint/secretlint-rule-preset-recommend@${SECRETLINT_VERSION} && \

Dependencies illust:

publish to npm -> build Docker Image that install secretlint from npm

So, We can not use lerna version with --create-release option.

The reason of adding --no-push option .

secretlint/package.json

Lines 30 to 33 in 8723133

"versionup": "lerna version --no-push --conventional-commits",
"versionup:patch": "lerna version patch --no-push --conventional-commits",
"versionup:minor": "lerna version minor --no-push --conventional-commits",
"versionup:major": "lerna version major --no-push --conventional-commits",

We want to resolve this by publishing to npm from CI.

In Local

  • npm run versionup

In CI

  • npm run release if tags is pushed

Icon/logo

We need to get Icon and Logo

Icon usecase is organization icon:

image

Logo usecase is README:

image

rule: unexpected expose user path

We want to detect unexpected expose user path.

For example, webpack build js file and output bundled file.
In some case, The bundled file include the user name(file path).

This issue is occured by bundler, sourcemap, etc...

We want to detect unexpected exposing persoanl information.

Idea

  • ... welcome

re-create formatter for secretlint

Currently, @secretlint/formatter is wrapper of textlint's formatter.

We want to implement each formatter as native and separated modules.

rule: secretlint-rule-gcp

Detect

  • <project>-<hash>.json
{
  "type": "service_account",
  "project_id": "xxxxxxxx",
  "private_key_id": "xxxxx",
  "private_key": "-----BEGIN PRIVATE KEY-----\nsssssn-----END PRIVATE KEY-----\n",
  "client_email": "[email protected]",
  "client_id": "123454321234543212345",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token" ...
}
  • <project>-<hash>.p12

This p12 file can be decoded.
Because, the file password is notasecret.

Bag Attributes
    friendlyName: privatekey
    localKeyID:  54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54
Key Attributes: <No Attributes>
Bag Attributes
    friendlyName: privatekey
    localKeyID: 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54
subject=/CN=11111111111111111111111111
issuer=/CN=11111111111111111111111111
-----BEGIN CERTIFICATE-----
CERTIFICATE_DATA==
-----END CERTIFICATE-----

long id vs. short id

Currently, we use long id like @<scope>/secretelint-rule-<name> instead of @<scope>/<name>.

Mixed id style is ambiguous.
For example, following linting result that include id.
In this case, if user use long id in config, secretlint show long id.

cloudbuild/deploy.sh
  12:26  error  found AWS Access Key ID: AKIXXXXXX  @secretlint/secretlint-rule-preset-recommend > @secretlint/secretlint-rule-aws

I think that user config affect formatter output is not good thing.
This issue can not be resolved by normalizing id .

Actually, user use the id for configuration of secretelint.
It is good that copy-pastable id or interactive fixing config way.

--profile

We need to add --profile feature.
It calculate spend time for each rule and each file.

const now = Date.now();
 lintSource().finally(() => {
            console.log(`${filePath} taken ${Date.now() - now}ms`);
        });

Design: Configuration file

secretlint will support secretlintrc.json as configuration file.

This issue discuss about the configuration format.

Condition

  • Configuration file can be parsed as JSON
    • It means that limit usage of RegExp literal

Format

textlint-pattern

Props

  • Simple object

Cons

{
  "rules": {
    "<pkg_1>": <option>
    "<pkg_2>": {
      "severity": "waring"
    }
  }
}

Babel/ESLint style

Depend on order of array.

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry"
      }
    ]
  ]
}

Array Rule

Props

  • explicitly
  • System options can be separated
  • It is flexible

Cons

  • A bit long
  • Should handle duplicated id?
{
  "rules": [
    { 
      "name": "<pkg>"
      "options": <option>
      // Additional by systems
      "severity": "warning"
    }
  ]
}

formatter: json formatter should be native

-f json is the result of textlint's format.
We should return secretlint results as json insteadof it.

Currently, @secretlint/formatter is wrapper of textlint's formatter #10
As soon as, json formatter will be replaced native formatter.
Because, json formatter present raw results data.

Ignore binary file

#8 #30 is similar issue.

Often binary file is large and spend time is huge.
The eser want to ignore binary file by option.

Secret config file

It conflicted with secretlint, but we need to think about secret config file.

We need to think about uncommitable(secret) config file.

Self-introduce

Introduce secretlint to secretlint repository.

Need to setup .secretlintignore, because test data has many secret...

report: documentation url

[TEST_DIR]/fixtures/SECRET.txt
  1:8  error  [EXAMPLE_MESSAGE] found secret: SECRET  @secretlint/secretlint-rule-example

โœ– 1 problem (1 error, 0 warnings)

See https://secretlint.example.com/?messageId={messageId},{messageId},{messageId}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.