-
Notifications
You must be signed in to change notification settings - Fork 10
Add Semgrep static analysis workflow for create-github-app-token action detection #101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8f8cad7
315ef63
6172edb
ecec62a
1c276b4
1763ca7
60c1c81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| name: Semgrep static analysis | ||
| on: | ||
| pull_request: | ||
| jobs: | ||
| semgrep: | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| # User definable name of this GitHub Actions job. | ||
| name: semgrep-oss/scan | ||
| # If you are self-hosting, change the following `runs-on` value: | ||
| runs-on: ubuntu-latest | ||
| container: | ||
| # A Docker image with Semgrep installed. Do not change this. | ||
| image: semgrep/semgrep:1.152.0 | ||
| steps: | ||
| # Fetch project source with GitHub Actions Checkout. | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
|
|
||
| # Fetch org-wide custom Semgrep rules from the central repository. | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| repository: grafana/security-github-actions | ||
| ref: ${{ github.repository == 'grafana/security-github-actions' && (github.head_ref || github.ref_name) || '' }} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, the action is pinned but the content isn't. When the workflow runs in grafana/security-github-actions: When the workflow runs in any other repo (e.g. grafana/some-app): the condition is false, so
These points are even more painful if this workflow is ever used in an enforcing/block mode. It is a good idea to pin the ref to a release tag or commit for consuming repos. Then updates are intentional, you change the tag/SHA in the workflow (or in a shared template) when you want to roll out a new version. Additionally, a bad push to main does not automatically affect consumers until something explicitly updates that ref.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make sense. I can do this in a future PR with the config file in place |
||
| sparse-checkout: | | ||
| semgrep/custom-rules.yaml | ||
| semgrep/format-results.sh | ||
| path: security-github-actions | ||
| - id: semgrep | ||
| env: | ||
| GITHUB_REPOSITORY: ${{github.repository}} | ||
| GITHUB_BRANCH: ${{github.head_ref || github.ref_name}} | ||
| run: | | ||
| set +e | ||
| semgrep scan --error --json --config security-github-actions/semgrep/custom-rules.yaml > /tmp/semgrep-results.json | ||
| EXIT_CODE=$? | ||
| set -e | ||
| if [ $EXIT_CODE -eq 1 ]; then | ||
| echo "has_findings=true" >> "$GITHUB_OUTPUT" | ||
| { | ||
| echo 'SEMGREP_OUTPUT<<SEMGREP_EOF' | ||
| bash security-github-actions/semgrep/format-results.sh /tmp/semgrep-results.json | ||
| echo 'SEMGREP_EOF' | ||
| } >> "$GITHUB_ENV" | ||
| fi | ||
|
|
||
| if [ $EXIT_CODE -gt 1 ]; then | ||
| echo "::error::Semgrep run encounters an error" | ||
| cat /tmp/semgrep-results.json | ||
| exit 1 | ||
| fi | ||
|
|
||
| HIGH_CRITICAL=$(jq '[.results[] | select(.extra.severity == "HIGH" or .extra.severity == "CRITICAL")] | length' /tmp/semgrep-results.json) | ||
| if [ "$HIGH_CRITICAL" -gt 0 ]; then | ||
| echo "has_high_critical=true" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - if: steps.semgrep.outputs.has_findings == 'true' | ||
|
|
||
| uses: int128/comment-action@66317511bc86c47bd51e03059040e8a460a167b8 | ||
| with: | ||
| update-if-exists: recreate | ||
| post: | | ||
| ${{ env.SEMGREP_OUTPUT }} | ||
|
|
||
|
Comment on lines
+58
to
+64
|
||
| - if: steps.semgrep.outputs.has_high_critical == 'true' | ||
| run: | | ||
| echo "::error::Semgrep found HIGH or CRITICAL severity findings." | ||
| exit 1 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| rules: | ||
| - id: deny-actions-create-github-app-token | ||
| patterns: | ||
| - pattern-regex: "uses:\\s*actions/create-github-app-token" | ||
| paths: | ||
| include: | ||
| - "*.yaml" | ||
| - "*.yml" | ||
| message: > | ||
| Do not use actions/create-github-app-token. Use the organization's | ||
| approved [alternative for generating GitHub App tokens](https://enghub.grafana-ops.net/docs/default/component/deployment-tools/platform/vault/github-app-token-broker-migration-guide/). | ||
| languages: [generic] | ||
| severity: LOW |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #!/usr/bin/env bash | ||
| # Format semgrep JSON results into a GitHub-flavored markdown comment. | ||
| set -euo pipefail | ||
|
|
||
| INPUT_FILE="$1" | ||
|
|
||
| RESULTS_COUNT=$(jq '.results | length' "$INPUT_FILE") | ||
|
|
||
| if [ "$RESULTS_COUNT" -eq 0 ]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "## Semgrep Findings" | ||
| echo "" | ||
| echo "**${RESULTS_COUNT}** finding(s) detected." | ||
| echo "" | ||
| echo "| Severity | Rule | File | Message |" | ||
| echo "|----------|------|------|---------|" | ||
|
|
||
| jq -r --arg repo "$GITHUB_REPOSITORY" --arg sha "$GITHUB_SHA" '.results[] | { | ||
| sev: .extra.severity, | ||
| rule: (.check_id | split(".")[-1]), | ||
| path: .path, | ||
| line: .start.line, | ||
| msg: (.extra.message | gsub("\n"; " ") | ltrimstr(" ") | rtrimstr(" ") | gsub("\\|"; "\\|") | gsub("`"; "\\`")) | ||
| } | { | ||
| icon: (if .sev == "CRITICAL" then "🔴" | ||
| elif .sev == "HIGH" then "🟠" | ||
| elif .sev == "MEDIUM" then "🟡" | ||
| elif .sev == "LOW" then "🔵" | ||
| elif .sev == "INFO" then "⚪" | ||
| else "⚪" end), | ||
| sev: .sev, | ||
| rule: .rule, | ||
| path: .path, | ||
| line: .line, | ||
| msg: .msg | ||
| } | "| \(.icon) \(.sev) | `\(.rule)` | [`\(.path):\(.line)`](https://github.com/\($repo)/blob/\($sha)/\(.path)#L\(.line)) | \(.msg) |"' "$INPUT_FILE" |
Uh oh!
There was an error while loading. Please reload this page.