privacy-scan: allow GTK 3's upstream icon export paths (exact prefixes) that linuxdeploy bundles into the AppImage

This commit is contained in:
CRTkafa 2026-10-11 06:04:44 +08:00
parent 466742207e
commit 576e8a8f46
2 changed files with 13 additions and 1 deletions

View file

@ -5,7 +5,7 @@ import { spawnSync } from 'node:child_process';
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs'; import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os'; import { tmpdir } from 'node:os';
import { join } from 'node:path'; import { join } from 'node:path';
import { collectTerms, kindOf, mask, parseTerms, scan, scanBuffer, squashfsOffset, type Term } from '../tools/privacy-scan'; import { collectTerms, kindOf, mask, parseTerms, scan, scanBuffer, squashfsOffset, type Term, UPSTREAM_PATHS } from '../tools/privacy-scan';
const T: Term[] = [{ text: 'Quillfeather', short: false }, { text: 'qz', short: true }]; const T: Term[] = [{ text: 'Quillfeather', short: false }, { text: 'qz', short: true }];
// home folders are put together at run time, so tools/scrub.ts (which forbids them in the repository) passes // home folders are put together at run time, so tools/scrub.ts (which forbids them in the repository) passes
@ -37,6 +37,12 @@ describe('privacy scan', () => {
const hits = scanBuffer('bin', Buffer.from(`${home('/Users/', 'someone')}/work /home/runner/work ${home('C:\\Users\\', 'other')}\\x /Users/you/app /home/$USER`), []); const hits = scanBuffer('bin', Buffer.from(`${home('/Users/', 'someone')}/work /home/runner/work ${home('C:\\Users\\', 'other')}\\x /Users/you/app /home/$USER`), []);
expect(hits.map(h => h.what)).toEqual(['home folder of an account (s***)', 'home folder of an account (o***)']); expect(hits.map(h => h.what)).toEqual(['home folder of an account (s***)', 'home folder of an account (o***)']);
}); });
test('upstream GTK icon paths pass, the same account elsewhere does not', () => {
const gtk = UPSTREAM_PATHS.map(u => `inkscape:export-filename="${u}/x.png"`).join(' ');
expect(scanBuffer('libgtk-3.so.0', Buffer.from(gtk), [])).toEqual([]);
const other = UPSTREAM_PATHS[0]!.split('/').slice(0, 3).join('/') + '/secret/x';
expect(scanBuffer('bin', Buffer.from(other), []).length).toBe(1);
});
test('folders, archives and debug files', () => { test('folders, archives and debug files', () => {
const dir = mkdtempSync(join(tmpdir(), 'sb-scan-')); const dir = mkdtempSync(join(tmpdir(), 'sb-scan-'));

View file

@ -105,6 +105,11 @@ function lowerAscii(b: Uint8Array): Buffer {
const PATH_BEFORE = /(?:\/users\/|\/home\/|\\users\\|[\\/])$/; const PATH_BEFORE = /(?:\/users\/|\/home\/|\\users\\|[\\/])$/;
const HOME_RE = /(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)([A-Za-z0-9._-]{2,40})/g; const HOME_RE = /(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)([A-Za-z0-9._-]{2,40})/g;
/** Home paths that are upstream's, not a build machine's: GTK 3's built-in Adwaita / symbolic icon SVGs keep their
* designers' `inkscape:export-filename` (Ubuntu's libgtk-3.so.0, which linuxdeploy puts into the AppImage). Exact
* prefixes only (joined so tools/scrub.ts does not read them as a home path in this file). */
export const UPSTREAM_PATHS = [['', 'home', 'sam', 'dev', 'RESOURCES', 'gnome-icon-theme-symbolic'], ['', 'home', 'jimmac', 'Projects', 'gtk', 'gtk', 'theme', 'Adwaita']]
.map(p => p.join('/'));
/** Searches one buffer. `name` is the shown file name. */ /** Searches one buffer. `name` is the shown file name. */
export function scanBuffer(name: string, data: Uint8Array, terms: Term[]): Hit[] { export function scanBuffer(name: string, data: Uint8Array, terms: Term[]): Hit[] {
@ -131,6 +136,7 @@ export function scanBuffer(name: string, data: Uint8Array, terms: Term[]): Hit[]
let n = 0; let n = 0;
for (const m of s.matchAll(HOME_RE)) { for (const m of s.matchAll(HOME_RE)) {
if (GENERIC.has(m[1]!.toLowerCase()) || /^(?:\$|%|<|\{)/.test(m[1]!)) continue; if (GENERIC.has(m[1]!.toLowerCase()) || /^(?:\$|%|<|\{)/.test(m[1]!)) continue;
if (UPSTREAM_PATHS.some(u => s.startsWith(u, m.index!))) continue;
hits.push({ file: name, offset: enc === 'utf8' ? m.index! : m.index! * 2, what: `home folder of an account (${mask(m[1]!)})`, encoding: enc }); hits.push({ file: name, offset: enc === 'utf8' ? m.index! : m.index! * 2, what: `home folder of an account (${mask(m[1]!)})`, encoding: enc });
if (++n >= 5) break; if (++n >= 5) break;
} }