@rogatio/cli 6.16.4 → 6.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +555 -175
- package/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cli(args?: string[]): Promise<number>;
|
package/dist/node/index.js
CHANGED
|
@@ -2200,19 +2200,21 @@ function compileProject(value) {
|
|
|
2200
2200
|
};
|
|
2201
2201
|
}
|
|
2202
2202
|
}
|
|
2203
|
-
function
|
|
2204
|
-
|
|
2205
|
-
if (regex === null) return false;
|
|
2206
|
-
if (source.key === "url") {
|
|
2207
|
-
return regex.test(url);
|
|
2208
|
-
}
|
|
2203
|
+
function sourceMatchText(source, url) {
|
|
2204
|
+
if (source.key === "url") return url;
|
|
2209
2205
|
try {
|
|
2210
|
-
|
|
2211
|
-
return regex.test(hostname);
|
|
2206
|
+
return new URL(url).hostname;
|
|
2212
2207
|
} catch {
|
|
2213
|
-
return
|
|
2208
|
+
return null;
|
|
2214
2209
|
}
|
|
2215
2210
|
}
|
|
2211
|
+
function sourceMatches(source, url) {
|
|
2212
|
+
const regex = compileUrlRegex(source.value);
|
|
2213
|
+
if (regex === null) return false;
|
|
2214
|
+
const text = sourceMatchText(source, url);
|
|
2215
|
+
if (text === null) return false;
|
|
2216
|
+
return regex.test(text);
|
|
2217
|
+
}
|
|
2216
2218
|
var PAC_STEER_MARKER = "steer:";
|
|
2217
2219
|
function decodePacSteer(entry) {
|
|
2218
2220
|
if (!entry.startsWith(PAC_STEER_MARKER)) return null;
|
|
@@ -22596,6 +22598,15 @@ function defaultTrustInstallRoot(platform) {
|
|
|
22596
22598
|
}
|
|
22597
22599
|
return join2(process.env.HOME ?? "", ".local", "share", "rogatio");
|
|
22598
22600
|
}
|
|
22601
|
+
var MANIFEST_DIR_RECORD = "native-messaging-dirs.json";
|
|
22602
|
+
function isSafeManifestDir(dir) {
|
|
22603
|
+
if (!isAbsolute2(dir) || dir.includes("\0")) return false;
|
|
22604
|
+
const parts = dir.split(/[\\/]/).filter((part) => part.length > 0);
|
|
22605
|
+
if (parts.includes("..") || parts.length < 2) return false;
|
|
22606
|
+
const browser = parts[parts.length - 2];
|
|
22607
|
+
const leaf = parts[parts.length - 1];
|
|
22608
|
+
return leaf === "NativeMessagingHosts" && (browser === "google-chrome" || browser === "chromium");
|
|
22609
|
+
}
|
|
22599
22610
|
function isWellFormedManifest(value) {
|
|
22600
22611
|
if (typeof value !== "object" || value === null) return false;
|
|
22601
22612
|
const m = value;
|
|
@@ -22752,12 +22763,110 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22752
22763
|
installRoot,
|
|
22753
22764
|
options.caCertFileName ?? ".rogatio-ca.crt"
|
|
22754
22765
|
);
|
|
22766
|
+
const storePendingPath = join2(
|
|
22767
|
+
dirname2(caKeyFile),
|
|
22768
|
+
".rogatio-ca-store-pending"
|
|
22769
|
+
);
|
|
22755
22770
|
const caPreviousCertFile = join2(
|
|
22756
22771
|
dirname2(caCertFile),
|
|
22757
22772
|
".rogatio-ca.previous.crt"
|
|
22758
22773
|
);
|
|
22759
|
-
const
|
|
22774
|
+
const configuredManifestDirs = options.manifestDirs && options.manifestDirs.length > 0 ? [...options.manifestDirs] : [manifestDir];
|
|
22775
|
+
const recordsManifestDirs = options.manifestDirs !== void 0 && options.manifestDirs.length > 0;
|
|
22776
|
+
const manifestRecordPath = join2(installRoot, MANIFEST_DIR_RECORD);
|
|
22760
22777
|
let installerCalled = false;
|
|
22778
|
+
function parseRecordedDirs(raw) {
|
|
22779
|
+
let parsed;
|
|
22780
|
+
try {
|
|
22781
|
+
parsed = JSON.parse(raw);
|
|
22782
|
+
} catch {
|
|
22783
|
+
return void 0;
|
|
22784
|
+
}
|
|
22785
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || parsed.length > 8) {
|
|
22786
|
+
return void 0;
|
|
22787
|
+
}
|
|
22788
|
+
const dirs = [];
|
|
22789
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22790
|
+
for (const entry of parsed) {
|
|
22791
|
+
if (typeof entry !== "string" || seen.has(entry) || !isSafeManifestDir(entry)) {
|
|
22792
|
+
return void 0;
|
|
22793
|
+
}
|
|
22794
|
+
seen.add(entry);
|
|
22795
|
+
dirs.push(entry);
|
|
22796
|
+
}
|
|
22797
|
+
return dirs;
|
|
22798
|
+
}
|
|
22799
|
+
async function readRecordedDirs() {
|
|
22800
|
+
if (!recordsManifestDirs) return void 0;
|
|
22801
|
+
try {
|
|
22802
|
+
return parseRecordedDirs(await readFile2(manifestRecordPath, "utf8"));
|
|
22803
|
+
} catch {
|
|
22804
|
+
return void 0;
|
|
22805
|
+
}
|
|
22806
|
+
}
|
|
22807
|
+
async function activeManifestDirs() {
|
|
22808
|
+
const recorded = await readRecordedDirs();
|
|
22809
|
+
if (recorded) return recorded;
|
|
22810
|
+
if (!recordsManifestDirs) return configuredManifestDirs;
|
|
22811
|
+
const present = [];
|
|
22812
|
+
for (const dir of configuredManifestDirs) {
|
|
22813
|
+
if (await existsFile(join2(dir, `${hostName}.json`))) present.push(dir);
|
|
22814
|
+
}
|
|
22815
|
+
return present.length > 0 ? present : configuredManifestDirs;
|
|
22816
|
+
}
|
|
22817
|
+
async function snapshotFile(path2) {
|
|
22818
|
+
let previous;
|
|
22819
|
+
try {
|
|
22820
|
+
previous = await readFile2(path2, "utf8");
|
|
22821
|
+
} catch {
|
|
22822
|
+
previous = void 0;
|
|
22823
|
+
}
|
|
22824
|
+
return { path: path2, previous, written: false };
|
|
22825
|
+
}
|
|
22826
|
+
async function restoreSnapshot(snap) {
|
|
22827
|
+
if (!snap.written) return;
|
|
22828
|
+
if (snap.previous !== void 0) {
|
|
22829
|
+
await writeFileAtomic(snap.path, snap.previous);
|
|
22830
|
+
return;
|
|
22831
|
+
}
|
|
22832
|
+
await rm(snap.path, { force: true });
|
|
22833
|
+
}
|
|
22834
|
+
async function rollbackWritten(snaps) {
|
|
22835
|
+
for (const snap of snaps) {
|
|
22836
|
+
try {
|
|
22837
|
+
await restoreSnapshot(snap);
|
|
22838
|
+
} catch {
|
|
22839
|
+
}
|
|
22840
|
+
}
|
|
22841
|
+
}
|
|
22842
|
+
async function writeManifestFiles(data) {
|
|
22843
|
+
const snaps = [];
|
|
22844
|
+
try {
|
|
22845
|
+
for (const dir of configuredManifestDirs) {
|
|
22846
|
+
if (recordsManifestDirs && !isSafeManifestDir(dir)) {
|
|
22847
|
+
throw new Error("trust.write-failed");
|
|
22848
|
+
}
|
|
22849
|
+
const snap = await snapshotFile(join2(dir, `${hostName}.json`));
|
|
22850
|
+
snaps.push(snap);
|
|
22851
|
+
await writeFileAtomic(snap.path, data);
|
|
22852
|
+
snap.written = true;
|
|
22853
|
+
}
|
|
22854
|
+
if (recordsManifestDirs) {
|
|
22855
|
+
const recordSnap = await snapshotFile(manifestRecordPath);
|
|
22856
|
+
snaps.push(recordSnap);
|
|
22857
|
+
await writeFileAtomic(
|
|
22858
|
+
manifestRecordPath,
|
|
22859
|
+
`${JSON.stringify(configuredManifestDirs)}
|
|
22860
|
+
`
|
|
22861
|
+
);
|
|
22862
|
+
recordSnap.written = true;
|
|
22863
|
+
}
|
|
22864
|
+
return { ok: true, snaps };
|
|
22865
|
+
} catch (error) {
|
|
22866
|
+
await rollbackWritten(snaps);
|
|
22867
|
+
return { ok: false, reason: codeOf(error, "trust.write-failed") };
|
|
22868
|
+
}
|
|
22869
|
+
}
|
|
22761
22870
|
async function install(extensionId) {
|
|
22762
22871
|
if (!extensionId || !/^[a-p]{32}$/.test(extensionId)) {
|
|
22763
22872
|
return {
|
|
@@ -22792,21 +22901,17 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22792
22901
|
}
|
|
22793
22902
|
const caps = await detect();
|
|
22794
22903
|
if (!caps.manifest) return unsupportedResult(caps);
|
|
22795
|
-
|
|
22796
|
-
|
|
22797
|
-
} catch (error) {
|
|
22904
|
+
const written = await writeManifestFiles(data);
|
|
22905
|
+
if (!written.ok) {
|
|
22798
22906
|
return {
|
|
22799
22907
|
ok: false,
|
|
22800
22908
|
state: "unsupported",
|
|
22801
|
-
reasons: [
|
|
22909
|
+
reasons: [written.reason]
|
|
22802
22910
|
};
|
|
22803
22911
|
}
|
|
22804
22912
|
const caTrustCaps = await detect();
|
|
22805
22913
|
if (!caTrustCaps.caTrust) {
|
|
22806
|
-
|
|
22807
|
-
await rm(manifestPath(), { force: true });
|
|
22808
|
-
} catch {
|
|
22809
|
-
}
|
|
22914
|
+
await rollbackWritten(written.snaps);
|
|
22810
22915
|
return unsupportedResult(caTrustCaps);
|
|
22811
22916
|
}
|
|
22812
22917
|
const trustResult = await trust();
|
|
@@ -22815,13 +22920,11 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22815
22920
|
await rollbackReplacedCa();
|
|
22816
22921
|
} catch {
|
|
22817
22922
|
}
|
|
22818
|
-
|
|
22819
|
-
await rm(manifestPath(), { force: true });
|
|
22820
|
-
} catch {
|
|
22821
|
-
}
|
|
22923
|
+
await rollbackWritten(written.snaps);
|
|
22822
22924
|
installerCalled = false;
|
|
22823
22925
|
return trustResult;
|
|
22824
22926
|
}
|
|
22927
|
+
await rm(storePendingPath, { force: true });
|
|
22825
22928
|
return trustResult.reasons ? { ok: true, state: "installed", reasons: trustResult.reasons } : { ok: true, state: "installed" };
|
|
22826
22929
|
}
|
|
22827
22930
|
async function reusableCaMaterial() {
|
|
@@ -22951,8 +23054,8 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22951
23054
|
}
|
|
22952
23055
|
let installedNew = false;
|
|
22953
23056
|
if (caTrustInstaller && !installerCalled) {
|
|
22954
|
-
await caTrustInstaller(await readFile2(caCertFile, "utf8"));
|
|
22955
23057
|
installerCalled = true;
|
|
23058
|
+
await caTrustInstaller(await readFile2(caCertFile, "utf8"));
|
|
22956
23059
|
installedNew = true;
|
|
22957
23060
|
}
|
|
22958
23061
|
if (reusable && siblingAnchor && (installedNew || !caTrustInstaller)) {
|
|
@@ -22977,11 +23080,15 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22977
23080
|
const saved = await readPreviousRogatioCa(caPreviousCertFile);
|
|
22978
23081
|
const live = await readPreviousRogatioCa(caCertFile);
|
|
22979
23082
|
const caWasPresent = await existsFile(caKeyFile);
|
|
23083
|
+
if (caWasPresent && caTrustRemover) {
|
|
23084
|
+
await writeFileAtomic(storePendingPath, "1\n", 384);
|
|
23085
|
+
}
|
|
22980
23086
|
await rm(caKeyFile, { force: true });
|
|
22981
23087
|
await rm(caPubFile, { force: true });
|
|
22982
23088
|
await rm(caCertFile, { force: true });
|
|
22983
|
-
if (
|
|
23089
|
+
if (caTrustRemover && await existsFile(storePendingPath)) {
|
|
22984
23090
|
await caTrustRemover();
|
|
23091
|
+
await rm(storePendingPath, { force: true });
|
|
22985
23092
|
}
|
|
22986
23093
|
if (!saved) return;
|
|
22987
23094
|
if (!caWasPresent || saved.fingerprint !== live?.fingerprint) {
|
|
@@ -22996,14 +23103,19 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
22996
23103
|
}
|
|
22997
23104
|
async function uninstall() {
|
|
22998
23105
|
try {
|
|
22999
|
-
|
|
23106
|
+
const dirs = await activeManifestDirs();
|
|
23107
|
+
for (const dir of dirs) {
|
|
23108
|
+
await rm(join2(dir, `${hostName}.json`), { force: true });
|
|
23109
|
+
}
|
|
23110
|
+
if (recordsManifestDirs) await rm(manifestRecordPath, { force: true });
|
|
23000
23111
|
await removeCa();
|
|
23001
23112
|
installerCalled = false;
|
|
23002
23113
|
} catch (error) {
|
|
23114
|
+
const reason = error instanceof TrustError ? error.message : error instanceof Error ? error.message : String(error);
|
|
23003
23115
|
return {
|
|
23004
23116
|
ok: false,
|
|
23005
23117
|
state: "unsupported",
|
|
23006
|
-
reasons: [
|
|
23118
|
+
reasons: [reason]
|
|
23007
23119
|
};
|
|
23008
23120
|
}
|
|
23009
23121
|
return { ok: true, state: "uninstalled" };
|
|
@@ -23020,13 +23132,30 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
23020
23132
|
}
|
|
23021
23133
|
return anchorRemovalWarning ? { ok: true, state: "trusted", reasons: [anchorRemovalWarning] } : { ok: true, state: "trusted" };
|
|
23022
23134
|
}
|
|
23135
|
+
function manifestAcceptable(parsed) {
|
|
23136
|
+
if (!recordsManifestDirs) return true;
|
|
23137
|
+
return parsed.name === hostName && parsed.path === hostPath && parsed.type === "stdio";
|
|
23138
|
+
}
|
|
23139
|
+
function sameOrigins(left, right) {
|
|
23140
|
+
if (left.length !== right.length) return false;
|
|
23141
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
23142
|
+
if (left[index] !== right[index]) return false;
|
|
23143
|
+
}
|
|
23144
|
+
return true;
|
|
23145
|
+
}
|
|
23023
23146
|
async function status() {
|
|
23024
|
-
|
|
23025
|
-
|
|
23026
|
-
|
|
23027
|
-
|
|
23028
|
-
|
|
23029
|
-
|
|
23147
|
+
const dirs = await activeManifestDirs();
|
|
23148
|
+
let installed = dirs.length > 0;
|
|
23149
|
+
for (const dir of dirs) {
|
|
23150
|
+
try {
|
|
23151
|
+
const raw = await readFile2(join2(dir, `${hostName}.json`), "utf8");
|
|
23152
|
+
const parsed = JSON.parse(raw);
|
|
23153
|
+
if (!isWellFormedManifest(parsed) || !manifestAcceptable(parsed)) {
|
|
23154
|
+
installed = false;
|
|
23155
|
+
}
|
|
23156
|
+
} catch {
|
|
23157
|
+
installed = false;
|
|
23158
|
+
}
|
|
23030
23159
|
}
|
|
23031
23160
|
const trusted = await existsFile(caKeyFile) && await existsFile(caCertFile);
|
|
23032
23161
|
const caps = await detect();
|
|
@@ -23039,34 +23168,50 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
23039
23168
|
}
|
|
23040
23169
|
async function verify2() {
|
|
23041
23170
|
const reasons = [];
|
|
23042
|
-
|
|
23043
|
-
|
|
23171
|
+
const pushReason = (reason) => {
|
|
23172
|
+
if (!reasons.includes(reason)) reasons.push(reason);
|
|
23173
|
+
};
|
|
23174
|
+
const dirs = await activeManifestDirs();
|
|
23175
|
+
let manifestExists = dirs.length > 0;
|
|
23176
|
+
let manifestValid = dirs.length > 0;
|
|
23044
23177
|
let binaryExists = false;
|
|
23045
23178
|
let binaryExecutable = false;
|
|
23046
23179
|
let allowedOrigins = [];
|
|
23047
|
-
|
|
23048
|
-
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
|
|
23052
|
-
|
|
23053
|
-
|
|
23054
|
-
|
|
23055
|
-
|
|
23056
|
-
binaryExists = fileStat.isFile();
|
|
23057
|
-
binaryExecutable = platform === "win32" ? binaryExists : (fileStat.mode & 73) !== 0;
|
|
23058
|
-
if (!binaryExists) reasons.push("binary-not-found");
|
|
23059
|
-
if (!binaryExecutable) reasons.push("binary-not-executable");
|
|
23060
|
-
} catch {
|
|
23061
|
-
binaryExists = false;
|
|
23062
|
-
reasons.push("binary-not-found");
|
|
23180
|
+
let binaryPath;
|
|
23181
|
+
for (const dir of dirs) {
|
|
23182
|
+
try {
|
|
23183
|
+
const raw = await readFile2(join2(dir, `${hostName}.json`), "utf8");
|
|
23184
|
+
const parsed = JSON.parse(raw);
|
|
23185
|
+
if (!isWellFormedManifest(parsed) || !manifestAcceptable(parsed)) {
|
|
23186
|
+
manifestValid = false;
|
|
23187
|
+
pushReason("manifest-invalid");
|
|
23188
|
+
continue;
|
|
23063
23189
|
}
|
|
23064
|
-
if (
|
|
23065
|
-
|
|
23066
|
-
|
|
23190
|
+
if (binaryPath === void 0) {
|
|
23191
|
+
binaryPath = parsed.path;
|
|
23192
|
+
allowedOrigins = [...parsed.allowed_origins];
|
|
23193
|
+
} else if (parsed.path !== binaryPath || !sameOrigins(parsed.allowed_origins, allowedOrigins)) {
|
|
23194
|
+
manifestValid = false;
|
|
23195
|
+
pushReason("manifest-invalid");
|
|
23196
|
+
}
|
|
23197
|
+
} catch {
|
|
23198
|
+
manifestExists = false;
|
|
23199
|
+
manifestValid = false;
|
|
23200
|
+
pushReason("manifest-not-found");
|
|
23067
23201
|
}
|
|
23068
|
-
}
|
|
23069
|
-
|
|
23202
|
+
}
|
|
23203
|
+
if (binaryPath !== void 0) {
|
|
23204
|
+
try {
|
|
23205
|
+
const fileStat = await stat(binaryPath);
|
|
23206
|
+
binaryExists = fileStat.isFile();
|
|
23207
|
+
binaryExecutable = platform === "win32" ? binaryExists : (fileStat.mode & 73) !== 0;
|
|
23208
|
+
if (!binaryExists) pushReason("binary-not-found");
|
|
23209
|
+
if (!binaryExecutable) pushReason("binary-not-executable");
|
|
23210
|
+
} catch {
|
|
23211
|
+
binaryExists = false;
|
|
23212
|
+
pushReason("binary-not-found");
|
|
23213
|
+
}
|
|
23214
|
+
if (allowedOrigins.length === 0) pushReason("no-allowed-origins");
|
|
23070
23215
|
}
|
|
23071
23216
|
const caTrusted = await existsFile(caKeyFile) && await existsFile(caCertFile);
|
|
23072
23217
|
if (!caTrusted) reasons.push("ca-not-trusted");
|
|
@@ -23259,10 +23404,99 @@ var darwinAdapter = {
|
|
|
23259
23404
|
};
|
|
23260
23405
|
var darwin_default = darwinAdapter;
|
|
23261
23406
|
var CA_DIR = "/usr/local/share/ca-certificates";
|
|
23262
|
-
var
|
|
23263
|
-
|
|
23264
|
-
|
|
23265
|
-
|
|
23407
|
+
var CERT_NAME = "rogatio-ca.crt";
|
|
23408
|
+
var DEBIAN_CERT = posixJoin2(CA_DIR, CERT_NAME);
|
|
23409
|
+
var ARCH_TRUST_SOURCE = "/etc/ca-certificates/trust-source";
|
|
23410
|
+
var FEDORA_TRUST_SOURCE = "/etc/pki/ca-trust/source";
|
|
23411
|
+
var ARCH_ANCHORS = "/etc/ca-certificates/trust-source/anchors";
|
|
23412
|
+
var FEDORA_ANCHORS = "/etc/pki/ca-trust/source/anchors";
|
|
23413
|
+
var P11_CERTS = [
|
|
23414
|
+
posixJoin2(ARCH_ANCHORS, CERT_NAME),
|
|
23415
|
+
posixJoin2(FEDORA_ANCHORS, CERT_NAME)
|
|
23416
|
+
];
|
|
23417
|
+
var BROWSERS = ["google-chrome", "chromium"];
|
|
23418
|
+
function nodeCode(err) {
|
|
23419
|
+
const code = err?.code;
|
|
23420
|
+
return typeof code === "string" && code.length > 0 ? code : "EACCES";
|
|
23421
|
+
}
|
|
23422
|
+
function exists(path2) {
|
|
23423
|
+
try {
|
|
23424
|
+
accessSync2(path2);
|
|
23425
|
+
return true;
|
|
23426
|
+
} catch (err) {
|
|
23427
|
+
return nodeCode(err) !== "ENOENT";
|
|
23428
|
+
}
|
|
23429
|
+
}
|
|
23430
|
+
function writable(path2) {
|
|
23431
|
+
try {
|
|
23432
|
+
accessSync2(path2, constants3.W_OK);
|
|
23433
|
+
return true;
|
|
23434
|
+
} catch {
|
|
23435
|
+
return false;
|
|
23436
|
+
}
|
|
23437
|
+
}
|
|
23438
|
+
function toolOnPath(name) {
|
|
23439
|
+
const result = spawnSync2("which", [name], { timeout: 1e3 });
|
|
23440
|
+
if (result.status === 0) return true;
|
|
23441
|
+
const code = result.error?.code;
|
|
23442
|
+
if (code !== "ENOENT") return false;
|
|
23443
|
+
const pathEnv = process.env.PATH ?? "";
|
|
23444
|
+
for (const dir of pathEnv.split(":")) {
|
|
23445
|
+
if (dir.length === 0) continue;
|
|
23446
|
+
try {
|
|
23447
|
+
accessSync2(posixJoin2(dir, name));
|
|
23448
|
+
return true;
|
|
23449
|
+
} catch {
|
|
23450
|
+
}
|
|
23451
|
+
}
|
|
23452
|
+
return false;
|
|
23453
|
+
}
|
|
23454
|
+
function caBackend() {
|
|
23455
|
+
if (toolOnPath("update-ca-certificates")) return "debian";
|
|
23456
|
+
if (toolOnPath("update-ca-trust")) return "p11kit";
|
|
23457
|
+
return void 0;
|
|
23458
|
+
}
|
|
23459
|
+
function p11kitAnchorsDir() {
|
|
23460
|
+
const arch = exists(ARCH_TRUST_SOURCE);
|
|
23461
|
+
const fedora = exists(FEDORA_TRUST_SOURCE);
|
|
23462
|
+
if (arch && !fedora) return ARCH_ANCHORS;
|
|
23463
|
+
if (fedora && !arch) return FEDORA_ANCHORS;
|
|
23464
|
+
return void 0;
|
|
23465
|
+
}
|
|
23466
|
+
function needsElevation(dir) {
|
|
23467
|
+
if (writable(dir)) return false;
|
|
23468
|
+
try {
|
|
23469
|
+
accessSync2(dir, constants3.W_OK);
|
|
23470
|
+
} catch (err) {
|
|
23471
|
+
if (nodeCode(err) === "ENOENT" && writable(dirname4(dir))) return false;
|
|
23472
|
+
}
|
|
23473
|
+
return !toolOnPath("sudo");
|
|
23474
|
+
}
|
|
23475
|
+
function configHome() {
|
|
23476
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
23477
|
+
if (typeof xdg === "string" && xdg.startsWith("/")) return xdg;
|
|
23478
|
+
const home = process.env.HOME ?? "";
|
|
23479
|
+
return posixJoin2(home, ".config");
|
|
23480
|
+
}
|
|
23481
|
+
function manifestDirFor(browser) {
|
|
23482
|
+
return posixJoin2(configHome(), browser, "NativeMessagingHosts");
|
|
23483
|
+
}
|
|
23484
|
+
function canHostManifest(dir) {
|
|
23485
|
+
try {
|
|
23486
|
+
accessSync2(dir, constants3.W_OK);
|
|
23487
|
+
return true;
|
|
23488
|
+
} catch (err) {
|
|
23489
|
+
if (nodeCode(err) !== "ENOENT") return false;
|
|
23490
|
+
}
|
|
23491
|
+
try {
|
|
23492
|
+
accessSync2(dirname4(dir), constants3.W_OK);
|
|
23493
|
+
return true;
|
|
23494
|
+
} catch {
|
|
23495
|
+
return false;
|
|
23496
|
+
}
|
|
23497
|
+
}
|
|
23498
|
+
function installableManifestDirs() {
|
|
23499
|
+
return BROWSERS.map(manifestDirFor).filter(canHostManifest);
|
|
23266
23500
|
}
|
|
23267
23501
|
function installFailureReason(stderr) {
|
|
23268
23502
|
const text = stderr.toLowerCase();
|
|
@@ -23304,44 +23538,36 @@ function runSudo(args, stdin) {
|
|
|
23304
23538
|
input.end(stdin);
|
|
23305
23539
|
});
|
|
23306
23540
|
}
|
|
23541
|
+
async function sudoOrThrow(args, stdin) {
|
|
23542
|
+
const result = await runSudo(args, stdin);
|
|
23543
|
+
if (result.code === 0) return;
|
|
23544
|
+
const reason = installFailureReason(result.stderr);
|
|
23545
|
+
throw new TrustError("trust.internal", reason, [reason]);
|
|
23546
|
+
}
|
|
23307
23547
|
var linuxAdapter = {
|
|
23308
23548
|
platform: "linux",
|
|
23309
23549
|
defaultManifestDir: () => {
|
|
23310
23550
|
const home = process.env.HOME ?? "";
|
|
23311
23551
|
return posixJoin2(home, ".config/google-chrome/NativeMessagingHosts");
|
|
23312
23552
|
},
|
|
23553
|
+
manifestDirs: () => installableManifestDirs(),
|
|
23313
23554
|
defaultCaInstallPath: () => CA_DIR,
|
|
23314
23555
|
detect() {
|
|
23315
23556
|
const reasons = [];
|
|
23316
|
-
const
|
|
23317
|
-
|
|
23318
|
-
|
|
23319
|
-
});
|
|
23320
|
-
if (updateCa.status !== 0) {
|
|
23321
|
-
reasons.push("tooling-missing");
|
|
23322
|
-
}
|
|
23323
|
-
try {
|
|
23324
|
-
accessSync2(manifestDir, constants3.W_OK);
|
|
23325
|
-
} catch {
|
|
23557
|
+
const backend = caBackend();
|
|
23558
|
+
if (!backend) reasons.push("tooling-missing");
|
|
23559
|
+
if (installableManifestDirs().length === 0) {
|
|
23326
23560
|
reasons.push("manifest-dir-unwritable");
|
|
23327
23561
|
}
|
|
23328
|
-
|
|
23329
|
-
|
|
23330
|
-
}
|
|
23331
|
-
|
|
23332
|
-
|
|
23333
|
-
|
|
23334
|
-
} catch {
|
|
23335
|
-
if (!hasSudo()) {
|
|
23336
|
-
reasons.push("elevation-required");
|
|
23337
|
-
}
|
|
23338
|
-
}
|
|
23339
|
-
} else if (!hasSudo()) {
|
|
23340
|
-
reasons.push("elevation-required");
|
|
23341
|
-
}
|
|
23562
|
+
if (backend === "debian") {
|
|
23563
|
+
if (needsElevation(CA_DIR)) reasons.push("elevation-required");
|
|
23564
|
+
} else if (backend === "p11kit") {
|
|
23565
|
+
const anchors = p11kitAnchorsDir();
|
|
23566
|
+
if (!anchors) reasons.push("ca-store-unwritable");
|
|
23567
|
+
else if (needsElevation(anchors)) reasons.push("elevation-required");
|
|
23342
23568
|
}
|
|
23343
23569
|
const manifest = !reasons.includes("tooling-missing") && !reasons.includes("manifest-dir-unwritable");
|
|
23344
|
-
const caTrust = !reasons.includes("tooling-missing") && !reasons.includes("elevation-required");
|
|
23570
|
+
const caTrust = !reasons.includes("tooling-missing") && !reasons.includes("elevation-required") && !reasons.includes("ca-store-unwritable");
|
|
23345
23571
|
return {
|
|
23346
23572
|
manifest,
|
|
23347
23573
|
caTrust,
|
|
@@ -23354,29 +23580,55 @@ var linuxAdapter = {
|
|
|
23354
23580
|
"invalid-ca-certificate"
|
|
23355
23581
|
]);
|
|
23356
23582
|
}
|
|
23357
|
-
|
|
23358
|
-
|
|
23359
|
-
|
|
23583
|
+
if (caBackend() === "debian") {
|
|
23584
|
+
try {
|
|
23585
|
+
mkdirSync(CA_DIR, { recursive: true });
|
|
23586
|
+
} catch {
|
|
23587
|
+
throw new TrustError("trust.internal", "ca-store-unwritable", [
|
|
23588
|
+
"ca-store-unwritable"
|
|
23589
|
+
]);
|
|
23590
|
+
}
|
|
23591
|
+
await sudoOrThrow(["tee", DEBIAN_CERT], certPem);
|
|
23592
|
+
await sudoOrThrow(["update-ca-certificates"]);
|
|
23593
|
+
return;
|
|
23594
|
+
}
|
|
23595
|
+
if (caBackend() !== "p11kit") {
|
|
23596
|
+
throw new TrustError("trust.internal", "tooling-missing", [
|
|
23597
|
+
"tooling-missing"
|
|
23598
|
+
]);
|
|
23599
|
+
}
|
|
23600
|
+
const anchors = p11kitAnchorsDir();
|
|
23601
|
+
if (!anchors) {
|
|
23360
23602
|
throw new TrustError("trust.internal", "ca-store-unwritable", [
|
|
23361
23603
|
"ca-store-unwritable"
|
|
23362
23604
|
]);
|
|
23363
23605
|
}
|
|
23364
|
-
const
|
|
23365
|
-
|
|
23366
|
-
|
|
23367
|
-
|
|
23368
|
-
|
|
23369
|
-
|
|
23370
|
-
|
|
23371
|
-
|
|
23372
|
-
|
|
23373
|
-
|
|
23606
|
+
const certPath = posixJoin2(anchors, CERT_NAME);
|
|
23607
|
+
await sudoOrThrow(["mkdir", "-p", anchors]);
|
|
23608
|
+
await sudoOrThrow(["tee", certPath], certPem);
|
|
23609
|
+
const refresh = await runSudo(["update-ca-trust"]);
|
|
23610
|
+
if (refresh.code === 0) return;
|
|
23611
|
+
await sudoOrThrow(["rm", "-f", certPath]);
|
|
23612
|
+
const rebuilt = await runSudo(["update-ca-trust"]);
|
|
23613
|
+
if (rebuilt.code !== 0) {
|
|
23614
|
+
const reason2 = installFailureReason(rebuilt.stderr);
|
|
23615
|
+
throw new TrustError("trust.internal", reason2, [reason2]);
|
|
23616
|
+
}
|
|
23617
|
+
const reason = installFailureReason(refresh.stderr);
|
|
23618
|
+
throw new TrustError("trust.internal", reason, [reason]);
|
|
23374
23619
|
},
|
|
23375
23620
|
async caTrustRemover() {
|
|
23376
23621
|
try {
|
|
23377
|
-
unlinkSync2(
|
|
23622
|
+
unlinkSync2(DEBIAN_CERT);
|
|
23378
23623
|
} catch {
|
|
23379
23624
|
}
|
|
23625
|
+
if (!toolOnPath("update-ca-trust")) return;
|
|
23626
|
+
const present = P11_CERTS.filter((path2) => exists(path2));
|
|
23627
|
+
if (caBackend() !== "p11kit" && present.length === 0) return;
|
|
23628
|
+
for (const certPath of present) {
|
|
23629
|
+
await sudoOrThrow(["rm", "-f", certPath]);
|
|
23630
|
+
}
|
|
23631
|
+
await sudoOrThrow(["update-ca-trust"]);
|
|
23380
23632
|
},
|
|
23381
23633
|
async caTrustAnchorRemover(fingerprintSha1, certPem) {
|
|
23382
23634
|
void fingerprintSha1;
|
|
@@ -23543,13 +23795,15 @@ function createInstalledTrustController() {
|
|
|
23543
23795
|
const platform = process.platform;
|
|
23544
23796
|
const adapter = selectTrustPlatformAdapter(platform);
|
|
23545
23797
|
const installRoot = defaultTrustInstallRoot(platform);
|
|
23798
|
+
const manifestDirs = adapter.manifestDirs?.() ?? [];
|
|
23546
23799
|
return createRequestBodyTrustController({
|
|
23547
23800
|
platform,
|
|
23548
23801
|
installRoot,
|
|
23549
23802
|
hostPath: join5(installRoot, "runtime-host"),
|
|
23550
23803
|
hostName: "com.rogatio.runtime",
|
|
23551
23804
|
allowedOrigins: [],
|
|
23552
|
-
manifestDir: adapter.defaultManifestDir(),
|
|
23805
|
+
manifestDir: manifestDirs[0] ?? adapter.defaultManifestDir(),
|
|
23806
|
+
...manifestDirs.length > 0 ? { manifestDirs } : {},
|
|
23553
23807
|
detectCapabilities: () => adapter.detect(),
|
|
23554
23808
|
caTrustInstaller: (cert) => adapter.caTrustInstaller(cert),
|
|
23555
23809
|
caTrustRemover: () => adapter.caTrustRemover(),
|
|
@@ -24419,29 +24673,6 @@ async function resolveConfinedRoot(value) {
|
|
|
24419
24673
|
await directory?.close().catch(() => void 0);
|
|
24420
24674
|
}
|
|
24421
24675
|
}
|
|
24422
|
-
var MOCK_LISTENER_PREFIX = "/.rogatio/mock/";
|
|
24423
|
-
function isSingleSegment(value) {
|
|
24424
|
-
return value.length > 0 && value.length <= 2048 && value !== "." && value !== ".." && !value.includes("/") && !value.includes("\\") && !value.includes("?") && !hasControl(value);
|
|
24425
|
-
}
|
|
24426
|
-
function parseMockRedirect(rawUrl) {
|
|
24427
|
-
const queryAt = rawUrl.indexOf("?");
|
|
24428
|
-
const path2 = queryAt === -1 ? rawUrl : rawUrl.slice(0, queryAt);
|
|
24429
|
-
if (!path2.startsWith(MOCK_LISTENER_PREFIX)) return null;
|
|
24430
|
-
const rest = path2.slice(MOCK_LISTENER_PREFIX.length);
|
|
24431
|
-
const slash = rest.indexOf("/");
|
|
24432
|
-
if (slash <= 0) return null;
|
|
24433
|
-
if (rest.indexOf("/", slash + 1) !== -1) return null;
|
|
24434
|
-
let token;
|
|
24435
|
-
let digest;
|
|
24436
|
-
try {
|
|
24437
|
-
token = decodeURIComponent(rest.slice(0, slash));
|
|
24438
|
-
digest = decodeURIComponent(rest.slice(slash + 1));
|
|
24439
|
-
} catch {
|
|
24440
|
-
return null;
|
|
24441
|
-
}
|
|
24442
|
-
if (!isSingleSegment(token) || !isSingleSegment(digest)) return null;
|
|
24443
|
-
return { token, digest };
|
|
24444
|
-
}
|
|
24445
24676
|
var REGEX_WORKER_SOURCE = `
|
|
24446
24677
|
const workerThreads =
|
|
24447
24678
|
typeof process.getBuiltinModule === "function"
|
|
@@ -24450,11 +24681,35 @@ const workerThreads =
|
|
|
24450
24681
|
const { parentPort } = workerThreads;
|
|
24451
24682
|
parentPort.postMessage({ type: "ready" });
|
|
24452
24683
|
parentPort.on("message", (msg) => {
|
|
24453
|
-
if (msg.type !== "replace") return;
|
|
24684
|
+
if (msg.type !== "replace" && msg.type !== "test" && msg.type !== "exec") return;
|
|
24454
24685
|
parentPort.postMessage({ id: msg.id, type: "ack" });
|
|
24455
24686
|
try {
|
|
24456
|
-
|
|
24457
|
-
|
|
24687
|
+
if (msg.type === "replace") {
|
|
24688
|
+
const out = msg.text.replace(new RegExp(msg.pattern, "gu"), msg.replacement);
|
|
24689
|
+
parentPort.postMessage({ id: msg.id, type: "result", ok: true, out });
|
|
24690
|
+
return;
|
|
24691
|
+
}
|
|
24692
|
+
const regex = new RegExp(msg.pattern);
|
|
24693
|
+
if (msg.type === "test") {
|
|
24694
|
+
parentPort.postMessage({
|
|
24695
|
+
id: msg.id,
|
|
24696
|
+
type: "result",
|
|
24697
|
+
ok: true,
|
|
24698
|
+
matched: regex.test(msg.text),
|
|
24699
|
+
});
|
|
24700
|
+
return;
|
|
24701
|
+
}
|
|
24702
|
+
const match = regex.exec(msg.text);
|
|
24703
|
+
const captures =
|
|
24704
|
+
match === null
|
|
24705
|
+
? null
|
|
24706
|
+
: match.slice(1).map((part) => (part === undefined ? null : part));
|
|
24707
|
+
parentPort.postMessage({
|
|
24708
|
+
id: msg.id,
|
|
24709
|
+
type: "result",
|
|
24710
|
+
ok: true,
|
|
24711
|
+
captures,
|
|
24712
|
+
});
|
|
24458
24713
|
} catch (err) {
|
|
24459
24714
|
parentPort.postMessage({
|
|
24460
24715
|
id: msg.id,
|
|
@@ -24470,6 +24725,7 @@ var regexWorker = null;
|
|
|
24470
24725
|
var regexWorkerBoot = null;
|
|
24471
24726
|
var nextRegexJobId = 1;
|
|
24472
24727
|
var regexWorkerBootDelayForTestsMs = 0;
|
|
24728
|
+
var failNextRegexWorkerBootForTests = false;
|
|
24473
24729
|
function discardRegexWorker(worker) {
|
|
24474
24730
|
if (regexWorker === worker) {
|
|
24475
24731
|
regexWorker = null;
|
|
@@ -24479,6 +24735,10 @@ function discardRegexWorker(worker) {
|
|
|
24479
24735
|
});
|
|
24480
24736
|
}
|
|
24481
24737
|
function bootRegexWorker() {
|
|
24738
|
+
if (failNextRegexWorkerBootForTests) {
|
|
24739
|
+
failNextRegexWorkerBootForTests = false;
|
|
24740
|
+
return Promise.reject(new Error("regex-worker-boot-failed"));
|
|
24741
|
+
}
|
|
24482
24742
|
if (regexWorker !== null) return Promise.resolve(regexWorker);
|
|
24483
24743
|
if (regexWorkerBoot !== null) return regexWorkerBoot;
|
|
24484
24744
|
const boot = new Promise((resolve12, reject) => {
|
|
@@ -24546,7 +24806,7 @@ function bootRegexWorker() {
|
|
|
24546
24806
|
});
|
|
24547
24807
|
return boot;
|
|
24548
24808
|
}
|
|
24549
|
-
function runOnRegexWorker(worker, id2, text, pattern, replacement, deadlineMs) {
|
|
24809
|
+
function runOnRegexWorker(worker, id2, type, text, pattern, replacement, deadlineMs) {
|
|
24550
24810
|
return new Promise((resolve12, reject) => {
|
|
24551
24811
|
let timer = null;
|
|
24552
24812
|
const cleanup = () => {
|
|
@@ -24567,8 +24827,15 @@ function runOnRegexWorker(worker, id2, text, pattern, replacement, deadlineMs) {
|
|
|
24567
24827
|
}
|
|
24568
24828
|
if (msg.type === "result") {
|
|
24569
24829
|
cleanup();
|
|
24570
|
-
if (msg.ok
|
|
24571
|
-
|
|
24830
|
+
if (!msg.ok) {
|
|
24831
|
+
reject(new Error(msg.error || "regex-invalid"));
|
|
24832
|
+
return;
|
|
24833
|
+
}
|
|
24834
|
+
resolve12({
|
|
24835
|
+
...typeof msg.out === "string" ? { out: msg.out } : {},
|
|
24836
|
+
...typeof msg.matched === "boolean" ? { matched: msg.matched } : {},
|
|
24837
|
+
...msg.captures !== void 0 ? { captures: msg.captures } : {}
|
|
24838
|
+
});
|
|
24572
24839
|
}
|
|
24573
24840
|
};
|
|
24574
24841
|
const onError = (error) => {
|
|
@@ -24582,23 +24849,109 @@ function runOnRegexWorker(worker, id2, text, pattern, replacement, deadlineMs) {
|
|
|
24582
24849
|
worker.on("message", onMessage);
|
|
24583
24850
|
worker.once("error", onError);
|
|
24584
24851
|
worker.once("exit", onExit);
|
|
24585
|
-
worker.postMessage({
|
|
24852
|
+
worker.postMessage({
|
|
24853
|
+
id: id2,
|
|
24854
|
+
type,
|
|
24855
|
+
text,
|
|
24856
|
+
pattern,
|
|
24857
|
+
...replacement !== void 0 ? { replacement } : {}
|
|
24858
|
+
});
|
|
24586
24859
|
});
|
|
24587
24860
|
}
|
|
24588
|
-
function
|
|
24861
|
+
function nextJobId() {
|
|
24589
24862
|
const id2 = nextRegexJobId;
|
|
24590
24863
|
nextRegexJobId += 1;
|
|
24864
|
+
return id2;
|
|
24865
|
+
}
|
|
24866
|
+
function runRegexReplace(text, pattern, replacement, deadlineMs) {
|
|
24867
|
+
const id2 = nextJobId();
|
|
24591
24868
|
return bootRegexWorker().then(
|
|
24592
|
-
(worker) => runOnRegexWorker(
|
|
24593
|
-
|
|
24594
|
-
|
|
24595
|
-
|
|
24596
|
-
|
|
24597
|
-
|
|
24598
|
-
|
|
24599
|
-
|
|
24869
|
+
(worker) => runOnRegexWorker(
|
|
24870
|
+
worker,
|
|
24871
|
+
id2,
|
|
24872
|
+
"replace",
|
|
24873
|
+
text,
|
|
24874
|
+
pattern,
|
|
24875
|
+
replacement,
|
|
24876
|
+
deadlineMs
|
|
24877
|
+
).then((result) => {
|
|
24878
|
+
if (typeof result.out !== "string") throw new Error("regex-invalid");
|
|
24879
|
+
return result.out;
|
|
24880
|
+
})
|
|
24881
|
+
);
|
|
24882
|
+
}
|
|
24883
|
+
function capturesFromWorker(captures) {
|
|
24884
|
+
if (captures === null || captures === void 0) return null;
|
|
24885
|
+
return captures.map((part) => part === null ? void 0 : part);
|
|
24886
|
+
}
|
|
24887
|
+
function runRegexTest(text, pattern, deadlineMs) {
|
|
24888
|
+
const id2 = nextJobId();
|
|
24889
|
+
return bootRegexWorker().then(
|
|
24890
|
+
(worker) => runOnRegexWorker(
|
|
24891
|
+
worker,
|
|
24892
|
+
id2,
|
|
24893
|
+
"test",
|
|
24894
|
+
text,
|
|
24895
|
+
pattern,
|
|
24896
|
+
void 0,
|
|
24897
|
+
deadlineMs
|
|
24898
|
+
).then(
|
|
24899
|
+
(result) => result.matched === true,
|
|
24900
|
+
() => false
|
|
24901
|
+
),
|
|
24902
|
+
() => false
|
|
24600
24903
|
);
|
|
24601
24904
|
}
|
|
24905
|
+
function runRegexExec(text, pattern, deadlineMs) {
|
|
24906
|
+
const id2 = nextJobId();
|
|
24907
|
+
return bootRegexWorker().then(
|
|
24908
|
+
(worker) => runOnRegexWorker(
|
|
24909
|
+
worker,
|
|
24910
|
+
id2,
|
|
24911
|
+
"exec",
|
|
24912
|
+
text,
|
|
24913
|
+
pattern,
|
|
24914
|
+
void 0,
|
|
24915
|
+
deadlineMs
|
|
24916
|
+
).then(
|
|
24917
|
+
(result) => capturesFromWorker(result.captures),
|
|
24918
|
+
() => null
|
|
24919
|
+
),
|
|
24920
|
+
() => null
|
|
24921
|
+
);
|
|
24922
|
+
}
|
|
24923
|
+
async function sourceMatchesWithinDeadline(source, url) {
|
|
24924
|
+
if (compileUrlRegex(source.value) === null) return false;
|
|
24925
|
+
const text = sourceMatchText(source, url);
|
|
24926
|
+
if (text === null) return false;
|
|
24927
|
+
return runRegexTest(text, source.value, RUNTIME_LIMITS.maxRegexDeadlineMs);
|
|
24928
|
+
}
|
|
24929
|
+
function matchUrlCapturesWithinDeadline(urlRegex, url) {
|
|
24930
|
+
return runRegexExec(url, urlRegex, RUNTIME_LIMITS.maxRegexDeadlineMs);
|
|
24931
|
+
}
|
|
24932
|
+
var MOCK_LISTENER_PREFIX = "/.rogatio/mock/";
|
|
24933
|
+
function isSingleSegment(value) {
|
|
24934
|
+
return value.length > 0 && value.length <= 2048 && value !== "." && value !== ".." && !value.includes("/") && !value.includes("\\") && !value.includes("?") && !hasControl(value);
|
|
24935
|
+
}
|
|
24936
|
+
function parseMockRedirect(rawUrl) {
|
|
24937
|
+
const queryAt = rawUrl.indexOf("?");
|
|
24938
|
+
const path2 = queryAt === -1 ? rawUrl : rawUrl.slice(0, queryAt);
|
|
24939
|
+
if (!path2.startsWith(MOCK_LISTENER_PREFIX)) return null;
|
|
24940
|
+
const rest = path2.slice(MOCK_LISTENER_PREFIX.length);
|
|
24941
|
+
const slash = rest.indexOf("/");
|
|
24942
|
+
if (slash <= 0) return null;
|
|
24943
|
+
if (rest.indexOf("/", slash + 1) !== -1) return null;
|
|
24944
|
+
let token;
|
|
24945
|
+
let digest;
|
|
24946
|
+
try {
|
|
24947
|
+
token = decodeURIComponent(rest.slice(0, slash));
|
|
24948
|
+
digest = decodeURIComponent(rest.slice(slash + 1));
|
|
24949
|
+
} catch {
|
|
24950
|
+
return null;
|
|
24951
|
+
}
|
|
24952
|
+
if (!isSingleSegment(token) || !isSingleSegment(digest)) return null;
|
|
24953
|
+
return { token, digest };
|
|
24954
|
+
}
|
|
24602
24955
|
function supportedContentType(value) {
|
|
24603
24956
|
if (value === void 0) return false;
|
|
24604
24957
|
const mediaType = value.split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
@@ -24630,7 +24983,7 @@ async function rewriteRequestBody(input, action, captureContext) {
|
|
|
24630
24983
|
}
|
|
24631
24984
|
outputText = action.body;
|
|
24632
24985
|
if (captureContext !== void 0) {
|
|
24633
|
-
const captures =
|
|
24986
|
+
const captures = await matchUrlCapturesWithinDeadline(
|
|
24634
24987
|
captureContext.urlRegex,
|
|
24635
24988
|
captureContext.url
|
|
24636
24989
|
);
|
|
@@ -24870,7 +25223,7 @@ async function rewriteResponseBody(input, replacements, replaceAction, captureCo
|
|
|
24870
25223
|
if (captureContext === void 0) {
|
|
24871
25224
|
text = replaceAction.body;
|
|
24872
25225
|
} else {
|
|
24873
|
-
const captures =
|
|
25226
|
+
const captures = await matchUrlCapturesWithinDeadline(
|
|
24874
25227
|
captureContext.urlRegex,
|
|
24875
25228
|
captureContext.url
|
|
24876
25229
|
);
|
|
@@ -24902,8 +25255,11 @@ async function rewriteResponseBody(input, replacements, replaceAction, captureCo
|
|
|
24902
25255
|
}
|
|
24903
25256
|
};
|
|
24904
25257
|
}
|
|
24905
|
-
function replaceResponseBody(body, contentType, captureContext) {
|
|
24906
|
-
const captures = captureContext === void 0 ? [] :
|
|
25258
|
+
async function replaceResponseBody(body, contentType, captureContext) {
|
|
25259
|
+
const captures = captureContext === void 0 ? [] : await matchUrlCapturesWithinDeadline(
|
|
25260
|
+
captureContext.urlRegex,
|
|
25261
|
+
captureContext.url
|
|
25262
|
+
);
|
|
24907
25263
|
if (captureContext !== void 0 && captures === null) {
|
|
24908
25264
|
return failure("runtime.url-capture-mismatch");
|
|
24909
25265
|
}
|
|
@@ -24925,7 +25281,7 @@ async function fetchAndRewriteAuthorizedResponse(operation, action, options = {}
|
|
|
24925
25281
|
const response = await fetchAuthorized(operation, options);
|
|
24926
25282
|
if (!response.ok) return response;
|
|
24927
25283
|
const contentType = responseHeader(response.value.headers, "content-type");
|
|
24928
|
-
const transformed = isReplaceAction(action) ? replaceResponseBody(
|
|
25284
|
+
const transformed = isReplaceAction(action) ? await replaceResponseBody(
|
|
24929
25285
|
action.body,
|
|
24930
25286
|
contentType,
|
|
24931
25287
|
operation.sourceValue === void 0 ? void 0 : { url: operation.target, urlRegex: operation.sourceValue }
|
|
@@ -24995,7 +25351,7 @@ function projectHasRule(project, groupId, ruleId) {
|
|
|
24995
25351
|
function isBodyOperation(operation) {
|
|
24996
25352
|
return operation.kind === "request-body" || operation.kind === "response-body";
|
|
24997
25353
|
}
|
|
24998
|
-
function revalidateAuthority(project, operations, request) {
|
|
25354
|
+
async function revalidateAuthority(project, operations, request) {
|
|
24999
25355
|
const projectSnap = snapshotOwnData3(project);
|
|
25000
25356
|
if (!projectSnap.valid) return { allowed: false, reason: "project-invalid" };
|
|
25001
25357
|
const opsSnap = snapshotOwnData3(operations);
|
|
@@ -25016,7 +25372,7 @@ function revalidateAuthority(project, operations, request) {
|
|
|
25016
25372
|
return { allowed: false, reason: "project-inconsistent" };
|
|
25017
25373
|
}
|
|
25018
25374
|
const matcher = operation.matcher;
|
|
25019
|
-
if (!
|
|
25375
|
+
if (!await sourceMatchesWithinDeadline(matcher.source, request.url)) {
|
|
25020
25376
|
return { allowed: false, reason: "url-mismatch" };
|
|
25021
25377
|
}
|
|
25022
25378
|
const requestOrigin = originOf(request.url);
|
|
@@ -25056,18 +25412,19 @@ function revalidateAuthority(project, operations, request) {
|
|
|
25056
25412
|
function isBodyOp(op) {
|
|
25057
25413
|
return op.kind === "request-body" || op.kind === "response-body";
|
|
25058
25414
|
}
|
|
25059
|
-
function matcherMatches(op, url, method) {
|
|
25060
|
-
if (!
|
|
25415
|
+
async function matcherMatches(op, url, method) {
|
|
25416
|
+
if (!await sourceMatchesWithinDeadline(op.matcher.source, url))
|
|
25417
|
+
return false;
|
|
25061
25418
|
if (op.matcher.method !== void 0 && op.matcher.method !== method.toUpperCase()) {
|
|
25062
25419
|
return false;
|
|
25063
25420
|
}
|
|
25064
25421
|
return true;
|
|
25065
25422
|
}
|
|
25066
|
-
function pickHighest(operations, kind, url, method) {
|
|
25423
|
+
async function pickHighest(operations, kind, url, method) {
|
|
25067
25424
|
let best = null;
|
|
25068
25425
|
for (const op of operations) {
|
|
25069
25426
|
if (!isBodyOp(op) || op.kind !== kind) continue;
|
|
25070
|
-
if (!matcherMatches(op, url, method)) continue;
|
|
25427
|
+
if (!await matcherMatches(op, url, method)) continue;
|
|
25071
25428
|
if (best === null || op.matcher.priority > best.matcher.priority || op.matcher.priority === best.matcher.priority && op.ruleId.localeCompare(best.ruleId) < 0) {
|
|
25072
25429
|
best = op;
|
|
25073
25430
|
}
|
|
@@ -25436,17 +25793,21 @@ function initiatorFromHeaders(headers, targetUrl) {
|
|
|
25436
25793
|
return void 0;
|
|
25437
25794
|
}
|
|
25438
25795
|
}
|
|
25439
|
-
function authorizeOp(policy, op, url, method, headers) {
|
|
25796
|
+
async function authorizeOp(policy, op, url, method, headers) {
|
|
25440
25797
|
const resourceType = op.matcher.resourceTypes[0];
|
|
25441
25798
|
const initiator = initiatorFromHeaders(headers, url);
|
|
25442
|
-
const decision = revalidateAuthority(
|
|
25443
|
-
|
|
25444
|
-
|
|
25445
|
-
|
|
25446
|
-
|
|
25447
|
-
|
|
25448
|
-
|
|
25449
|
-
|
|
25799
|
+
const decision = await revalidateAuthority(
|
|
25800
|
+
policy.project,
|
|
25801
|
+
policy.operations,
|
|
25802
|
+
{
|
|
25803
|
+
groupId: op.groupId,
|
|
25804
|
+
ruleId: op.ruleId,
|
|
25805
|
+
url,
|
|
25806
|
+
method,
|
|
25807
|
+
...initiator !== void 0 ? { initiator } : {},
|
|
25808
|
+
...resourceType !== void 0 ? { resourceType } : {}
|
|
25809
|
+
}
|
|
25810
|
+
);
|
|
25450
25811
|
return decision.allowed;
|
|
25451
25812
|
}
|
|
25452
25813
|
async function startInterceptProxy(options = {}) {
|
|
@@ -25494,13 +25855,13 @@ async function startInterceptProxy(options = {}) {
|
|
|
25494
25855
|
}
|
|
25495
25856
|
const method = (req.method ?? "GET").toUpperCase();
|
|
25496
25857
|
const active = policy;
|
|
25497
|
-
const requestOp = active === null ? null : pickHighest(
|
|
25858
|
+
const requestOp = active === null ? null : await pickHighest(
|
|
25498
25859
|
active.operations,
|
|
25499
25860
|
"request-body",
|
|
25500
25861
|
targetUrl,
|
|
25501
25862
|
method
|
|
25502
25863
|
);
|
|
25503
|
-
const responseOp = active === null ? null : pickHighest(
|
|
25864
|
+
const responseOp = active === null ? null : await pickHighest(
|
|
25504
25865
|
active.operations,
|
|
25505
25866
|
"response-body",
|
|
25506
25867
|
targetUrl,
|
|
@@ -25520,7 +25881,13 @@ async function startInterceptProxy(options = {}) {
|
|
|
25520
25881
|
}
|
|
25521
25882
|
let requestBody = bodyResult.body;
|
|
25522
25883
|
if (needsRequestBody && requestOp !== null && active !== null) {
|
|
25523
|
-
if (!authorizeOp(
|
|
25884
|
+
if (!await authorizeOp(
|
|
25885
|
+
active,
|
|
25886
|
+
requestOp,
|
|
25887
|
+
targetUrl,
|
|
25888
|
+
method,
|
|
25889
|
+
req.headers
|
|
25890
|
+
)) {
|
|
25524
25891
|
} else {
|
|
25525
25892
|
const rewritten = await rewriteRequestBody(
|
|
25526
25893
|
{
|
|
@@ -25569,7 +25936,13 @@ async function startInterceptProxy(options = {}) {
|
|
|
25569
25936
|
let responseBody = upstream.body;
|
|
25570
25937
|
if (responseOp !== null && active !== null) {
|
|
25571
25938
|
if (responseBody.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes) {
|
|
25572
|
-
} else if (!authorizeOp(
|
|
25939
|
+
} else if (!await authorizeOp(
|
|
25940
|
+
active,
|
|
25941
|
+
responseOp,
|
|
25942
|
+
targetUrl,
|
|
25943
|
+
method,
|
|
25944
|
+
req.headers
|
|
25945
|
+
)) {
|
|
25573
25946
|
} else {
|
|
25574
25947
|
const action = responseOp.responseBody;
|
|
25575
25948
|
const isReplace = "mode" in action && action.mode === "replace";
|
|
@@ -25693,7 +26066,10 @@ async function startInterceptProxy(options = {}) {
|
|
|
25693
26066
|
const operation = active.operations.find(
|
|
25694
26067
|
(op) => op.kind === "response-body" && op.ruleId === parsed.ruleId
|
|
25695
26068
|
);
|
|
25696
|
-
if (operation === void 0 || !
|
|
26069
|
+
if (operation === void 0 || !await sourceMatchesWithinDeadline(
|
|
26070
|
+
operation.matcher.source,
|
|
26071
|
+
parsed.originalUrl
|
|
26072
|
+
)) {
|
|
25697
26073
|
res.writeHead(404);
|
|
25698
26074
|
res.end();
|
|
25699
26075
|
return;
|
|
@@ -25709,15 +26085,19 @@ async function startInterceptProxy(options = {}) {
|
|
|
25709
26085
|
res.end();
|
|
25710
26086
|
return;
|
|
25711
26087
|
}
|
|
25712
|
-
const allowed = revalidateAuthority(
|
|
25713
|
-
|
|
25714
|
-
|
|
25715
|
-
|
|
25716
|
-
|
|
25717
|
-
|
|
25718
|
-
|
|
25719
|
-
|
|
25720
|
-
|
|
26088
|
+
const allowed = await revalidateAuthority(
|
|
26089
|
+
active.project,
|
|
26090
|
+
active.operations,
|
|
26091
|
+
{
|
|
26092
|
+
groupId: operation.groupId,
|
|
26093
|
+
ruleId: operation.ruleId,
|
|
26094
|
+
url: parsed.originalUrl,
|
|
26095
|
+
target,
|
|
26096
|
+
method: "GET",
|
|
26097
|
+
initiator: initiatorFromHeaders(req.headers, parsed.originalUrl) ?? new URL(target).origin,
|
|
26098
|
+
resourceType: operation.matcher.resourceTypes[0]
|
|
26099
|
+
}
|
|
26100
|
+
);
|
|
25721
26101
|
if (!allowed.allowed) {
|
|
25722
26102
|
res.writeHead(403);
|
|
25723
26103
|
res.end();
|
|
@@ -33142,10 +33522,10 @@ function reportTrust(subcommand, result, okMessage) {
|
|
|
33142
33522
|
const reasons = result.reasons ?? ["unknown"];
|
|
33143
33523
|
console.error(`trust unsupported: ${reasons.join(", ")}`);
|
|
33144
33524
|
const hints = {
|
|
33145
|
-
"tooling-missing": "Hint: install required tooling (macOS: security; Linux: update-ca-certificates; Windows: certutil is built-in)",
|
|
33146
|
-
"manifest-dir-unwritable": "Hint: check permissions on
|
|
33525
|
+
"tooling-missing": "Hint: install required tooling (macOS: security; Linux: update-ca-certificates or update-ca-trust; Windows: certutil is built-in)",
|
|
33526
|
+
"manifest-dir-unwritable": "Hint: check permissions on the browser NativeMessagingHosts directory (Google Chrome or Chromium) or run with appropriate access",
|
|
33147
33527
|
"keychain-unwritable": "Hint: macOS login keychain not writable; try running with appropriate keychain access or use sudo for system keychain",
|
|
33148
|
-
"ca-store-unwritable": "Hint: /usr/local/share/ca-certificates
|
|
33528
|
+
"ca-store-unwritable": "Hint: the CA trust store is not writable, or this system has no supported anchors directory. Debian uses /usr/local/share/ca-certificates. Arch uses /etc/ca-certificates/trust-source/anchors. Fedora and RHEL use /etc/pki/ca-trust/source/anchors",
|
|
33149
33529
|
"elevation-required": "Hint: device-local CA trust requires root (Linux: sudo, macOS: keychain password, Windows: Administrator). Re-run with elevated privileges"
|
|
33150
33530
|
};
|
|
33151
33531
|
for (const reason of reasons) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rogatio/cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Local-first browser request and response rules — editor host, file verification, test runner, and runtime dispatch.",
|
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
|
+
"main": "./dist/node/index.js",
|
|
24
|
+
"types": "./dist/node/index.d.ts",
|
|
23
25
|
"exports": {
|
|
24
26
|
".": {
|
|
25
|
-
"types": "./
|
|
27
|
+
"types": "./dist/node/index.d.ts",
|
|
26
28
|
"import": "./dist/node/index.js"
|
|
27
29
|
}
|
|
28
30
|
},
|