-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck-public-surface.mjs
More file actions
100 lines (91 loc) · 4.18 KB
/
Copy pathcheck-public-surface.mjs
File metadata and controls
100 lines (91 loc) · 4.18 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
#!/usr/bin/env node
import { execFileSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
const historyMode = process.argv.includes("--history");
const publicIdentity = {
name: "Shaelz",
email: "7167970+Shaelz@users.noreply.github.com",
};
const forbidden = [
{ label: "Windows workspace path", pattern: /[A-Za-z]:[\\/](?:CODE|Users|Documents|Projects)[\\/]/i },
{ label: "macOS/Linux user path", pattern: /\/Users\/[^/\s]+\/|\/home\/[^/\s]+\//i },
{ label: "Windows profile data path", pattern: /AppData[\\/]/i },
{ label: "private validation target name", pattern: new RegExp(["ger", "svelte"].join(""), "i") },
];
function git(args) {
return execFileSync("git", args, { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
}
function inspect(label, content, failures) {
for (const [index, line] of content.split(/\r?\n/).entries()) {
for (const rule of forbidden) {
if (rule.pattern.test(line)) failures.add(`${label}:${index + 1} ${rule.label}`);
}
}
}
const failures = new Set();
if (historyMode) {
const refs = git(["for-each-ref", "--format=%(refname)", "refs/heads", "refs/tags"]).trim().split(/\r?\n/).filter(Boolean);
for (const ref of refs) {
inspect(`ref:${ref}`, ref, failures);
if (git(["cat-file", "-t", ref]).trim() === "tag") {
const tag = git(["cat-file", "-p", ref]);
inspect(`tag:${ref}`, tag, failures);
const tagger = tag.match(/^tagger (.+) <(.+)> \d+ [+-]\d+$/m);
if (!tagger || tagger[1] !== publicIdentity.name || tagger[2] !== publicIdentity.email) {
failures.add(`tag:${ref} non-public tagger identity`);
}
}
}
if (refs.length === 0) throw new Error("history audit requires at least one branch or tag");
const commits = git(["rev-list", ...refs]).trim().split(/\r?\n/).filter(Boolean);
const inspectedBlobs = new Set();
for (const commit of commits) {
const metadata = git(["show", "-s", "--format=%an%x00%ae%x00%cn%x00%ce%x00%B", commit]).split("\0");
const [authorName, authorEmail, committerName, committerEmail, message = ""] = metadata;
if (authorName !== publicIdentity.name || authorEmail !== publicIdentity.email) {
failures.add(`${commit.slice(0, 12)}:metadata non-public author identity`);
}
if (committerName !== publicIdentity.name || committerEmail !== publicIdentity.email) {
failures.add(`${commit.slice(0, 12)}:metadata non-public committer identity`);
}
inspect(`${commit.slice(0, 12)}:message`, message, failures);
const entries = git(["ls-tree", "-r", "-z", commit]).split("\0").filter(Boolean);
for (const entry of entries) {
const match = entry.match(/^\d+\s+blob\s+([0-9a-f]+)\t(.*)$/s);
if (!match) continue;
const [, blob, path] = match;
inspect(`${commit.slice(0, 12)}:path`, path, failures);
if (inspectedBlobs.has(blob)) continue;
inspectedBlobs.add(blob);
try {
inspect(`${commit.slice(0, 12)}:${path}`, git(["cat-file", "-p", blob]), failures);
} catch {
// Binary and otherwise unreadable blobs are outside this text-surface check.
}
}
}
} else {
const files = git(["ls-files", "--cached", "--others", "--exclude-standard", "-z"]).split("\0").filter(Boolean);
for (const path of files) {
inspect(`path:${path}`, path, failures);
if (existsSync(path)) inspect(path, readFileSync(path, "utf8"), failures);
}
}
const failureList = [...failures];
if (failureList.length) {
console.error(`check:public-surface failed - ${failureList.length} disclosure(s) found`);
const categories = [
...forbidden.map((rule) => rule.label),
"non-public author identity",
"non-public committer identity",
"non-public tagger identity",
];
for (const category of categories) {
const count = failureList.filter((failure) => failure.includes(category)).length;
if (count > 0) console.error(` ${category}: ${count}`);
}
for (const failure of failureList.slice(0, 50)) console.error(` ${failure}`);
if (failureList.length > 50) console.error(` ... ${failureList.length - 50} more`);
process.exit(1);
}
console.log(`check:public-surface OK - ${historyMode ? "publishable branch/tag history" : "tracked current tree"} is public-safe.`);