Skip to content

Commit 36819d7

Browse files
committed
chore: validate full reachable history
1 parent 50f4a83 commit 36819d7

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

.github/workflows/validate.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
steps:
1818
- name: Check out the repository
1919
uses: actions/checkout@v6
20+
with:
21+
fetch-depth: 0
2022

2123
- name: Set up Node.js
2224
uses: actions/setup-node@v6

scripts/validate-public.mjs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ for (const file of publicContentFiles) {
148148

149149
try {
150150
const safeRoot = root.replaceAll('\\', '/');
151+
const git = (args, options = {}) => execFileSync(
152+
'git',
153+
['-c', `safe.directory=${safeRoot}`, '-C', root, ...args],
154+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], ...options },
155+
);
151156
const emailOutput = execFileSync(
152157
'git',
153158
['-c', `safe.directory=${safeRoot}`, '-C', root, 'log', '--format=%ae%n%ce'],
@@ -159,8 +164,31 @@ try {
159164
fail(`reachable Git history exposes a non-noreply email: ${email}`);
160165
}
161166
}
167+
168+
const reachableObjects = git(['rev-list', '--objects', '--all'])
169+
.split(/\r?\n/)
170+
.filter(Boolean)
171+
.map((line) => {
172+
const separator = line.indexOf(' ');
173+
return separator === -1
174+
? { objectId: line, path: '(no path)' }
175+
: { objectId: line.slice(0, separator), path: line.slice(separator + 1) };
176+
});
177+
const inspectedBlobs = new Set();
178+
for (const { objectId, path } of reachableObjects) {
179+
if (inspectedBlobs.has(objectId)) continue;
180+
if (git(['cat-file', '-t', objectId]).trim() !== 'blob') continue;
181+
inspectedBlobs.add(objectId);
182+
const blob = git(['cat-file', '-p', objectId], { maxBuffer: 10 * 1024 * 1024 });
183+
if (blob.includes('\0')) continue;
184+
for (const [pattern, label] of forbiddenPatterns) {
185+
if (pattern.test(blob)) {
186+
fail(`reachable Git blob ${objectId.slice(0, 12)} (${path}) contains a forbidden ${label} pattern`);
187+
}
188+
}
189+
}
162190
} catch (error) {
163-
fail(`could not inspect reachable Git metadata: ${error.message}`);
191+
fail(`could not inspect reachable Git metadata and blobs: ${error.message}`);
164192
}
165193

166194
const durationMs = Math.round(performance.now() - startedAt);

0 commit comments

Comments
 (0)