Skip to content

Commit 3de9600

Browse files
Test Gitleaks workflow
1 parent 2f1a06a commit 3de9600

File tree

4 files changed

+174
-12
lines changed

4 files changed

+174
-12
lines changed

.github/docs/gitleaks-response.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Gitleaks Response Guide
2+
3+
When this workflow comments on your pull request, it means Gitleaks spotted something that looks like a credential. The build stays green, but secrets must be handled quickly and carefully.
4+
5+
## Quick Checklist
6+
7+
1. Stop merging the pull request until the investigation is complete.
8+
2. Open the PR comment or downloaded `gitleaks-report.json` artifact to review the redacted findings.
9+
3. Confirm whether each finding is a real secret or a false positive.
10+
4. Follow the appropriate section below and leave a short update on the PR comment.
11+
12+
## If the Secret Is Real
13+
14+
- **Rotate / revoke the credential immediately.** Use the relevant provider console or contact the owner of the secret.
15+
- **Purge the secret from Git history.** Remove it locally (including from previous commits) and force-push a clean branch.
16+
- Prefer [`git filter-repo`](https://github.com/newren/git-filter-repo) (or `git filter-branch` as a fallback) to rewrite history.
17+
- After rewriting history, regenerate the artifact (`git commit --amend` or new commit) and push with `--force-with-lease`.
18+
- **Document replacements.** Update `.env.example` or secrets management notes so others know the new credential.
19+
- **Confirm the fix.** Run `gitleaks detect --redact` locally to be sure the repository is clean before merging.
20+
- **Update the PR comment.** Reply to the workflow comment summarizing what was rotated and how the history was cleaned (no need to paste secrets).
21+
22+
## If It Is a False Positive
23+
24+
- **Verify carefully.** Make sure the redacted value truly is benign (example: test data, dummy keys, or hashed values).
25+
- **Mask the pattern going forward.** Add a rule or `allowlist` entry in your repository-level `.gitleaks.toml` or configuration file, and commit that change with a note explaining the rationale.
26+
- **Re-run locally.** Validate that `gitleaks detect --redact` reports no findings after the rule is added.
27+
- **Reply on the PR.** Note that the finding is a false positive and link to the configuration change.
28+
29+
## Need Help?
30+
31+
- Mention `@CivicTechWR/organizers` in the pull request comment if you need support rotating credentials or cleaning history.
32+
- For high-impact secrets (production credentials, user data access), escalate immediately in the organizers' channel or via the documented security contact.
33+
34+
Keeping secrets out of Git protects our community projects. Thank you for responding quickly when Gitleaks speaks up!

.github/workflows/gitleaks.yml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
name: Gitleaks Scan
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
permissions:
9+
actions: write
10+
contents: read
11+
pull-requests: write
12+
13+
jobs:
14+
scan:
15+
name: Scan for Leaked Secrets
16+
runs-on: ubuntu-latest
17+
env:
18+
RESPONSE_GUIDE_URL: https://github.com/CivicTechWR/.github/blob/main/docs/gitleaks-response.md
19+
steps:
20+
- name: Check out code
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
25+
- name: Run Gitleaks (redacted)
26+
id: gitleaks
27+
continue-on-error: true
28+
uses: gitleaks/gitleaks-action@v2
29+
with:
30+
args: >-
31+
detect --source . --no-banner --redact --report-format json --report-path gitleaks-report.json
32+
env:
33+
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
34+
35+
- name: Summarize findings
36+
id: summarize
37+
run: |
38+
if [ ! -f gitleaks-report.json ]; then
39+
echo "[]" > gitleaks-report.json
40+
fi
41+
42+
count=$(jq 'length' gitleaks-report.json 2>/dev/null || echo 0)
43+
44+
if [ "$count" -gt 0 ]; then
45+
echo "found=true" >> "$GITHUB_OUTPUT"
46+
echo "count=$count" >> "$GITHUB_OUTPUT"
47+
echo "::warning::Gitleaks detected ${count} potential secret(s)."
48+
else
49+
echo "found=false" >> "$GITHUB_OUTPUT"
50+
echo "count=0" >> "$GITHUB_OUTPUT"
51+
echo "::notice::Gitleaks found no potential secrets."
52+
fi
53+
54+
- name: Note scan issues
55+
if: ${{ steps.gitleaks.outcome == 'failure' && steps.summarize.outputs.found == 'false' }}
56+
run: |
57+
echo "::warning::Gitleaks scan ended with an error before producing findings. Review the action logs."
58+
59+
- name: Add pull request comment
60+
if: ${{ steps.summarize.outputs.found == 'true' && github.event_name == 'pull_request' }}
61+
uses: actions/github-script@v7
62+
env:
63+
LEAK_COUNT: ${{ steps.summarize.outputs.count }}
64+
with:
65+
script: |
66+
const fs = require('fs');
67+
const path = 'gitleaks-report.json';
68+
const responseGuide = process.env.RESPONSE_GUIDE_URL;
69+
const findings = JSON.parse(fs.readFileSync(path, 'utf8'));
70+
71+
if (!Array.isArray(findings) || findings.length === 0) {
72+
return;
73+
}
74+
75+
const lines = findings.slice(0, 10).map((finding) => {
76+
const file = finding.file ? `\`${finding.file}\`` : 'unknown file';
77+
const line = finding.startLine ? ` (line ${finding.startLine})` : '';
78+
const rule = finding.ruleId || finding.rule || 'potential secret';
79+
return `- ${file}${line} — ${rule}`;
80+
}).join('\n');
81+
82+
const remainder = findings.length > 10
83+
? `\n\n…and ${findings.length - 10} more finding${findings.length - 10 === 1 ? '' : 's'} in the attached report.`
84+
: '';
85+
86+
const body = [
87+
`@CivicTechWR/organizers Gitleaks flagged **${process.env.LEAK_COUNT}** potential secret${findings.length === 1 ? '' : 's'} in this pull request.`,
88+
'',
89+
`Please review the [Gitleaks response guide](${responseGuide}) for next steps.`,
90+
'',
91+
lines,
92+
remainder,
93+
'',
94+
'_Secret values are redacted by the scanner. Follow the guide before merging._'
95+
].filter(Boolean).join('\n');
96+
97+
await github.rest.issues.createComment({
98+
owner: context.repo.owner,
99+
repo: context.repo.repo,
100+
issue_number: context.issue.number,
101+
body,
102+
});
103+
104+
- name: Upload redacted report
105+
if: ${{ steps.summarize.outputs.found == 'true' }}
106+
uses: actions/upload-artifact@v4
107+
with:
108+
name: gitleaks-report
109+
path: gitleaks-report.json
110+
retention-days: 7
111+
112+
- name: Record scan summary
113+
if: ${{ always() }}
114+
env:
115+
LEAK_COUNT: ${{ steps.summarize.outputs.count }}
116+
HAS_FINDINGS: ${{ steps.summarize.outputs.found }}
117+
run: |
118+
if [ "$HAS_FINDINGS" = "true" ]; then
119+
{
120+
echo "## Gitleaks Findings"
121+
echo ""
122+
echo "Potential secrets detected: $LEAK_COUNT"
123+
echo "Report: gitleaks-report.json (uploaded as artifact when available)"
124+
echo "Guide: $RESPONSE_GUIDE_URL"
125+
} >> "$GITHUB_STEP_SUMMARY"
126+
else
127+
{
128+
echo "## Gitleaks Findings"
129+
echo ""
130+
echo "No potential secrets detected."
131+
} >> "$GITHUB_STEP_SUMMARY"
132+
fi

PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
- [ ] Privacy and data protection standards are maintained
6161
- [ ] Input validation and sanitization implemented
6262
- [ ] Security best practices followed
63+
- [ ] Responded to any Gitleaks comment and followed the [Gitleaks Response Guide](https://github.com/CivicTechWR/.github/blob/main/docs/gitleaks-response.md)
6364
- [ ] No new security vulnerabilities introduced
6465

6566
### Inclusivity & Accessibility

SECURITY.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ If you're using this template for your CTWR project and discover a security issu
5151
- **Review the [Security Guide](docs/SECURITY_GUIDE.md)** before starting development
5252
- **Use secure coding practices** throughout development
5353
- **Enable automated security scanning** in your repository
54+
- **Follow the [Gitleaks Response Guide](.github/docs/gitleaks-response.md)** whenever the secret scanning workflow reports a finding
5455
- **Conduct security reviews** before major releases
5556
- **Train team members** on civic tech security considerations
5657

@@ -98,22 +99,16 @@ When working with government partners:
9899
- **Privacy Commissioner of Canada** - Privacy law guidance
99100
- **PIPEDA** - Personal Information Protection and Electronic Documents Act
100101

101-
## Emergency Security Contact
102+
## Security Contacts
102103

103-
### Critical Security Issues
104+
### How to Reach Us
104105

105-
For critical security vulnerabilities that pose immediate risk:
106+
- **Primary channels:** email `civictechwr@gmail.com`, post in the private organizers channel, or send a direct message in the CTWR Slack workspace
107+
- **GitHub escalation:** mention `@CivicTechWR/organizers` on the relevant issue or pull request to notify the organizers team
106108

107-
**Contact:** [Emergency contact information]
108-
**Available:** 24/7 for critical issues
109-
**Response:** Immediate acknowledgment, resolution within 24 hours
109+
### Response Expectations
110110

111-
### Non-Critical Security Issues
112-
113-
For general security concerns or questions:
114-
115-
**Contact:** [Regular contact information]
116-
**Response Time:** Within 48 hours during business days
111+
The CivicTechWR security group is volunteer-run and does not maintain a formal SLA. We address reports as quickly as the team is available and will coordinate next steps once someone has acknowledged the issue. If a report seems urgent, use every channel above and add “URGENT” in the subject or message so we can prioritize it when a volunteer is online.
117112

118113
## Security Acknowledgments
119114

0 commit comments

Comments
 (0)