Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
This repository contains Semgrep rules developed and made public by @Saleor.

<!-- TOC -->
* [Saleor Semgrep Rules](#saleor-semgrep-rules)
* [Usage](#usage)
* [Rules](#rules)
* [Typescript](#typescript)
* [Contributing](#contributing)

- [Saleor Semgrep Rules](#saleor-semgrep-rules)
- [Usage](#usage)
- [Rules](#rules)
- [Typescript](#typescript)
- [Contributing](#contributing)

<!-- TOC -->

## Usage
Expand All @@ -31,17 +33,19 @@ semgrep -c /path-to-the-clone-semgrep-rules .
### Typescript

| ID | Impact | Confidence | Description |
|-------------------------------------------------------------------------------------------------------------------------|--------|------------|---------------------------------------------------|
| ----------------------------------------------------------------------------------------------------------------------- | ------ | ---------- | ------------------------------------------------- |
| [typescript.lang.security.audit.timing-attack-comparison](typescript/lang/security/audit/timing-attack-comparison.yaml) | HIGH | LOW | Checks comparisons against secrets are time-safe. |

### YAML

| ID | Impact | Confidence | Description |
|-----------------------------------------------------------------------------------------------------------------------------|--------|------------|----------------------------------------------------------------------------------------------------|
| [yaml.github-actions.security.audit.shell-script-injection](yaml/github-actions/security/audit/shell-script-injection.yaml) | HIGH | HIGH | Ensures no string interpolations (`${{ ... }}`) are present inside `run` blocks of GitHub Actions. |
| ID | Impact | Confidence | Description |
| ------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| [yaml.github-actions.security.audit.shell-script-injection](yaml/github-actions/security/audit/shell-script-injection.yaml) | HIGH | HIGH | Ensures no string interpolations (`${{ ... }}`) are present inside `run` blocks of GitHub Actions. |
| [yaml.github-actions.security.audit.secrets-without-environment](yaml/github-actions/security/audit/secrets-without-environment.yaml) | HIGH | HIGH | Matches GitHub Workflows that use secrets (other than GITHUB_TOKEN) without providing a GitHub Environment (`environment` keyword). |

## Contributing

Refer to our guidelines:

- [CONTRIBUTING.md](CONTRIBUTING.md)
- [CODE_OF_CONDUCT.md](https://github.com/saleor/.github/blob/main/CODE_OF_CONDUCT.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- env:
# ruleid: secrets-without-environment-in-env-block
foo: ${{ secrets.PROD_API_KEY }}
run: |
echo "$foo"
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
foo1: bar
# ruleid: secrets-without-environment-in-env-block
foo: "${{ secrets.PROD_API_KEY }}"
foo2: bar
run: |
echo "$foo"
---
name: CI

on:
push:
branches: [main]

# Test surrounded by other jobs
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
deploy:
runs-on: ubuntu-latest
steps:
- name: do something
env:
# ruleid: secrets-without-environment-in-env-block
foo: ${{ secrets.PROD_API_KEY }}
run: |
echo "$foo"
finalize:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
# Shouldn't match when using GITHUB_TOKEN
# ok: secrets-without-environment-in-env-block
run: echo "${{ secrets.GITHUB_TOKEN }}"
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
environment: my-env
steps:
- if: ${{ true }}
env:
# Shouldn't match when an environment is used
# ok: secrets-without-environment-in-with-block
foo: ${{ secrets.PROD_API_KEY }}
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
# Should match when passing a secret to 'with' block
# ruleid: secrets-without-environment-in-with-block
token: ${{ secrets.MY_TOKEN }}
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
# Test with quoted secret + surrounded by other keys
with:
foo1: bar
# ruleid: secrets-without-environment-in-with-block
token: "${{ secrets.MY_TOKEN }}"
foo2: bar
---
name: CI

on:
push:
branches: [main]

# Test surrounded by other jobs
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
deploy:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
# ruleid: secrets-without-environment-in-with-block
token: "${{ secrets.MY_TOKEN }}"
finalize:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
# Shouldn't match when using GITHUB_TOKEN
# ok: secrets-without-environment-in-with-block
token: ${{ secrets.GITHUB_TOKEN }}
---
name: CI

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
environment: my-env
steps:
- if: ${{ true }}
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
# Shouldn't match when an environment is used
# ok: secrets-without-environment-in-with-block
token: ${{ secrets.PROD_API_KEY }}
---
name: CI

on:
push:
branches: [main]

jobs:
reusable-workflow:
uses: saleor/foo
with:
# Environments aren't supported in reusable workflows
# as per https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows
# ok: secrets-without-environment-in-with-block
token: ${{ secrets.PROD_API_KEY }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# NOTE: this rule assumes ${{ secrets.SECRET }} is NEVER passed inside 'run' blocks
# Meaning the rule ./shell-script-injection.yaml is being used & respected.
rules:
- id: secrets-without-environment-in-env-block
message: >
This GitHub Actions workflow uses secrets but does not configure a job-level
environment. Secrets should be scoped to a GitHub Environment to enforce
protection rules (reviewers, deployment gates, etc) and to reduce blast radius.
severity: WARNING
languages: [yaml]
metadata:
category: security
technology: github-actions
cwe: "CWE-522: Insufficiently Protected Credentials"
likelihood: MEDIUM
confidence: HIGH
impact: HIGH

patterns:
- pattern-inside: |
steps: [...]
- pattern-inside: |
env: ...
...
- pattern: |
env: $X
- metavariable-pattern:
language: generic
metavariable: $X
patterns:
- pattern: "${{ secrets.$SECRET }}"
# GITHUB_TOKEN can be OK without environment as it's a dynamic secret
- pattern-not: "${{ secrets.GITHUB_TOKEN }}"
# Exclude jobs that properly define an environment
- pattern-not-inside: |
jobs:
...
$JOB:
...
environment:
...
- focus-metavariable: $SECRET
- id: secrets-without-environment-in-with-block
message: >
This GitHub Actions workflow uses secrets but does not configure a job-level
environment. Secrets should be scoped to a GitHub Environment to enforce
protection rules (reviewers, deployment gates, etc) and to reduce blast radius.
severity: WARNING
languages: [yaml]
metadata:
category: security
technology: github-actions
cwe: "CWE-522: Insufficiently Protected Credentials"
confidence: medium

patterns:
- pattern-inside: |
steps: [...]
- pattern-inside: |
with: ...
...
- pattern: |
with: $X
- metavariable-pattern:
language: generic
metavariable: $X
patterns:
- pattern: "${{ secrets.$SECRET }}"
- pattern-not: "${{ secrets.GITHUB_TOKEN }}"
# GITHUB_TOKEN can be OK without environment as it's a dynamic secret
- pattern-not-inside: |
jobs:
...
$JOB:
...
environment:
...
- focus-metavariable: $SECRET