This Action adds more awareness, and optionally fails a pull request status check, when a secret scanning alert is introduced as part of a pull request. This makes it harder for peer reviewers to miss the alert and makes it easier to enforce that the alert is resolved before the pull request is merged (when combined with repository rulesets).
This Action is also helpful in increasing visibility for secrets that are detected with secret scanning, but are not yet supported with push protection, or where push protection has been bypassed.
Note
When running the Action with the python
runtime, the Action will also provide a summary of the secrets introduced in the pull request title, description, comments, review, and review comments.
For private and internal repositories, you must enable GitHub Advanced Security.
The Action adds a Warning
annotation to any file in the pull request that has introduced a secret (based on the secret scanning alert's initial commit):
Setting the workflow FailOnAlert configuration value to true
will change those Warnings
into Errors
:
By adding Error
annotations, new secret alerts will fail the workflow's status check, which provides a "trust, but verify" approach to secret scanning:
The Action summarizes all secrets introduced in the pull request in the workflow run summary:
By default, when any secrets are found the Action will also add a comment to the pull request with a summary of the secrets introduced in the pull request:
When running the Action with the python
runtime option, the Action will also provide a summary of the secrets introduced in the pull request as a step output variable, alerts
. You can access this step output in subsequent steps in your workflow for any further processing that you would like to perform.
Note
The alerts
step output does NOT include secret values.
An example of how to access this step output in your Actions workflow is shown below:
[...]
- name: 'Secret Scanning Review Action'
uses: advanced-security/secret-scanning-review-action@main
id: secret-alert-check
with:
token: ${{ steps.app-token.outputs.token }}
runtime: 'python'
- name: 'Log alert metadata'
if: always()
run: |
echo ${{ steps.secret-alert-check.outputs.alerts }}
The alerts
variable is set to a JSON array with the following fields for each alert detected in the PR:
number
: The ID of the alertsecret_type
: The type of secret detectedpush_protection_bypassed
: Whether the alert was introduced in a commit that bypassed push protectionpush_protection_bypassed_by
: The user who bypassed push protectionstate
: The state of the alertresolution
: The resolution of the alerthtml_url
: The URL to the alert in the GitHub UI
An example of the alerts
step output variable is shown below, where two different secrets were introduced in a PR:
[
{
"number": 68,
"secret_type": "hardcoded_password",
"push_protection_bypassed": false,
"push_protection_bypassed_by": null,
"state": "open",
"resolution": null,
"html_url": "https://github.com/callmegreg-demo-org/ss-demo-repo/security/secret-scanning/68"
},
{
"number": 67,
"secret_type": "hardcoded_password",
"push_protection_bypassed": true,
"push_protection_bypassed_by": {
"login": "CallMeGreg",
"id": 110078080,
"node_id": "U_kgDOBo-ogA",
"avatar_url": "https://avatars.githubusercontent.com/u/110078080?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/CallMeGreg",
"html_url": "https://github.com/CallMeGreg",
"followers_url": "https://api.github.com/users/CallMeGreg/followers",
"following_url": "https://api.github.com/users/CallMeGreg/following{/other_user}",
"gists_url": "https://api.github.com/users/CallMeGreg/gists{/gist_id}",
"starred_url": "https://api.github.com/users/CallMeGreg/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/CallMeGreg/subscriptions",
"organizations_url": "https://api.github.com/users/CallMeGreg/orgs",
"repos_url": "https://api.github.com/users/CallMeGreg/repos",
"events_url": "https://api.github.com/users/CallMeGreg/events{/privacy}",
"received_events_url": "https://api.github.com/users/CallMeGreg/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": true
},
"state": "resolved",
"resolution": "false_positive",
"html_url": "https://github.com/callmegreg-demo-org/ss-demo-repo/security/secret-scanning/67"
}
]
-
To be clear, this Action will surface secret scanning alerts to anyone with
Read
access to a repository. This level of visibility is consistent with the access needed to see any raw secrets already commited to the repository's commit history. -
By default, only users with the repository
Admin
role, users with the organizationSecurity manager
role, organization owners, and the committer of the secret, will be able to dismiss the alert. -
If you do wish to give broader access to secret scanning alerts in the repository you might consider a custom repository role configuration. With a custom role you can choose to grant
View secret scanning results
orDismiss or reopen secret scanning results
on top of any of the base repository roles.
REQUIRED A GitHub Access Token
- Classic Tokens
repo
scope. For public repositories, you may instead use thepublic_repo
+security_events
scopes.
- Fine-grained personal access token permissions
- Read-Only - Secret Scanning Alerts
- Write - Pull requests.
- (
disable-pr-comment: true
) Read-Only - Pull requests. Not required for public repositories.
- (
NOTE:
- Unfortunately we cannot currently utilize the built in Actions GITHUB_TOKEN due to ommitted permissions on the
secret-scanning
API. Therefore you must generate a token (PAT or GitHub App) with these permissions, add the token as a secret in your repository, and assign the secret to the workflow parameter. See Also: Granting additional permissions - It is worth noting this token will have
sensitive
data access to return a list of plain text secrets that have been detected in your organization/repository. At this point, a detected secret also implies anyone with read repository access would provide the same level of access to the leaked secret and therefore should be considered compromised.
OPTIONAL If provided, will fail the action workflow via non-zero exit code if a matching secret scanning alert is found. Default 'false'
.
OPTIONAL If provided, will handle failure exit code / annotations as warnings if the alert is found and the alert is marked as closed (state: 'resolved'). Default 'false'
.
OPTIONAL If provided, will not put a comment on the Pull Request with a summary of detected secrets. Default 'false'
.
OPTIONAL If provided, will desingate the runtime that's used to run the action. Options are 'powershell'
or 'python'
. Default 'powershell'
.
OPTIONAL If provided, will set the http proxy for the python runtime. Default ""
. Example: "http://proxy.example.com:1234"
OPTIONAL If provided, will set the https proxy for the python runtime. Default ""
. Example: "http://proxy.example.com:5678"
OPTIONAL If provided, will set the ssl verification option for the python runtime. Default 'true'
.
Warning
Disabling SSL verification is NOT recommended for production environments. This option is provided for testing purposes only.
OPTIONAL If provided, will only process open alerts. Default 'false'
.
OPTIONAL If provided, will not put a summary of detected secrets in the workflow run summary. Default 'false'
.
Note
Please keep in mind that you need a GitHub Advanced Security license if you're running this action on private repositories.
- Add a new YAML workflow to your
.github/workflows
folder:
name: 'Secret Scanning Review'
on: [pull_request]
jobs:
secret-scanning-review:
runs-on: ubuntu-latest
steps:
- name: 'Secret Scanning Review Action'
uses: advanced-security/secret-scanning-review-action@v1
with:
token: ${{ secrets.SECRET_SCAN_REVIEW_GITHUB_TOKEN }}
fail-on-alert: true
fail-on-alert-exclude-closed: true
runtime: 'powershell' # or 'python'
- A GitHub composite action wrapping a PowerShell script.
sequenceDiagram
autonumber
participant Repo as Repository
participant PR as Pull Request
participant Action as Action Workflow
participant API_PR as pulls<br/><br/>REST API
participant API_SECRET as secret-scanning<br/><br/> REST API
Repo->>PR: Create/Update PR
PR->>Action: invoke `pull_request` workflow
Action->>API_PR: GET PR
Action->>API_PR: GET PR Commits
loop Commits
Action->>Action: Build PR Commit SHA list
end
Action->>API_SECRET: GET Secret Scanning Alerts
loop Secret Scanning Alerts
Action->>API_SECRET: GET Secret Scanning Alert List Locations
loop Secret Scanning Alert Locations
Action->>Action:Build List of Alert Initial Location SHAs that are<br/>contained in the PR SHA List (Step 5)
end
end
loop List of matching PR/Alerts
loop List of Locations for matching PR/Alerts
Action->>PR:Writes an Annotation to the message log<br/>associated with the file and line/col number.<br/>(Error/Warning based on FailOnAlert setting)
end
end
Note right of PR: Annotations are visible<br/>on the PR Files changed rich diff
Action->>PR:Writes summary to PR comment and log.<br/>Returns success/failure exit code based on FailOnAlert setting.
Note right of PR: Fail workflow check<br/>based on FailOnAlert setting.
- Implicit
- GITHUB_REPOSITORY - The owner / repository name.
- GITHUB_REF - PR merge branch refs/pull/:prNumber/merge
- Outputs
- GITHUB_STEP_SUMMARY - Markdown for each job so that it will be displayed on the summary page of a workflow run (unique for each step in a job)
- GitHub Dependencies
- GitHub REST APIs
- Powershell Dependencies
- Python Dependencies
requests
module
- Pulls
- https://docs.github.com/en/enterprise-cloud@latest/rest/pulls/pulls#get-a-pull-request
- https://docs.github.com/en/enterprise-cloud@latest/rest/pulls/pulls#list-commits-on-a-pull-request
- https://docs.github.com/en/rest/pulls/reviews?apiVersion=2022-11-28#list-reviews-for-a-pull-request
- https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#get-a-review-comment-for-a-pull-request
- Secret Scanning
- Comments
- https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#get-an-issue-comment
- https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#update-an-issue-comment
- https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#create-an-issue-comment
- https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#list-issue-comments
The primary difference is the underlying language and the dependencies that are required to be installed on the runner. The powershell
runtime is the default and is the most tested. The python
runtime is a newer addition for those who may not have powershell installed on their self-hosted runners.
The python
runtime also includes some additional configuration options that are not available in the powershell
runtime, and looks beyond just the pull request commits for secrets that were introduced in the pull request title, description, comments, review, and review comments.