-
Notifications
You must be signed in to change notification settings - Fork 306
134 lines (110 loc) · 4.21 KB
/
required-secret-check.yml
File metadata and controls
134 lines (110 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
name: Secret Fields Check
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
secret-fields-check:
runs-on: ubuntu-22.04
timeout-minutes: 5
strategy:
matrix:
node-version: [22.x]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Check PR description
id: pr_desc
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const body = (pr?.body || "").toLowerCase();
const patterns = [
/-\s*\[x\]\s*required secret checkout/i,
/required secret checkout\s*:\s*true/i,
// The new checkbox you provided (checked)
/-\s*\[x\]\s*\*\*\s*Reviewed all field definitions\s*\*\*\s*for sensitive data\s*\(API keys, tokens, passwords, client secrets\)\s*and confirmed they use\s*`type:\s*'password'`/i
];
const skip = patterns.some(rx => rx.test(body));
core.setOutput("skip", skip ? "true" : "false");
console.log("Skip secret check:", skip);
- name: Run validate-secret-fields
id: list
if: steps.pr_desc.outputs.skip != 'true'
uses: actions/github-script@v7
with:
script: |
const { execSync } = require("child_process");
let raw = execSync("./bin/run validate-secret-fields", {
encoding: "utf8"
});
const parsed = JSON.parse(raw);
const findings = [];
for (const [destination, obj] of Object.entries(parsed)) {
if (Array.isArray(obj.settings) && obj.settings.length > 0) {
findings.push({
destination,
settings: obj.settings
});
}
}
core.setOutput("findings", JSON.stringify(findings));
console.log("Findings:", findings);
- name: Comment if secret fields found
if: steps.pr_desc.outputs.skip != 'true'
uses: actions/github-script@v7
with:
findings: ${{ steps.list.outputs.findings }}
script: |
const findings = JSON.parse(core.getInput("findings") || "[]");
// If NO secrets found → exit quietly and succeed
if (findings.length === 0) {
console.log("No secret fields found — skipping comment.");
return;
}
// Build comment markdown
const lines = findings
.map(f => `- **Destination**: ${f.destination}\n - Settings: ${f.settings.join(", ")}`)
.join("\n");
const body = `<!--SECRET_FIELDS_FOUND-->
### ⚠️ Secret Fields Detected
The following destinations require secret \`settings\` values that require review:
${lines}
This PR cannot be merged until these are removed or converted to secure secrets.
`;
// Find existing comment
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
const existing = comments.data.find(c =>
c.body?.includes("<!--SECRET_FIELDS_FOUND-->")
);
if (!existing) {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body
});
} else {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body
});
}
core.setFailed(
`Secret-like settings found in ${findings.length} destination(s).`
);