-
Notifications
You must be signed in to change notification settings - Fork 7.6k
143 lines (119 loc) · 5.77 KB
/
entropy-beauty-scan.yml
File metadata and controls
143 lines (119 loc) · 5.77 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
135
136
137
138
139
140
141
142
143
name: Entropy Beauty + TruffleHog Scan
on: [push, release, pull_request_target]
permissions:
contents: read
pull-requests: write
issues: write # must be at workflow level for push/merge events
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code (full history)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# Use shallow clone by default (much faster)
# Only use full history when necessary (push/release or when base commit is needed)
fetch-depth: ${{ github.event_name == 'pull_request_target' && 2 || 0 }}
- name: Cache pip manually
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-entropy-${{ hashFiles('.github/workflows/compute-entropy.py') }}
restore-keys: |
${{ runner.os }}-pip-entropy-
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.12'
- name: Install Python dependencies (only when needed)
run: |
python -m pip install --upgrade pip
# No extra packages needed — compute-entropy.py uses only stdlib
- name: Run TruffleHog
uses: trufflesecurity/trufflehog@6bd2d14f7a4bc1e569fa3550efa7ec632a4fa67b # main (as of March 2026)
with:
path: .
extra_args: --results=verified,unknown --filter-entropy=3.5 --json
- name: Compute mid-4 beauty entropy
run: python .github/workflows/compute-entropy.py
- name: Post summary comment (PR only)
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
uses: actions/github-script@v9
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
// Read TruffleHog output — it prints one JSON object per line (NDJSON)
let findings = [];
if (fs.existsSync('trufflehog.json')) {
try {
const lines = fs.readFileSync('trufflehog.json', 'utf8').trim().split('\n');
findings = lines.map(line => {
try { return JSON.parse(line); } catch(e) { return null; }
}).filter(Boolean);
} catch(e) {}
} else {
// Fallback: the action also logs to GITHUB_STEP_SUMMARY, but we use the file from the Python step
console.log("No trufflehog.json found, using empty findings");
}
const beauty = JSON.parse(fs.readFileSync('/tmp/beauty.json', 'utf8'));
let body = `## 🐷 TruffleHog + Entropy Beauty Scan\n\n`;
body += `**Average entropy of changed code:** ${beauty.average_entropy} bits/char\n`;
body += `**Verdict:** ${beauty.verdict}\n\n`;
if (beauty.files && beauty.files.length) {
body += `**Changed files entropy:**\n\`\`\`\n${beauty.files.join('\n')}\n\`\`\`\n\n`;
}
if (findings.length > 0) {
body += `⚠️ **TruffleHog found ${findings.length} potential issue(s)**\n`;
} else {
body += `✅ No secrets or suspicious high-entropy strings found.\n`;
}
body += `\n*Mid-4 beauty heuristic in action — powered by our entropy chats! 😊*`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
# ── Create issue on push ONLY if suspicious (entropy outside 4.3–5.1) ──
- name: Create issue on suspicious push
if: github.event_name == 'push' || github.event_name == 'release'
uses: actions/github-script@v9
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const beauty = JSON.parse(fs.readFileSync('/tmp/beauty.json', 'utf8'));
// Only create issue if it's NOT beautiful mid-4
if (beauty.average_entropy >= 4.3 && beauty.average_entropy <= 5.1) {
console.log("✅ Mid-4 beauty — no issue created");
return;
}
let findings = [];
if (fs.existsSync('trufflehog.json')) {
try {
const lines = fs.readFileSync('trufflehog.json', 'utf8').trim().split('\n');
findings = lines.map(line => {
try { return JSON.parse(line); } catch(e) { return null; }
}).filter(Boolean);
} catch(e) {}
}
let body = `**Average entropy:** ${beauty.average_entropy} bits/char\n\n`;
body += `**Verdict:** ${beauty.verdict}\n\n`;
if (beauty.files && beauty.files.length) {
body += `**Changed files:**\n\`\`\`\n${beauty.files.join('\n')}\n\`\`\`\n\n`;
}
if (findings.length > 0) {
body += `**TruffleHog found ${findings.length} potential issue(s)**\n`;
} else {
body += `✅ No secrets or suspicious high-entropy strings found.\n`;
}
body += `\n*Triggered by push to \`${context.sha}\` — mid-4 beauty heuristic*`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `🚨 Suspicious entropy detected in recent push (${beauty.average_entropy})`,
body: body,
labels: ['entropy', 'security', 'review-needed']
});
console.log("⚠️ Created issue because entropy was outside mid-4 range");