Merge pull request #28 from Checkmarx/feat/add-pr-commenter

feat: converting to javascript action
This commit is contained in:
Rogerio Peixoto
2021-10-21 14:35:35 +01:00
committed by GitHub
16 changed files with 19713 additions and 115 deletions

24
.github/workflows/test_action.yaml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Test KICS action
on:
workflow_dispatch:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: mkdir -p myoutput
- name: Test KICS action
uses: ./
with:
path: test/samples/positive1.tf,test/samples/positive2.tf
token: ${{ secrets.GITHUB_TOKEN }}
timeout: 60
output_path: myoutput/
output_formats: sarif
ignore_on_exit: results
enable_comments: true
- run: ls -la && ls -la myoutput
if: always()

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
.vscode

179
README.md
View File

@ -1,10 +1,29 @@
# KICS Github Action ![kics](images/icon-32x32.png) <img src="images/github.png" alt="Github" width="40" height="40"> # KICS Github Action
[![License: GPL-3.0](https://img.shields.io/badge/License-GPL3.0-yellow.svg)](https://www.gnu.org/licenses) [![License: GPL-3.0](https://img.shields.io/badge/License-GPL3.0-yellow.svg)](https://www.gnu.org/licenses)
[![Latest Release](https://img.shields.io/github/v/release/checkmarx/kics-github-action)](https://github.com/checkmarx/kics-github-action/releases) [![Latest Release](https://img.shields.io/github/v/release/checkmarx/kics-github-action)](https://github.com/checkmarx/kics-github-action/releases)
[![Open Issues](https://img.shields.io/github/issues-raw/checkmarx/kics-github-action)](https://github.com/checkmarx/kics-github-action/issues) [![Open Issues](https://img.shields.io/github/issues-raw/checkmarx/kics-github-action)](https://github.com/checkmarx/kics-github-action/issues)
## Integrate KICS into your GitHub workflows, using KICS Github Action to make your IaC more secure - [KICS Github Action](#kics-github-action)
- [Integrate KICS into your GitHub workflows](#integrate-kics-into-your-github-workflows)
- [Supported Platforms](#supported-platforms)
- [Please find more info in the official website: <a href="https://kics.io">kics.io</a>](#please-find-more-info-in-the-official-website-kicsio)
- [Inputs](#inputs)
- [Simple usage example](#simple-usage-example)
- [Workflow failures](#workflow-failures)
- [Don't fail on results](#dont-fail-on-results)
- [Fail by severity usage example](#fail-by-severity-usage-example)
- [Enabling Pull Request Comment](#enabling-pull-request-comment)
- [PR Comment Example](#pr-comment-example)
- [Annotations](#annotations)
- [Profiling KICS](#profiling-kics)
- [Uploading SARIF report](#uploading-sarif-report)
- [Using configuration file](#using-configuration-file)
- [How To Contribute](#how-to-contribute)
- [License](#license)
## Integrate KICS into your GitHub workflows
**KICS** (pronounced as 'kick-s') or **Kicscan** is an open source solution for static code analysis of Infrastructure as Code. **KICS** (pronounced as 'kick-s') or **Kicscan** is an open source solution for static code analysis of Infrastructure as Code.
@ -28,26 +47,37 @@ It is as simple as running a CLI tool, making it easy to integrate into any proj
### Please find more info in the official website: <a href="https://kics.io">kics.io</a> ### Please find more info in the official website: <a href="https://kics.io">kics.io</a>
And official documentation page <a href="https://docs.kics.io">docs.kics.io</a>
## Inputs ## Inputs
| Variable | Example Value &nbsp; | Description &nbsp; | Type | Required | Default | | Variable | Example Value &nbsp; | Description &nbsp; | Type | Required | Default |
| ------------------ | --------------------------------------- | ---------------------------------------------------------------- | ------- | -------- | --------------------------------------------- | | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------- | --------------------------------------------- |
| path | terraform/main.tf,Dockerfile | paths to a file or directories to scan, comma separated list | String | Yes | N/A | | enable_comment | true | Enable pull request report comments | Boolean | No | false |
| ignore_on_exit | results | defines which non-zero exit codes should be ignored (all, results, errors, none) | String | No | none | | path | terraform/main.tf,Dockerfile | paths to a file or directories to scan, comma separated list | String | Yes | N/A |
| fail_on | high,medium | comma separated list of which severities returns exit code !=0 | String | No | high,medium,low,info | | ignore_on_exit | results | defines which non-zero exit codes should be ignored (all, results, errors, none) | String | No | none |
| timeout | 75 | number of seconds the query has to execute before being canceled | String | No | 60 | | fail_on | high,medium | comma separated list of which severities returns exit code !=0 | String | No | high,medium,low,info |
| profiling | CPU | turns on profiler that prints resource consumption in the logs during the execution (CPU, MEM) | String | No | N/A | | timeout | 75 | number of seconds the query has to execute before being canceled | String | No | 60 |
| config_path | ./kics.config | path to configuration file | String | No | N/A | | profiling | CPU | turns on profiler that prints resource consumption in the logs during the execution (CPU, MEM) | String | No | N/A |
| platform_type | terraform,ansible | case insensitive list of platform types to scan | String | No | All platforms | | config_path | ./kics.config | path to configuration file | String | No | N/A |
| exclude_paths | ./shouldNotScan/*,somefile.txt | exclude paths from scan, supports glob, comma separated list | String | No | N/A | | platform_type | terraform,ansible | case insensitive list of platform types to scan | String | No | All platforms |
| exclude_queries | a227ec01-f97a-4084-91a4-47b350c1db54 | exclude queries by providing the query ID, comma separated list | String | No | N/A | | exclude_paths | ./shouldNotScan/*,somefile.txt | exclude paths from scan, supports glob, comma separated list | String | No | N/A |
| exclude_categories | 'Observability,Networking and Firewall' | exclude categories by providing its name, comma separated list | String | No | N/A | | exclude_queries | a227ec01-f97a-4084-91a4-47b350c1db54 | exclude queries by providing the query ID, comma separated list | String | No | N/A |
| exclude_results | 'd4a1fa80-d9d8-450f-87c2-e1f6669c41f8' | exclude results by providing the similarity ID of a result | String | No | N/A | | exclude_categories | 'Observability,Networking and Firewall' | exclude categories by providing its name, comma separated list | String | No | N/A |
| output_formats | 'json,sarif' | formats in which the results report will be exported | String | No | json | | exclude_results | 'd4a1fa80-d9d8-450f-87c2-e1f6669c41f8' | exclude results by providing the similarity ID of a result | String | No | N/A |
| output_path | results.json | file path to store result in json format | String | No | N/A | | include_queries | a227ec01-f97a-4084-91a4-47b350c1db54 | include only specified list of queries to the scan, cannot be provided with query exclusion flags | String | No | N/A |
| payload_path | /tmp/mypayload.json | file path to store source internal representation in JSON format | String | No | N/A | | output_formats | 'json,sarif' | formats in which the results report will be exported | String | No | json |
| queries | | path to directory with queries (default "./assets/queries") | String | No | ./assets/queries downloaded with the binaries | | output_path | results.json | file path to store result in json format | String | No | N/A |
| verbose | true | verbose scan | Boolean | No | false | | payload_path | /tmp/mypayload.json | file path to store source internal representation in JSON format | String | No | N/A |
| queries | | path to directory with queries (default "./assets/queries") | String | No | ./assets/queries downloaded with the binaries |
| verbose | true | verbose scan | Boolean | No | false |
| type | Ansible,Dockerfile | case insensitive comma-separated list of platform types to scan (Ansible, AzureResourceManager, CloudFormation, Dockerfile, Kubernetes, OpenAPI, Terraform) | String | No | all types |
| bom | true | include bill of materials (BoM) in results.json output | Boolean | No | false |
| disable_full_descriptions | false | disable request for full descriptions and use default vulnerability descriptions | Boolean | false |
| disable_secrets | false | disable secrets detection | Boolean | false |
| secrets_regexes_path | ./mydir/secrets-config.json | path to custom secrets regex rules configuration file | String | No | N/A |
| libraries_path | ./myLibsDir | path to directory with Rego libraries | String | No | N/A |
## Simple usage example ## Simple usage example
@ -58,7 +88,7 @@ It is as simple as running a CLI tool, making it easy to integrate into any proj
- uses: actions/checkout@v2 - uses: actions/checkout@v2
# Scan Iac with kics # Scan Iac with kics
- name: run kics Scan - name: run kics Scan
uses: checkmarx/kics-action@v1.2 uses: checkmarx/kics-action@v1.3
with: with:
# scanning two directories: ./terraform/ ./cfn-templates/ plus a single file # scanning two directories: ./terraform/ ./cfn-templates/ plus a single file
path: 'terraform,cfn-templates,my-other-sub-folder/Dockerfile' path: 'terraform,cfn-templates,my-other-sub-folder/Dockerfile'
@ -73,24 +103,6 @@ It is as simple as running a CLI tool, making it easy to integrate into any proj
By default KICS will fail your workflow on any results found. By default KICS will fail your workflow on any results found.
### Fail by severity usage example
If want your pipeline just to fail on HIGH and MEDIUM severity results and KICS engine execution errors:
```yaml
steps:
- uses: actions/checkout@v2
- name: run kics Scan
uses: checkmarx/kics-action@v1.2
with:
path: 'terraform,my-other-sub-folder/Dockerfile'
fail_on: high,medium
output_path: 'results.json'
- name: display kics results
run: |
cat results.json
```
### Don't fail on results ### Don't fail on results
If you want KICS to ignore the results and return exit status code 0 unless a KICS engine error happens: If you want KICS to ignore the results and return exit status code 0 unless a KICS engine error happens:
@ -99,7 +111,7 @@ If you want KICS to ignore the results and return exit status code 0 unless a KI
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: run kics Scan - name: run kics Scan
uses: checkmarx/kics-action@v1.2 uses: checkmarx/kics-action@v1.3
with: with:
path: 'terraform' path: 'terraform'
ignore_on_exit: results ignore_on_exit: results
@ -109,6 +121,88 @@ If you want KICS to ignore the results and return exit status code 0 unless a KI
cat results.json cat results.json
``` ```
### Fail by severity usage example
If want your pipeline just to fail on HIGH and MEDIUM severity results and KICS engine execution errors:
```yaml
steps:
- uses: actions/checkout@v2
- name: run kics Scan
uses: checkmarx/kics-action@v1.3
with:
path: 'terraform,my-other-sub-folder/Dockerfile'
fail_on: high,medium
output_path: 'results.json'
- name: display kics results
run: |
cat results.json
```
## Enabling Pull Request Comment
`GITHUB_TOKEN` enables this github action to access github API and post comments in a pull request:
```yaml
name: Test KICS action PR comment
on:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: run kics Scan
uses: checkmarx/kics-action@v1.3
with:
path: test/samples/positive1.tf,test/samples/positive2.tf
token: ${{ secrets.GITHUB_TOKEN }}
output_path: myResults/
ignore_on_exit: results
enable_comments: true
```
### PR Comment Example
<img alt="KICS Logo" src="https://user-images.githubusercontent.com/75368139/136991766-a4e5bc8b-63db-48f7-9384-740e9f15c9f6.png" width="150">
**KICS version: 1.4.5**
<table>
<tr></tr>
<tr><td>
| | Category | Results |
| --------------------------------------------------------------------------------------------------------------- | -------- | ------- |
| ![HIGH](https://user-images.githubusercontent.com/23239410/92157087-97285600-ee32-11ea-988f-0aca12c4c126.png) | HIGH | 3 |
| ![MEDIUM](https://user-images.githubusercontent.com/23239410/92157093-98598300-ee32-11ea-83d7-af52251a011b.png) | MEDIUM | 2 |
| ![LOW](https://user-images.githubusercontent.com/23239410/92157091-98598300-ee32-11ea-8498-19bd7d62019b.png) | LOW | 0 |
| ![INFO](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | INFO | 0 |
| ![TRACE](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | TRACE | 0 |
| ![TOTAL](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | TOTAL | 5 |
</td><td>
| | Metric | Values |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------- | ------ |
| ![placeholder](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | Files scanned | 2 |
| ![placeholder](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | Files parsed | 2 |
| ![placeholder](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | Files failed to scan | 0 |
| ![placeholder](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | Total queries | 821 |
| ![placeholder](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | Queries failed to execute | 0 |
| ![placeholder](https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png) | Execution time | 13s |
</td></tr> </table>
## Annotations
After scanning, [kics-github-action](https://github.com/Checkmarx/kics-github-action) will add the results as annotations in a pull request:
<img alt="annotations-preview" src="images/annotations-preview.png" width=800>
## Profiling KICS ## Profiling KICS
@ -120,7 +214,7 @@ You can only enable one profiler at a time, CPU or MEM.
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: run kics Scan - name: run kics Scan
uses: checkmarx/kics-action@v1.2 uses: checkmarx/kics-action@v1.3
with: with:
path: 'terraform' path: 'terraform'
profiling: MEM profiling: MEM
@ -151,7 +245,7 @@ jobs:
# make sure results dir is created # make sure results dir is created
run: mkdir -p results-dir run: mkdir -p results-dir
- name: Run KICS Scan with SARIF result - name: Run KICS Scan with SARIF result
uses: checkmarx/kics-action@v1.2 uses: checkmarx/kics-action@v1.3
with: with:
path: 'terraform' path: 'terraform'
# when provided with a directory on output_path # when provided with a directory on output_path
@ -225,7 +319,6 @@ jobs:
with: with:
sarif_file: results-dir/results.sarif sarif_file: results-dir/results.sarif
``` ```
## How To Contribute ## How To Contribute
We welcome [issues](https://github.com/checkmarx/kics-github-action/issues) to and [pull requests](https://github.com/checkmarx/kics-github-action/pulls) against this repository! We welcome [issues](https://github.com/checkmarx/kics-github-action/issues) to and [pull requests](https://github.com/checkmarx/kics-github-action/pulls) against this repository!

View File

@ -1,27 +1,35 @@
# action.yml # action.yml
name: 'KICS Github Action' name: "KICS Github Action"
description: 'Run KICS scan against IaC projects' description: "Run KICS scan against IaC projects"
inputs: inputs:
token:
description: "The GITHUB_TOKEN for the current workflow run"
required: false
default: ${{github.token}}
enable_comments:
required: false
default: false
description: "Enable pull request report comments"
path: path:
description: 'paths to a file or directories to scan, accepts a comma separated list' description: "paths to a file or directories to scan, accepts a comma separated list"
required: true required: true
ignore_on_exit: ignore_on_exit:
description: 'defines which non-zero exit codes should be ignored (all, results, errors, none)' description: "defines which non-zero exit codes should be ignored (all, results, errors, none)"
required: false required: false
fail_on: fail_on:
description: 'comma separated list of which severities returns exit code !=0' description: "comma separated list of which severities returns exit code !=0"
required: false required: false
timeout: timeout:
description: 'number of seconds the query has to execute before being canceled' description: "number of seconds the query has to execute before being canceled"
required: false required: false
profiling: profiling:
description: 'turns on profiler that prints resource consumption in the logs during the execution (CPU, MEM)' description: "turns on profiler that prints resource consumption in the logs during the execution (CPU, MEM)"
required: false required: false
config_path: config_path:
description: 'path to configuration file' description: "path to configuration file"
required: false required: false
platform_type: platform_type:
description: 'case insensitive list of platform types to scan' description: "case insensitive list of platform types to scan"
required: false required: false
exclude_paths: exclude_paths:
description: "exclude paths from scan, supports glob, quoted comma separated string example: './shouldNotScan/*,somefile.txt'" description: "exclude paths from scan, supports glob, quoted comma separated string example: './shouldNotScan/*,somefile.txt'"
@ -39,39 +47,44 @@ inputs:
description: "formats in which the results report will be exported (json, sarif)" description: "formats in which the results report will be exported (json, sarif)"
required: false required: false
output_path: output_path:
description: 'file path to store results report (json, sarif)' description: "directory to store results report"
required: false required: false
payload_path: payload_path:
description: 'file path to store source internal representation in JSON format' description: "file path to store source internal representation in JSON format"
required: false required: false
queries: queries:
description: 'path to directory with queries (default "./assets/queries")' description: 'path to directory with queries (default "./assets/queries")'
required: false required: false
secrets_regexes_path:
description: "path to secrets regex rules configuration file"
required: false
libraries_path:
description: "path to directory with Rego libraries"
required: false
disable_full_descriptions:
description: "disable request for full descriptions and use default vulnerability descriptions"
required: false
disable_secrets:
description: "disable secrets detection"
required: false
type:
description: "case insensitive comma-separated list of platform types to scan (Ansible, AzureResourceManager, CloudFormation, Dockerfile, Kubernetes, OpenAPI, Terraform)"
required: false
verbose: verbose:
description: 'verbose scan' description: "verbose scan"
required: false
include_queries:
description: "comma separated list of queries ID's to include, cannot be provided with query exclusion flags"
required: false
bom:
description: "include bill of materials (BoM) in results output"
required: false
outputs: outputs:
results: results:
description: 'the result of KICS scan' description: "the result of KICS scan"
branding: branding:
icon: 'shield' icon: "shield"
color: 'green' color: "green"
runs: runs:
using: 'docker' using: node12
image: 'Dockerfile' main: dist/index.js
args:
- ${{ inputs.path }}
- ${{ inputs.ignore_on_exit }}
- ${{ inputs.fail_on }}
- ${{ inputs.timeout }}
- ${{ inputs.profiling }}
- ${{ inputs.config }}
- ${{ inputs.platform_type }}
- ${{ inputs.exclude_paths }}
- ${{ inputs.exclude_queries }}
- ${{ inputs.exclude_categories }}
- ${{ inputs.exclude_results }}
- ${{ inputs.output_formats }}
- ${{ inputs.output_path }}
- ${{ inputs.payload_path }}
- ${{ inputs.queries }}
- ${{ inputs.verbose }}

18472
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,38 +0,0 @@
#!/bin/ash
DATETIME="`date '+%H:%M'`"
if [ -z "$INPUT_PATH" ]
then
echo "${DATETIME} - ERR input path can't be empty"
exit 1
else
INPUT_PARAM="-p $INPUT_PATH"
fi
[[ ! -z "$INPUT_OUTPUT_PATH" ]] && OUTPUT_PATH_PARAM="-o $INPUT_OUTPUT_PATH"
[[ ! -z "$INPUT_PAYLOAD_PATH" ]] && PAYLOAD_PATH_PARAM="-d $INPUT_PAYLOAD_PATH"
[[ ! -z "$INPUT_CONFIG_PATH" ]] && CONFIG_PATH_PARAM="--config $INPUT_CONFIG_PATH"
[[ ! -z "$INPUT_EXCLUDE_PATHS" ]] && EXCLUDE_PATHS_PARAM="-e $INPUT_EXCLUDE_PATHS"
[[ ! -z "$INPUT_EXCLUDE_RESULTS" ]] && EXCLUDE_RESULTS_PARAM="-x $INPUT_EXCLUDE_RESULTS"
[[ ! -z "$INPUT_EXCLUDE_QUERIES" ]] && EXCLUDE_QUERIES_PARAM="--exclude-queries $INPUT_EXCLUDE_QUERIES"
[[ ! -z "$INPUT_EXCLUDE_CATEGORIES" ]] && EXCLUDE_CATEGORIES_PARAM="--exclude-categories $INPUT_EXCLUDE_CATEGORIES"
[[ ! -z "$INPUT_OUTPUT_FORMATS" ]] && OUTPUT_FORMATS_PARAM="--report-formats $INPUT_OUTPUT_FORMATS"
[[ ! -z "$INPUT_PLATFORM_TYPE" ]] && PLATFORM_TYPE_PARAM="--type $INPUT_PLATFORM_TYPE"
[[ ! -z "$INPUT_IGNORE_ON_EXIT" ]] && IGNORE_ON_EXIT_PARAM="--ignore-on-exit $INPUT_IGNORE_ON_EXIT"
[[ ! -z "$INPUT_FAIL_ON" ]] && FAIL_ON_PARAM="--fail-on $INPUT_FAIL_ON"
[[ ! -z "$INPUT_TIMEOUT" ]] && TIMEOUT_PARAM="--timeout $INPUT_TIMEOUT"
[[ ! -z "$INPUT_PROFILING" ]] && PROFILING_PARAM="--profiling $INPUT_PROFILING"
[[ ! -z "$INPUT_VERBOSE" ]] && VERBOSE_PARAM="-v"
if [ ! -z "$INPUT_QUERIES" ]
then
QUERIES_PARAM="-q $INPUT_QUERIES"
else
QUERIES_PARAM="-q /app/bin/assets/queries"
fi
cd $GITHUB_WORKSPACE
echo "${DATETIME} - INF : about to scan directory $INPUT_PATH"
echo "${DATETIME} - INF : kics command kics $INPUT_PARAM $OUTPUT_PATH_PARAM $OUTPUT_FORMATS_PARAM $PLATFORM_TYPE_PARAM $PAYLOAD_PATH_PARAM $CONFIG_PATH_PARAM $EXCLUDE_PATHS_PARAM $EXCLUDE_CATEGORIES_PARAM $EXCLUDE_RESULTS_PARAM $EXCLUDE_QUERIES_PARAM $QUERIES_PARAM $VERBOSE_PARAM $IGNORE_ON_EXIT_PARAM $FAIL_ON_PARAM $TIMEOUT_PARAM $PROFILING_PARAM"
/app/bin/kics scan --no-progress $INPUT_PARAM $OUTPUT_PATH_PARAM $OUTPUT_FORMATS_PARAM $PLATFORM_TYPE_PARAM $PAYLOAD_PATH_PARAM $CONFIG_PATH_PARAM $EXCLUDE_PATHS_PARAM $EXCLUDE_CATEGORIES_PARAM $EXCLUDE_RESULTS_PARAM $EXCLUDE_QUERIES_PARAM $QUERIES_PARAM $VERBOSE_PARAM $IGNORE_ON_EXIT_PARAM $FAIL_ON_PARAM $TIMEOUT_PARAM $PROFILING_PARAM

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

543
package-lock.json generated Normal file
View File

@ -0,0 +1,543 @@
{
"name": "kics-github-action",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "kics-github-action",
"version": "1.0.0",
"license": "GNU GENERAL PUBLIC LICENSE",
"dependencies": {
"@actions/core": "^1.6.0",
"@actions/exec": "^1.1.0",
"@actions/github": "^5.0.0",
"@actions/io": "^1.1.1",
"@actions/tool-cache": "^1.7.1",
"moment": "^2.29.1"
},
"devDependencies": {
"@vercel/ncc": "^0.31.1",
"prettier": "^2.4.1"
}
},
"node_modules/@actions/core": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
"integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
"dependencies": {
"@actions/http-client": "^1.0.11"
}
},
"node_modules/@actions/exec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz",
"integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/github": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz",
"integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==",
"dependencies": {
"@actions/http-client": "^1.0.11",
"@octokit/core": "^3.4.0",
"@octokit/plugin-paginate-rest": "^2.13.3",
"@octokit/plugin-rest-endpoint-methods": "^5.1.1"
}
},
"node_modules/@actions/http-client": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
"dependencies": {
"tunnel": "0.0.6"
}
},
"node_modules/@actions/io": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz",
"integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA=="
},
"node_modules/@actions/tool-cache": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.7.1.tgz",
"integrity": "sha512-y1xxxOhXaBUIUit3lhepmu/0xdgiTMpnZRLmVdtF0hTm521doi+MdRRRP62czHvM7wxH6epj4JPNJQ3iJpOrkQ==",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/http-client": "^1.0.8",
"@actions/io": "^1.1.1",
"semver": "^6.1.0",
"uuid": "^3.3.2"
}
},
"node_modules/@actions/tool-cache/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"dependencies": {
"@octokit/types": "^6.0.3"
}
},
"node_modules/@octokit/core": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
"dependencies": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.0",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"dependencies": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"dependencies": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/openapi-types": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz",
"integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA=="
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz",
"integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==",
"dependencies": {
"@octokit/types": "^6.34.0"
},
"peerDependencies": {
"@octokit/core": ">=2"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "5.13.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz",
"integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==",
"dependencies": {
"@octokit/types": "^6.34.0",
"deprecation": "^2.3.1"
},
"peerDependencies": {
"@octokit/core": ">=3"
}
},
"node_modules/@octokit/request": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
"dependencies": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.1",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"dependencies": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"node_modules/@octokit/types": {
"version": "6.34.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz",
"integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==",
"dependencies": {
"@octokit/openapi-types": "^11.2.0"
}
},
"node_modules/@vercel/ncc": {
"version": "0.31.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.31.1.tgz",
"integrity": "sha512-g0FAxwdViI6UzsiVz5HssIHqjcPa1EHL6h+2dcJD893SoCJaGdqqgUF09xnMW6goWnnhbLvgiKlgJWrJa+7qYA==",
"dev": true,
"bin": {
"ncc": "dist/ncc/cli.js"
}
},
"node_modules/before-after-hook": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
},
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"engines": {
"node": "*"
}
},
"node_modules/node-fetch": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/prettier": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
"integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
},
"node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
},
"dependencies": {
"@actions/core": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
"integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
"requires": {
"@actions/http-client": "^1.0.11"
}
},
"@actions/exec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz",
"integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==",
"requires": {
"@actions/io": "^1.0.1"
}
},
"@actions/github": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz",
"integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==",
"requires": {
"@actions/http-client": "^1.0.11",
"@octokit/core": "^3.4.0",
"@octokit/plugin-paginate-rest": "^2.13.3",
"@octokit/plugin-rest-endpoint-methods": "^5.1.1"
}
},
"@actions/http-client": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
"requires": {
"tunnel": "0.0.6"
}
},
"@actions/io": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz",
"integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA=="
},
"@actions/tool-cache": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.7.1.tgz",
"integrity": "sha512-y1xxxOhXaBUIUit3lhepmu/0xdgiTMpnZRLmVdtF0hTm521doi+MdRRRP62czHvM7wxH6epj4JPNJQ3iJpOrkQ==",
"requires": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/http-client": "^1.0.8",
"@actions/io": "^1.1.1",
"semver": "^6.1.0",
"uuid": "^3.3.2"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
"@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"requires": {
"@octokit/types": "^6.0.3"
}
},
"@octokit/core": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
"requires": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.0",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"requires": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"requires": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/openapi-types": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz",
"integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA=="
},
"@octokit/plugin-paginate-rest": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz",
"integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==",
"requires": {
"@octokit/types": "^6.34.0"
}
},
"@octokit/plugin-rest-endpoint-methods": {
"version": "5.13.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz",
"integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==",
"requires": {
"@octokit/types": "^6.34.0",
"deprecation": "^2.3.1"
}
},
"@octokit/request": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
"requires": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.1",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"requires": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"@octokit/types": {
"version": "6.34.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz",
"integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==",
"requires": {
"@octokit/openapi-types": "^11.2.0"
}
},
"@vercel/ncc": {
"version": "0.31.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.31.1.tgz",
"integrity": "sha512-g0FAxwdViI6UzsiVz5HssIHqjcPa1EHL6h+2dcJD893SoCJaGdqqgUF09xnMW6goWnnhbLvgiKlgJWrJa+7qYA==",
"dev": true
},
"before-after-hook": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
},
"deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"node-fetch": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"prettier": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
"integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
"dev": true
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
}

33
package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "kics-github-action",
"version": "1.0.0",
"description": "[![License: GPL-3.0](https://img.shields.io/badge/License-GPL3.0-yellow.svg)](https://www.gnu.org/licenses) [![Latest Release](https://img.shields.io/github/v/release/checkmarx/kics-github-action)](https://github.com/checkmarx/kics-github-action/releases) [![Open Issues](https://img.shields.io/github/issues-raw/checkmarx/kics-github-action)](https://github.com/checkmarx/kics-github-action/issues)",
"main": "index.js",
"scripts": {
"build": "ncc build src/main.js",
"format": "prettier --write **/*.ts"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Checkmarx/kics-github-action.git"
},
"keywords": [],
"author": "",
"license": "GNU GENERAL PUBLIC LICENSE",
"bugs": {
"url": "https://github.com/Checkmarx/kics-github-action/issues"
},
"homepage": "https://github.com/Checkmarx/kics-github-action#readme",
"dependencies": {
"@actions/core": "^1.6.0",
"@actions/exec": "^1.1.0",
"@actions/github": "^5.0.0",
"@actions/io": "^1.1.1",
"@actions/tool-cache": "^1.7.1",
"moment": "^2.29.1"
},
"devDependencies": {
"@vercel/ncc": "^0.31.1",
"prettier": "^2.4.1"
}
}

38
src/annotator.js Normal file
View File

@ -0,0 +1,38 @@
const core = require("@actions/core");
function extractAnnotations(results) {
let annotations = [];
for (i in results.queries) {
let query = results.queries[i];
for (j in query.files) {
let file = query.files[j];
annotations.push({
file: file['file_name'],
startLine: file['line'],
endLine: file['line'],
severity: query['severity'],
queryName: query['query_name'],
description: query['description'],
});
}
}
return annotations;
}
function annotateChangesWithResults(results) {
const annotations = extractAnnotations(results);
annotations.forEach(annotation => {
core.warning(annotation.description, {
title: `[${annotation.severity}] ${annotation.queryName}`,
startLine: annotation.startLine,
endLine: annotation.endLine,
file: annotation.file,
});
});
}
module.exports = {
annotateChangesWithResults
}

80
src/commenter.js Normal file
View File

@ -0,0 +1,80 @@
const moment = require('moment')
const kicsLogo = "https://user-images.githubusercontent.com/75368139/136991766-a4e5bc8b-63db-48f7-9384-740e9f15c9f6.png"
const severityOrder = ["HIGH", "MEDIUM", "LOW", "INFO", "TRACE"];
const severityIcons = {
"HIGH": "https://user-images.githubusercontent.com/23239410/92157087-97285600-ee32-11ea-988f-0aca12c4c126.png",
"MEDIUM": "https://user-images.githubusercontent.com/23239410/92157093-98598300-ee32-11ea-83d7-af52251a011b.png",
"LOW": "https://user-images.githubusercontent.com/23239410/92157091-98598300-ee32-11ea-8498-19bd7d62019b.png",
"INFO": "https://user-images.githubusercontent.com/75368139/137872145-b13b5200-6919-43c2-a49b-d3fdbbc20f63.png",
"TRACE": "https://user-images.githubusercontent.com/23239410/92157090-97c0ec80-ee32-11ea-9b2e-aa6b32b03d54.png",
}
const emptyIcon = "https://user-images.githubusercontent.com/75368139/137874724-5118ebc4-9769-4eb2-923d-e4ca479f747f.png"
function createComment(results) {
let message = "![kics-logo](" + kicsLogo + ")\n";
message += `\n**KICS version: ${results['kics_version']}**\n`
message += "<table>\n";
message += "<tr></tr>\n";
message += "<tr><td>\n\n";
message += "| | Category | Results |\n";
message += "| --- |--- | --- |\n";
let severityCounters = results['severity_counters']
for (let severity of severityOrder) {
if (severity in severityCounters) {
message += `| ![${severity}](${severityIcons[severity]}) | ${severity.toUpperCase()} | ${severityCounters[severity.toUpperCase()]} |\n`;
}
}
message += `| ![TOTAL](${emptyIcon}) | TOTAL | ${results['total_counter']} |`;
message += "\n\n</td><td>\n\n";
message += "| Metric | Values |\n";
message += "| --- | --- |\n";
message += `| Files scanned ![placeholder](${emptyIcon}) | ${results['files_scanned']}\n`;
message += `| Files parsed ![placeholder](${emptyIcon}) | ${results['files_parsed']}\n`;
message += `| Files failed to scan ![placeholder](${emptyIcon}) | ${results['files_failed_to_scan']}\n`;
message += `| Total executed queries ![placeholder](${emptyIcon}) | ${results['queries_total']}\n`;
message += `| Queries failed to execute ![placeholder](${emptyIcon}) | ${results['queries_failed_to_execute']}\n`;
message += `| Execution time ![placeholder](${emptyIcon}) | ${moment(results['end']).diff(moment(results['start']), 'seconds')}\n`;
message += "\n</td></tr>\n</table>\n\n";
return message;
}
async function postPRComment(results, repo, prNumber, octokit) {
const message = createComment(results);
const { data: comments } = await octokit.rest.issues.listComments({
...repo,
issue_number: prNumber,
});
const comment = comments.find((comment) => {
return (
comment.user.login === "github-actions[bot]" &&
comment.body.startsWith("![kics-logo](")
);
});
if (comment) {
await octokit.rest.issues.updateComment({
...repo,
comment_id: comment.id,
body: message
});
} else {
await octokit.rest.issues.createComment({
...repo,
issue_number: prNumber,
body: message
});
}
}
module.exports = {
postPRComment
};

93
src/install.js Normal file
View File

@ -0,0 +1,93 @@
const https = require('https')
const filepath = require('path');
const tc = require('@actions/tool-cache');
const core = require("@actions/core");
const os = require('os');
function getVersion(version) {
let path = ''
if (version == "latest") {
path = '/repos/checkmarx/kics/releases/latest'
} else {
path = '/repos/checkmarx/kics/releases/tags/' + version
}
const options = {
hostname: 'api.github.com',
port: 443,
path: path,
headers: {
'User-Agent': 'node.js'
},
method: 'GET'
}
return new Promise((resolve, reject) => {
const req = https.get(options, (resp) => {
console.log(`${options.method} https://${options.hostname}${options.path} ${resp.statusCode}`)
let rawData = '';
resp.on('data', (d) => {
rawData += d;
});
resp.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
} catch (e) {
reject(e);
}
});
})
req.on('error', (error) => {
reject(error);
})
})
}
function getReleaseInfo(release) {
const assets = release.assets || [];
const os = process.platform;
const arch = process.arch;
let targetAsset;
switch (os) {
case 'darwin':
targetAsset = assets.filter((asset) => asset.name.indexOf('darwin') !== -1 && asset.name.indexOf(arch) !== -1)[0];
break;
case 'linux':
targetAsset = assets.filter((asset) => asset.name.indexOf('linux') !== -1 && asset.name.indexOf(arch) !== -1)[0];
break;
case 'win32':
targetAsset = assets.filter((asset) => asset.name.indexOf('windows') !== -1 && asset.name.indexOf(arch) !== -1)[0];
break;
default:
targetAsset = { size: 0, browser_download_url: '' };
}
return {
binary: 'kics',
size: targetAsset.size,
browser_download_url: targetAsset.browser_download_url,
version: release.tag_name,
arch: arch
};
}
async function installKICS(kicsVersion) {
let release = {};
if (!kicsVersion || kicsVersion == "latest") {
release = await getVersion("latest");
} else {
release = await getVersion(kicsVersion);
}
const releaseInfo = getReleaseInfo(release)
let kicsPath = tc.find(releaseInfo.binary, releaseInfo.version, releaseInfo.arch);
if (!kicsPath) {
core.info(`Downloading ${releaseInfo.binary} ${releaseInfo.version} ${releaseInfo.arch}`);
const kicsDownloadPath = await tc.downloadTool(releaseInfo.browser_download_url);
const kicsExtractedFolder = await tc.extractTar(kicsDownloadPath, filepath.join(os.homedir(), 'kics', releaseInfo.version));
kicsPath = await tc.cacheDir(kicsExtractedFolder, 'kics', releaseInfo.version, releaseInfo.arch);
}
core.addPath(kicsPath);
}
module.exports = {
installKICS
}

110
src/main.js Normal file
View File

@ -0,0 +1,110 @@
const install = require("./install");
const commenter = require("./commenter");
const scanner = require("./scanner");
const annotator = require("./annotator");
const core = require("@actions/core");
const github = require("@actions/github");
const io = require("@actions/io");
const fs = require("fs");
const exitStatus = {
results: {
codes: {
HIGH: 50,
MEDIUM: 40,
LOW: 30,
INFO: 20,
},
isResultExitStatus: function (exitCode) {
for (const key in this.codes) {
if (this.codes[key] === exitCode) {
return true;
}
}
return false;
}
}
}
function setWorkflowStatus(statusCode) {
console.log(`KICS scan status code: ${statusCode}`);
if (statusCode === 0) {
return;
}
const ignoreOnExit = core.getInput('ignore_on_exit');
if (ignoreOnExit.toLowerCase() === 'all') {
console.log(`ignore_on_exit=all :: Ignoring exit code ${statusCode}`);
return;
}
if (ignoreOnExit.toLowerCase() === 'results') {
if (exitStatus.results.isResultExitStatus(statusCode)) {
console.log(`ignore_on_exit=results :: Ignoring exit code ${statusCode}`);
return;
}
}
if (ignoreOnExit.toLowerCase() === 'errors') {
if (!exitStatus.results.isResultExitStatus(statusCode)) {
console.log(`ignore_on_exit=errors :: Ignoring exit code ${statusCode}`);
return;
}
}
core.setFailed(`KICS scan failed with exit code ${statusCode}`);
}
function readJSON(filename) {
const rawdata = fs.readFileSync(filename);
const parsedJSON = JSON.parse(rawdata.toString());
return parsedJSON;
}
function cleanupOutput(resultsJSONFile) {
const outputFormats = core.getInput('output_formats');
if (!outputFormats.toLowerCase().includes('json') || core.getInput('output_path') === '') {
io.rmRF(resultsJSONFile);
}
}
async function main() {
console.log("Running KICS action...");
try {
const githubToken = core.getInput("token");
const octokit = github.getOctokit(githubToken);
let context = {};
let repo = '';
let prNumber = '';
if (github.context) {
context = github.context;
if (context.repo) {
repo = context.repo;
}
if (context.payload && context.payload.pull_request) {
prNumber = context.payload.pull_request.number;
}
}
await install.installKICS();
const scanResults = await scanner.scanWithKICS();
const parsedResults = readJSON(scanResults.resultsJSONFile);
if (core.getInput('enable_comments').toLocaleLowerCase() === "true") {
await commenter.postPRComment(parsedResults, repo, prNumber, octokit);
}
annotator.annotateChangesWithResults(parsedResults);
cleanupOutput(scanResults.resultsJSONFile);
setWorkflowStatus(scanResults.statusCode);
} catch (e) {
console.error(e);
core.setFailed(e.message);
}
}
main();

101
src/scanner.js Normal file
View File

@ -0,0 +1,101 @@
const exec = require('@actions/exec');
const core = require("@actions/core");
const filepath = require('path');
const kicsBinary = 'kics';
const kicsInput = {
path: { value_type: "list", flag: '--path', value: core.getInput('path') },
ignore_on_exit: { value_type: "list", flag: '--ignore-on-exit', value: core.getInput('ignore_on_exit') },
fail_on: { value_type: "list", flag: '--fail-on', value: core.getInput('fail_on') },
timeout: { value_type: "int", flag: '--timeout', value: core.getInput('timeout') },
profiling: { value_type: "list", flag: '--profiling', value: core.getInput('profiling') },
config_path: { value_type: "string", flag: '--config', value: core.getInput('config_path') },
payload_path: { value_type: "string", flag: '--payload-path', value: core.getInput('payload_path') },
exclude_paths: { value_type: "list", flag: '--exclude-paths', value: core.getInput('exclude_paths') },
exclude_queries: { value_type: "list", flag: '--exclude-queries', value: core.getInput('exclude_queries') },
exclude_categories: { value_type: "list", flag: '--exclude-categories', value: core.getInput('exclude_categories') },
exclude_results: { value_type: "list", flag: '--exclude-results', value: core.getInput('exclude_results') },
output_formats: { value_type: "list", flag: '--report-formats', value: core.getInput('output_formats') },
output_path: { value_type: "string", flag: '--output-path', value: core.getInput('output_path') },
queries: { value_type: "string", flag: '--queries-path', value: core.getInput('queries') },
verbose: { value_type: "bool", flag: '--verbose', value: core.getInput('verbose') },
secrets_regexes_path: { value_type: "string", flag: '--secrets-regexes-path', value: core.getInput('secrets_regexes_path') },
libraries_path: { value_type: "string", flag: '--libraries-path', value: core.getInput('libraries-path') },
disable_secrets: { value_type: "bool", flag: '--disable-secrets', value: core.getInput('disable_secrets') },
disable_full_descriptions: { value_type: "bool", flag: '--disable-full-descriptions', value: core.getInput('disable_full_descriptions') },
types: { value_type: "list", flag: '--types', value: core.getInput('types') },
bom: { value_type: "bool", flag: '--bom', value: core.getInput('bom') },
};
function addJSONReportFormat(cmdArgs) {
const outputFormats = core.getInput('output_formats');
if (outputFormats.toLowerCase().indexOf('json') == -1) {
cmdArgs.push('--report-formats');
cmdArgs.push('json');
}
}
function addKICSCmdArgs(cmdArgs) {
for (let input in kicsInput) {
if (kicsInput[input].value_type === 'string') {
if (kicsInput[input].value) {
cmdArgs.push(kicsInput[input].flag);
cmdArgs.push(kicsInput[input].value);
}
} else if (kicsInput[input].value_type === 'list') {
if (kicsInput[input].value) {
if (kicsInput[input].value.indexOf(',') > -1) {
kicsInput[input].value.split(',').forEach(value => {
cmdArgs.push(kicsInput[input].flag);
cmdArgs.push(value);
});
} else {
cmdArgs.push(kicsInput[input].flag);
cmdArgs.push(kicsInput[input].value);
}
}
} else if (kicsInput[input].value_type === 'bool') {
if (kicsInput[input].value) {
cmdArgs.push(kicsInput[input].flag);
}
} else if (kicsInput[input].value_type === 'int') {
if (kicsInput[input].value) {
cmdArgs.push(kicsInput[input].flag);
cmdArgs.push(kicsInput[input].value);
}
}
}
}
async function scanWithKICS() {
let resultsJSONFile;
if (!kicsInput.path.value) {
core.error('Path to scan is not set');
core.setFailed('Path to scan is not set');
}
let cmdArgs = [];
addKICSCmdArgs(cmdArgs);
// making sure results.json is always created
if (!cmdArgs.find(arg => arg == '--output-path')) {
cmdArgs.push('--output-path');
cmdArgs.push('./');
resultsJSONFile = './results.json';
} else {
let resultsDir = core.getInput('output_path');
resultsJSONFile = filepath.join(resultsDir, '/results.json');
}
addJSONReportFormat(cmdArgs);
exitCode = await exec.exec(`${kicsBinary} scan --no-progress ${cmdArgs.join(" ")}`, [], { ignoreReturnCode: true });
return {
statusCode: exitCode,
resultsJSONFile: resultsJSONFile
};
}
module.exports = {
scanWithKICS
};

21
test/samples/positive1.tf Normal file
View File

@ -0,0 +1,21 @@
resource "azurerm_resource_group" "positive1" {
name = "acceptanceTestResourceGroup1"
location = "West US"
}
resource "azurerm_sql_server" "positive2" {
name = "mysqlserver1"
resource_group_name = "acceptanceTestResourceGroup1"
location = "West US"
version = "12.0"
administrator_login = "4dm1n157r470r"
administrator_login_password = "4-v3ry-53cr37-p455w0rd"
}
resource "azurerm_sql_active_directory_administrator" "positive3" {
server_name = "mysqlserver2"
resource_group_name = "acceptanceTestResourceGroup1"
login = "sqladmin"
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
}

13
test/samples/positive2.tf Normal file
View File

@ -0,0 +1,13 @@
resource "azurerm_resource_group" "positive1" {
name = "resourceGroup1"
location = "West US"
}
resource "azurerm_container_registry" "positive2" {
name = "containerRegistry1"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
sku = "Premium"
admin_enabled = true
georeplication_locations = ["East US", "West Europe"]
}