fix: redact nordvpn path metadata by default

This commit is contained in:
Stefano Fiorini
2026-03-12 02:37:16 -05:00
parent 60f425a4fc
commit 7d8eb89911
2 changed files with 62 additions and 13 deletions

View File

@@ -37,9 +37,29 @@ const MAC_WG_HELPER_PATH = path.join(
const CLIENT_IPV4 = "10.5.0.2";
const DNS_FALLBACK_RESOLVERS = ["1.1.1.1", "8.8.8.8"];
const NORDVPN_MAC_DNS_SERVERS = ["103.86.96.100", "103.86.99.100"];
const REDACTED_PATH_KEYS = new Set(["cliPath", "appPath", "configPath", "helperPath", "tokenSource"]);
function printJson(payload, exitCode = 0, errorStream = false) {
const body = `${JSON.stringify(payload, null, 2)}\n`;
function sanitizeOutputPayload(payload) {
if (Array.isArray(payload)) {
return payload.map((value) => sanitizeOutputPayload(value));
}
if (!payload || typeof payload !== "object") {
return payload;
}
const sanitized = {};
for (const [key, value] of Object.entries(payload)) {
if (REDACTED_PATH_KEYS.has(key)) {
sanitized[key] = null;
continue;
}
sanitized[key] = sanitizeOutputPayload(value);
}
return sanitized;
}
function printJson(payload, exitCode = 0, errorStream = false, debugOutput = false) {
const body = `${JSON.stringify(debugOutput ? payload : sanitizeOutputPayload(payload), null, 2)}\n`;
(errorStream ? process.stderr : process.stdout).write(body);
process.exit(exitCode);
}
@@ -1256,14 +1276,16 @@ async function loginNordvpn(installProbe) {
async function main() {
const args = parseArgs(process.argv.slice(2));
const debugOutput = Boolean(args.debug);
const emitJson = (payload, exitCode = 0, errorStream = false) => printJson(payload, exitCode, errorStream, debugOutput);
const action = args._[0];
if (!action || args.help) {
printJson(usage(), action ? 0 : 1, !action);
emitJson(usage(), action ? 0 : 1, !action);
}
const platform = detectPlatform();
if (!["darwin", "linux"].includes(platform)) {
printJson({ error: `Unsupported platform: ${platform}` }, 1, true);
emitJson({ error: `Unsupported platform: ${platform}` }, 1, true);
}
const installProbe = await probeInstallation(platform);
@@ -1271,13 +1293,13 @@ async function main() {
try {
if (action === "status") {
const ipInfo = await getPublicIpInfo();
printJson(buildStateSummary(installProbe, ipInfo));
emitJson(buildStateSummary(installProbe, ipInfo));
}
if (action === "install") {
const result = await installNordvpn(installProbe);
const refreshed = await probeInstallation(platform);
printJson({
emitJson({
action,
...result,
state: buildStateSummary(refreshed, await getPublicIpInfo()),
@@ -1287,7 +1309,7 @@ async function main() {
if (action === "login") {
const result = await loginNordvpn(installProbe);
const refreshed = await probeInstallation(platform);
printJson({
emitJson({
action,
...result,
state: buildStateSummary(refreshed, await getPublicIpInfo()),
@@ -1298,7 +1320,7 @@ async function main() {
const target = args.country || args.city ? buildConnectTarget(args) : null;
const verified = await verifyConnectionWithRetry(target);
const refreshed = await probeInstallation(platform);
printJson(
emitJson(
{
action,
requestedTarget: target,
@@ -1332,13 +1354,13 @@ async function main() {
}
if (connectResult.manualActionRequired) {
printJson({ action, requestedTarget: target, ...connectResult });
emitJson({ action, requestedTarget: target, ...connectResult });
}
const verified = await verifyConnectionWithRetry(target, { attempts: 6, delayMs: 2000 });
const refreshed = await probeInstallation(platform);
const connectState = normalizeSuccessfulConnectState(buildStateSummary(refreshed, verified.ipInfo), connectResult, verified);
printJson(
emitJson(
{
action,
requestedTarget: target,
@@ -1355,16 +1377,16 @@ async function main() {
if (action === "disconnect") {
const result = await disconnectNordvpn(installProbe);
const refreshed = await probeInstallation(platform);
printJson({
emitJson({
action,
...result,
state: buildStateSummary(refreshed, await getPublicIpInfo()),
});
}
printJson({ error: `Unknown action: ${action}`, ...usage() }, 1, true);
emitJson({ error: `Unknown action: ${action}`, ...usage() }, 1, true);
} catch (error) {
printJson({ error: error.message || String(error), action }, 1, true);
emitJson({ error: error.message || String(error), action }, 1, true);
}
}