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
10 changes: 10 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
[allowlist]
description = "Exclude test fixtures, mock data, sample configs, and CI resources"
paths = [
# Go test files (commonly contain mock credentials)
'''.*_test\.go$''',

# JS/TS test files (.spec.ts, .test.tsx, etc.)
'''.*\.spec\.(ts|tsx|js|jsx)$''',
'''.*\.test\.(ts|tsx|js|jsx)$''',

# JS/TS test directories
'''__tests__/''',

# Go testdata directories
'''testdata/''',

Expand Down
203 changes: 172 additions & 31 deletions semgrep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ rules:
# SECTION 1: GENERIC SECRETS DETECTION — Applies to all file types
# ==========================================================================

- id: generic-hardcoded-secret
- id: generic-hardcoded-secret # pragma: allowlist secret
languages: [generic]
severity: ERROR
message: |
Expand All @@ -42,7 +42,7 @@ rules:

If this is a test fixture or example:
- Add comment: # nosemgrep: generic-hardcoded-secret
- Or use obviously fake values: password = "REPLACE_ME"
- Or use obviously fake values: password = "FAKE"
patterns:
- pattern-regex: |-
(?i)(password|passwd|pwd|secret|token|api[_-]?key|private[_-]?key)\s*[:=]+\s*["'][^"']{8,}["']
Expand Down Expand Up @@ -71,13 +71,13 @@ rules:
- Enable AWS CloudTrail for key usage monitoring

False Positive: If this is documentation/example, replace with:
AKIAIOSFODNN7EXAMPLE (official AWS example key)
AKIA...EXAMPLE (redacted AWS example key)
pattern-regex: 'AKIA[0-9A-Z]{16}'
metadata:
cwe: "CWE-798"
category: "security"

- id: generic-aws-secret-access-key
- id: generic-aws-secret-access-key # pragma: allowlist secret
languages: [generic]
severity: ERROR
message: |
Expand Down Expand Up @@ -361,7 +361,7 @@ rules:
category: "security"
note: "Not necessarily dangerous, but aggregated roles can accumulate unexpected permissions if selectors are too broad"

- id: k8s-rbac-secrets-cluster-access
- id: k8s-rbac-secrets-cluster-access # pragma: allowlist secret
languages: [yaml]
severity: WARNING
message: |
Expand Down Expand Up @@ -498,7 +498,7 @@ rules:
cwe: "CWE-653"
category: "security"

- id: k8s-secret-in-configmap
- id: k8s-secret-in-configmap # pragma: allowlist secret
languages: [yaml]
severity: ERROR
message: |
Expand Down Expand Up @@ -541,7 +541,7 @@ rules:
cwe: "CWE-522"
category: "security"

- id: yaml-hardcoded-secret
- id: yaml-hardcoded-secret # pragma: allowlist secret
languages: [yaml]
severity: WARNING
message: |
Expand All @@ -560,20 +560,62 @@ rules:
languages: [yaml]
severity: WARNING
message: |
Pod explicitly enables automountServiceAccountToken (CWE-200).
Workload explicitly enables automountServiceAccountToken (CWE-200).

When enabled, the ServiceAccount token is mounted into the pod at
/var/run/secrets/kubernetes.io/serviceaccount/token. If the pod is
compromised, the attacker can use this token to access the Kubernetes API.

Remediation: Set automountServiceAccountToken: false if the pod doesn't
need Kubernetes API access (most application pods don't).
patterns:
- pattern: |
automountServiceAccountToken: true
- pattern-inside: |
kind: Pod
...
pattern-either:
# Match Pod directly
- patterns:
- pattern: |
automountServiceAccountToken: true
- pattern-inside: |
kind: Pod
...
# Match Deployment, StatefulSet, DaemonSet, ReplicaSet pod template
- patterns:
- pattern: |
automountServiceAccountToken: true
- pattern-inside: |
kind: $KIND
...
spec:
...
template:
...
- metavariable-regex:
metavariable: $KIND
regex: (Deployment|StatefulSet|DaemonSet|ReplicaSet)
# Match Job pod template
- patterns:
- pattern: |
automountServiceAccountToken: true
- pattern-inside: |
kind: Job
...
spec:
...
template:
...
# Match CronJob pod template (nested under jobTemplate)
- patterns:
- pattern: |
automountServiceAccountToken: true
- pattern-inside: |
kind: CronJob
...
spec:
...
jobTemplate:
...
spec:
...
template:
...
metadata:
cwe: "CWE-200"
category: "security"
Expand All @@ -582,7 +624,7 @@ rules:
languages: [yaml]
severity: WARNING
message: |
Pod uses default ServiceAccount (CWE-250).
Workload uses default ServiceAccount (CWE-250).

The default ServiceAccount may have more permissions than needed.
Each workload should use a dedicated ServiceAccount with minimal RBAC
Expand All @@ -594,12 +636,14 @@ rules:
metadata:
name: my-app-sa
pattern-either:
# Match Pod directly — explicit default
- pattern: |
kind: Pod
...
spec:
...
serviceAccountName: default
# Match Pod directly — no SA specified
- patterns:
- pattern: |
kind: Pod
Expand All @@ -608,6 +652,90 @@ rules:
...
- pattern-not: |
serviceAccountName: $SA
# Match controllers — explicit default
- patterns:
- pattern: |
spec:
...
template:
...
spec:
...
serviceAccountName: default
- pattern-inside: |
kind: $KIND
...
- metavariable-regex:
metavariable: $KIND
regex: (Deployment|StatefulSet|DaemonSet|ReplicaSet|Job)
# Match controllers — no SA specified (implicit default)
- patterns:
- pattern: |
spec:
...
template:
...
spec:
...
- pattern-not: |
spec:
...
template:
...
spec:
...
serviceAccountName: $SA
- pattern-inside: |
kind: $KIND
...
- metavariable-regex:
metavariable: $KIND
regex: (Deployment|StatefulSet|DaemonSet|ReplicaSet|Job)
# Match CronJob — explicit default
- patterns:
- pattern: |
spec:
...
jobTemplate:
...
spec:
...
template:
...
spec:
...
serviceAccountName: default
- pattern-inside: |
kind: CronJob
...
# Match CronJob — no SA specified (implicit default)
- patterns:
- pattern: |
spec:
...
jobTemplate:
...
spec:
...
template:
...
spec:
...
- pattern-not: |
spec:
...
jobTemplate:
...
spec:
...
template:
...
spec:
...
serviceAccountName: $SA
- pattern-inside: |
kind: CronJob
...
metadata:
cwe: "CWE-250"
category: "security"
Expand All @@ -616,10 +744,10 @@ rules:
# SECTION 4: GITHUB ACTIONS SECURITY — Workflow files
# ==========================================================================

- id: github-actions-hardcoded-secret
- id: github-actions-hardcoded-secret # pragma: allowlist secret
languages: [yaml]
severity: ERROR
message: |
message: | # pragma: allowlist secret
Hardcoded secret in GitHub Actions workflow.

Security Risk: Secrets in workflows are visible in git history and to all collaborators.
Expand All @@ -645,6 +773,10 @@ rules:
patterns:
- pattern-not: ${{ secrets.$SECRET }}
- pattern-not: ${{ env.$ENV }}
paths:
include:
- "**/.github/workflows/*.yml"
- "**/.github/workflows/*.yaml"
metadata:
cwe: "CWE-798"
category: "security"
Expand Down Expand Up @@ -678,11 +810,11 @@ rules:
env:
TITLE: ${{ github.event.pull_request.title }}
patterns:
- pattern-regex: 'run:.*\$\{\{\s*github\.(head_ref|event\.(issue|pull_request|discussion|review|review_comment|comment)\.(title|body|head\.ref|head\.label)|event\.head_commit\.message|event\.commits\[\d+\]\.message)\s*\}\}'
- pattern-regex: 'run:\s*(?:[|>][-+]?\n(?:[ \t]+[^\n]*\n)*|[^\n]*)\$\{\{\s*github\.(head_ref|event\.(issue|pull_request|discussion|review|review_comment|comment)\.(title|body|head\.ref|head\.label)|event\.head_commit\.message|event\.commits\[\d+\]\.message)\s*\}\}'
paths:
include:
- ".github/workflows/*.yml"
- ".github/workflows/*.yaml"
- "**/.github/workflows/*.yml"
- "**/.github/workflows/*.yaml"
metadata:
cwe: "CWE-78"
owasp: "A03:2021 - Injection"
Expand Down Expand Up @@ -716,12 +848,11 @@ rules:
- If checkout is needed, use merge commit: refs/pull/${{ github.event.number }}/merge
- Add persist-credentials: false to limit token scope
patterns:
- pattern-regex: 'pull_request_target'
- pattern-regex: 'ref:\s*\$\{\{.*pull_request\.head\.(sha|ref)\s*\}\}'
- pattern-regex: 'pull_request_target[\s\S]*?uses:\s*actions/checkout@[^\n]*\n(\s+[\w-]+:.*\n)*\s+ref:\s*\$\{\{[^\}]*pull_request\.head\.(sha|ref)\s*\}\}'
paths:
include:
- ".github/workflows/*.yml"
- ".github/workflows/*.yaml"
- "**/.github/workflows/*.yml"
- "**/.github/workflows/*.yaml"
metadata:
cwe: "CWE-829"
category: "security"
Expand Down Expand Up @@ -920,13 +1051,23 @@ rules:
patterns:
- pattern-either:
- pattern: |
const $VAR = "password"
- pattern: |
const $VAR = "secret"
$VAR := $VALUE
- pattern: |
const $VAR = "token"
const $VAR = $VALUE
- pattern: |
var $VAR = "Bearer ..."
var $VAR = $VALUE
- metavariable-regex:
metavariable: $VAR
regex: (?i)(password|passwd|secret|token|api[_-]?key|private[_-]?key|credentials?)
- metavariable-regex:
metavariable: $VALUE
regex: '"[^"]{8,}"'
- pattern-not: |
$VAR := os.Getenv("...")
- pattern-not: |
var $VAR = os.Getenv("...")
- pattern-not: |
$VAR, $_ := os.LookupEnv("...")
metadata:
cwe: "CWE-798"
owasp: "A07:2021"
Expand Down Expand Up @@ -1673,7 +1814,7 @@ rules:
metadata:
category: "security"

- id: dockerfile-secret-in-env
- id: dockerfile-secret-in-env # pragma: allowlist secret
languages: [dockerfile]
severity: ERROR
message: |
Expand Down Expand Up @@ -1726,7 +1867,7 @@ rules:
Remediation: Always quote variables in file operations:
rm "$FILE" # correct
rm $FILE # dangerous
pattern-regex: '(rm|cp|mv|eval|chmod|chown|kill|pkill)\s+[^|;]*(?<!["''\\])\$[A-Za-z_][A-Za-z0-9_]*'
pattern-regex: '(rm|cp|mv|eval|chmod|chown|kill|pkill)\s+[^|;]*(?<!["''\\])\$(?:\{[A-Za-z_][A-Za-z0-9_]*(?:[:\-\+\?=][^}]*)?\}|[A-Za-z_][A-Za-z0-9_]*)'
metadata:
cwe: "CWE-78"
category: "security"
Loading