Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add possibility to ignore unsupported fuses #11

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ if (mode === 'read') {

getCurrentFuseWire(argv.app)
.then((config) => {
const { version, resetAdHocDarwinSignature, ...rest } = config;
const { version, resetAdHocDarwinSignature, ignoreUnsupportedFuses, ...rest } = config;
console.log(`Fuse Version: ${chalk.cyan(`v${version}`)}`);

switch (config.version) {
Expand Down Expand Up @@ -101,7 +101,7 @@ if (mode === 'read') {

getCurrentFuseWire(argv.app)
.then((config) => {
const { version, resetAdHocDarwinSignature, ...rest } = config;
const { version } = config;
console.log(`Fuse Version: ${chalk.cyan(`v${version}`)}`);

const keyPairs = argv._ || [];
Expand Down Expand Up @@ -155,10 +155,11 @@ if (mode === 'read') {
console.log('Writing to app:', chalk.cyan(path.basename(argv.app!)));

function adaptConfig(config: FuseConfig<FuseState>): FuseConfig<boolean> {
const { version, resetAdHocDarwinSignature, ...rest } = config;
const { version, resetAdHocDarwinSignature, ignoreUnsupportedFuses, ...rest } = config;
const fuseConfig: FuseConfig<boolean> = {
version,
resetAdHocDarwinSignature,
ignoreUnsupportedFuses,
};

for (const key of Object.keys(rest)) {
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export enum FuseV1Options {
export type FuseV1Config<T = boolean> = {
version: FuseVersion.V1;
resetAdHocDarwinSignature?: boolean;
ignoreUnsupportedFuses?: boolean;
} & Partial<Record<FuseV1Options, T>>;

export type FuseConfig<T = boolean> = FuseV1Config<T>;
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const buildFuseV1Wire = (config: FuseV1Config, wireLength: number) => {
const badFuseOption = Object.keys(nonVersionConfig).find(
(fuseOption) => parseInt(fuseOption, 10) >= wireLength,
);
if (badFuseOption !== undefined) {
if (badFuseOption !== undefined && !config.ignoreUnsupportedFuses) {
throw new Error(
`Trying to configure ${
FuseV1Options[badFuseOption as any]
Expand Down Expand Up @@ -124,7 +124,7 @@ export const getCurrentFuseWire = async (

if (fuseWirePosition - SENTINEL.length === -1) {
throw new Error(
'Could not find sentinel in the provided ELectron binary, fuses are only supported in Electron 12 and higher',
'Could not find sentinel in the provided Electron binary, fuses are only supported in Electron 12 and higher',
);
}
const fuseWireVersion = (electron[fuseWirePosition] as any) as FuseVersion;
Expand Down
47 changes: 40 additions & 7 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('getCurrentFuseWire()', () => {
});

it('should return the expected defaults for Electron v20.0.0', async () => {
const electronPath = await getElectronLocally('20.0.0', 'darwin', 'x64');
const electronPath = await getElectronLocally('20.0.0', process.platform, process.arch);
expect(readableFuseWire(await getCurrentFuseWire(electronPath))).toMatchInlineSnapshot(`
{
"EnableCookieEncryption": "DISABLE",
Expand All @@ -35,16 +35,18 @@ describe('getCurrentFuseWire()', () => {
});

for (const [platform, arch] of supportedPlatforms) {
it(`should work on ${platform}/${arch}`, async () => {
const electronPath = await getElectronLocally('20.0.0', platform, arch);
await expect(getCurrentFuseWire(electronPath)).resolves.toBeTruthy();
});
if (process.platform === platform) {
it(`should work on ${platform}/${arch}`, async () => {
const electronPath = await getElectronLocally('20.0.0', platform, arch);
await expect(getCurrentFuseWire(electronPath)).resolves.toBeTruthy();
});
}
}
});

describe('flipFuses()', () => {
it('should allow toggling a single fuse', async () => {
const electronPath = await getElectronLocally('20.0.0', 'darwin', 'x64');
const electronPath = await getElectronLocally('20.0.0', process.platform, process.arch);
expect((await getCurrentFuseWire(electronPath))[FuseV1Options.EnableCookieEncryption]).toEqual(
FuseState.DISABLE,
);
Expand All @@ -59,7 +61,7 @@ describe('flipFuses()', () => {
});

it('should allow toggling multiple fuses', async () => {
const electronPath = await getElectronLocally('20.0.0', 'darwin', 'x64');
const electronPath = await getElectronLocally('20.0.0', process.platform, process.arch);
expect((await getCurrentFuseWire(electronPath))[FuseV1Options.EnableCookieEncryption]).toEqual(
FuseState.DISABLE,
);
Expand All @@ -79,6 +81,37 @@ describe('flipFuses()', () => {
).toEqual(FuseState.ENABLE);
});

it('should throw exception by default if unsupported fuse is specified', async () => {
const electronPath = await getElectronLocally('20.0.0', process.platform, process.arch);
const fuseConfig = await getCurrentFuseWire(electronPath);
expect(FuseV1Options.LoadBrowserProcessSpecificV8Snapshot in fuseConfig).toBeFalsy();

await expect(
flipFuses(electronPath, {
version: FuseVersion.V1,
[FuseV1Options.LoadBrowserProcessSpecificV8Snapshot]: true,
}),
).rejects.toThrow('LoadBrowserProcessSpecificV8Snapshot');
});

it('should toggle only supported fuses if ignoreNotSupportedFuses is true', async () => {
const electronPath = await getElectronLocally('20.0.0', process.platform, process.arch);
const fuseConfig = await getCurrentFuseWire(electronPath);
expect(FuseV1Options.LoadBrowserProcessSpecificV8Snapshot in fuseConfig).toBeFalsy();
expect(fuseConfig[FuseV1Options.EnableCookieEncryption]).toEqual(FuseState.DISABLE);

await flipFuses(electronPath, {
version: FuseVersion.V1,
ignoreUnsupportedFuses: true,
[FuseV1Options.EnableCookieEncryption]: true,
[FuseV1Options.LoadBrowserProcessSpecificV8Snapshot]: true,
});

const newFuseConfig = await getCurrentFuseWire(electronPath);
expect(FuseV1Options.LoadBrowserProcessSpecificV8Snapshot in newFuseConfig).toBeFalsy();
expect(newFuseConfig[FuseV1Options.EnableCookieEncryption]).toEqual(FuseState.ENABLE);
});

if (process.platform === 'darwin') {
it('should work on universal macOS applications', async () => {
const electronPathX64 = await getElectronLocally('20.0.0', 'darwin', 'x64');
Expand Down