vojo/scripts/check-no-tls-weakening.mjs

64 lines
2.4 KiB
JavaScript

#!/usr/bin/env node
/* eslint-disable no-console, no-restricted-syntax */
// This is a standalone Node CLI guard (not app code): console output is its
// whole purpose, and directory-walk loops are clearer than array gymnastics.
//
// Binding guard for proxy_support.md §15 #6: the native tree must never weaken
// TLS. The bring-your-own-proxy relay is a pure L4 forwarder — the WebView's
// TLS to the homeserver stays end-to-end validated against the system store,
// even through an untrusted upstream proxy. This guard fails the build if a
// future change introduces an SSL-error bypass, a custom TrustManager /
// HostnameVerifier, or cleartext traffic. Wired into .husky/pre-commit.
import { readdirSync, readFileSync, statSync } from 'node:fs';
import { join } from 'node:path';
const ROOT = 'android/app/src/main';
const FORBIDDEN = [
{
re: /onReceivedSslError/,
msg: 'onReceivedSslError override (would let a proxy MITM WebView TLS)',
},
{
re: /X509TrustManager|X509ExtendedTrustManager|implements\s+TrustManager/,
msg: 'custom TrustManager (TLS trust bypass)',
},
{ re: /HostnameVerifier|ALLOW_ALL_HOSTNAME_VERIFIER/, msg: 'custom/permissive HostnameVerifier' },
{ re: /usesCleartextTraffic\s*=\s*"true"/, msg: 'usesCleartextTraffic="true"' },
{ re: /setHostnameVerifier|setDefaultHostnameVerifier/, msg: 'setHostnameVerifier' },
];
function walk(dir) {
let out = [];
for (const name of readdirSync(dir)) {
const p = join(dir, name);
const s = statSync(p);
if (s.isDirectory()) out = out.concat(walk(p));
else if (/\.(java|kt|xml)$/.test(name)) out.push(p);
}
return out;
}
const violations = [];
for (const file of walk(ROOT)) {
const lines = readFileSync(file, 'utf8').split('\n');
lines.forEach((line, i) => {
const trimmed = line.trimStart();
// Skip comments (our own code documents that it does NOT do these things).
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) return;
for (const { re, msg } of FORBIDDEN) {
if (re.test(line)) violations.push(` ${file}:${i + 1} ${msg}\n ${line.trim()}`);
}
});
}
if (violations.length) {
console.error('\n✗ TLS-weakening guard failed (proxy_support.md §15 #6):\n');
console.error(violations.join('\n'));
console.error(
'\nThe proxy is a pure L4 forwarder; WebView TLS must stay end-to-end validated.\n'
);
process.exit(1);
}
console.log('✓ TLS-weakening guard: clean');