Skip to content

Commit c0596b3

Browse files
committed
Add secret scanning with gitleaks
1 parent 26af0b3 commit c0596b3

6 files changed

Lines changed: 86 additions & 0 deletions

File tree

.github/workflows/template-ci.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@ permissions:
1010
contents: read
1111

1212
jobs:
13+
secret-scan:
14+
name: Secret Scan
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Setup Node
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version-file: .nvmrc
26+
27+
- name: Setup Go
28+
uses: actions/setup-go@v5
29+
with:
30+
go-version: "1.25.1"
31+
32+
- name: Scan git history for secrets
33+
run: npm run check:secrets
34+
1335
workflow-lint:
1436
name: Workflow Lint
1537
runs-on: ubuntu-latest

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Use these commands before finishing work:
4949

5050
```bash
5151
npm run check:contract
52+
npm run check:secrets
5253
npm run check:workflows
5354
npm run check
5455
```

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ If Go is available locally, you can also lint GitHub Actions workflows:
7575
npm run check:workflows
7676
```
7777

78+
If Go is available locally, you can also scan tracked git content for secrets:
79+
80+
```bash
81+
npm run check:secrets
82+
```
83+
84+
For a pre-commit style check on staged content, run:
85+
86+
```bash
87+
npm run check:secrets -- --staged
88+
```
89+
7890
## Changing the API Contract
7991

8092
If you modify request or response shapes:

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ npm run dev:down
9696
npm run api:types
9797
npm run check:contract
9898
npm run check:images
99+
npm run check:secrets
99100
npm run check:workflows
100101
npm run check
101102
```
@@ -113,6 +114,8 @@ The root check runs:
113114

114115
`check:images` is separate and intended for environments where a Docker daemon is available.
115116

117+
`check:secrets` scans tracked git content with a pinned `gitleaks` version via Go.
118+
116119
`check:workflows` lints `.github/workflows/` with a pinned `actionlint` version via Go.
117120

118121
## Releases

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"check:contract": "node scripts/check-contract-drift.mjs",
1010
"check:images": "node scripts/check-docker-builds.mjs",
1111
"check:release-smoke": "node scripts/check-release-smoke.mjs",
12+
"check:secrets": "node scripts/check-secrets.mjs",
1213
"check:workflows": "node scripts/check-actionlint.mjs",
1314
"check": "node scripts/check.mjs"
1415
},

scripts/check-secrets.mjs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { spawnSync } from "node:child_process";
2+
import process from "node:process";
3+
4+
const GITLEAKS_VERSION = process.env.GITLEAKS_VERSION ?? "v8.30.1";
5+
const shell = process.platform === "win32";
6+
7+
function run(command, args, options = {}) {
8+
return spawnSync(command, args, {
9+
stdio: options.capture ? "pipe" : "inherit",
10+
encoding: options.capture ? "utf8" : undefined,
11+
shell,
12+
});
13+
}
14+
15+
const goVersion = run("go", ["version"], { capture: true });
16+
17+
if (goVersion.error || goVersion.status !== 0) {
18+
const details = [goVersion.stdout, goVersion.stderr].filter(Boolean).join("\n").trim();
19+
console.error(
20+
"Go is required to run secret scanning locally. Install Go or rely on the CI secret-scan job.",
21+
);
22+
23+
if (details) {
24+
console.error(details);
25+
}
26+
27+
process.exit(goVersion.status ?? 1);
28+
}
29+
30+
const args = [
31+
"run",
32+
`github.com/zricethezav/gitleaks/v8@${GITLEAKS_VERSION}`,
33+
"git",
34+
"--no-banner",
35+
"--redact",
36+
".",
37+
...process.argv.slice(2),
38+
];
39+
40+
const result = run("go", args);
41+
42+
if (result.error) {
43+
console.error(result.error.message);
44+
process.exit(1);
45+
}
46+
47+
process.exit(result.status ?? 1);

0 commit comments

Comments
 (0)