release: privacy scan of signed macOS artifacts leaves out Apple code signatures only (copies with codesign --remove-signature on every Mach-O, the DMG's koly signature blob zeroed); any other hit still fails; tests and docs
This commit is contained in:
parent
3a27c78f49
commit
ae681e3ecd
6 changed files with 228 additions and 3 deletions
|
|
@ -41,7 +41,8 @@ import { verify as verifySig } from '../cli/lib/minisign';
|
|||
import { buildOne, OUT_DIR as SIDECAR_DIR } from './build-sidecars';
|
||||
import { versions } from './desktop-version';
|
||||
import { upsert as forgejoUpsert } from './forgejo-release';
|
||||
import { scan } from './privacy-scan';
|
||||
import { isMacArtifact, scanSignedMac } from './mac-signature-scan';
|
||||
import { allTerms, DEFAULT_TERMS, type Report, scan, TERMS_ENV } from './privacy-scan';
|
||||
|
||||
export const ROOT = resolve(import.meta.dir, '..');
|
||||
const APP_DIR = join(ROOT, 'apps/desktop');
|
||||
|
|
@ -187,8 +188,27 @@ function signFile(file: string): string {
|
|||
return sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* The privacy scan of release artifacts. Signed macOS artifacts (.app, .dmg, .app.tar.gz) are scanned without their
|
||||
* Apple code signatures (tools/mac-signature-scan.ts): the Developer ID certificate in them names the developer, and
|
||||
* that name may appear there only. Every other byte is scanned; a hit outside a signature fails the release.
|
||||
*/
|
||||
function privacyGate(paths: string[]): { files: number; bytes: number; hits: number } {
|
||||
const r = scan(paths);
|
||||
const mac = process.platform === 'darwin' ? paths.filter(isMacArtifact) : [];
|
||||
const r = scan(paths.filter(p => !mac.includes(p)));
|
||||
if (mac.length) {
|
||||
const termsFile = process.env[TERMS_ENV] ?? DEFAULT_TERMS;
|
||||
const terms = allTerms(termsFile);
|
||||
const m: Report = { files: 0, bytes: 0, hits: [], errors: [] };
|
||||
for (const p of mac) {
|
||||
if (!existsSync(p)) { m.errors.push(`${p}: does not exist`); continue; }
|
||||
try { scanSignedMac(p, terms, m); } catch (e) { m.errors.push((e as Error).message); }
|
||||
}
|
||||
r.files += m.files; r.bytes += m.bytes; r.hits.push(...m.hits); r.errors.push(...m.errors);
|
||||
r.terms = terms.length;
|
||||
if (!r.termsFile && existsSync(termsFile)) r.termsFile = termsFile;
|
||||
say(`privacy: ${mac.length} signed macOS artifact(s) scanned without their code signatures (the Developer ID certificate may name the developer there only)`);
|
||||
}
|
||||
for (const h of r.hits) console.error(`privacy: ${h.file} @${h.offset}${h.encoding ? ` (${h.encoding})` : ''}: ${h.what}`);
|
||||
for (const e of r.errors) console.error(`privacy: could not open ${e}`);
|
||||
if (r.hits.length || r.errors.length) fail(`privacy scan failed (${r.hits.length} hits, ${r.errors.length} errors): nothing may ship`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue