Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ See [Translation Guide](docs/Translation.md).

## Build and Dev-server Instructions

To get started, install Node.js 22.12.0 or newer with npm 10 or newer; they come together as a package and can be found [here](https://nodejs.org). You will then need to clone this repository, cd into the NexusInterface dir, run `npm install`, then run `npm run dev` and the dev server will spin up launching the app for you.
To get started, install Node.js 22.12.0 or newer and npm 10.9.0 or newer. This repository currently builds against Electron 43. Clone this repository, cd into the NexusInterface directory, run `npm install`, then run `npm run dev` and the dev server will spin up launching the app for you.

To test a production build run `npm run package` and navigate to the _release_ directory in the root of the project and install as you would any other program.

Expand Down
1 change: 1 addition & 0 deletions configs/webpack.config.renderer.prod.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default merge(baseRendererConfig, prodConfig, {
entry: {
'renderer.prod': './src/index.js',
'keyboard.prod': './src/keyboard/index.tsx',
'keyboard_preload.prod': './src/keyboard/preload.js',
},

output: {
Expand Down
66 changes: 66 additions & 0 deletions docs/Detail_Document.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Detail Document: Core Binary and Electron IPC Hardening

## Purpose

This document records the detail-level scope for the branch after updating from the recent `Merging` branch PR merges:

- PR #15: analysis and implementation plan for repository issues
- PR #16: Core binary validation and process detection fixes
- PR #17: incremental Electron window IPC hardening

The remaining branch work focuses on preserving those merged changes while tightening validation around Core binary configuration, process lookup, privileged IPC handlers, and the Core settings UI.

## Current Problem Areas

### Core binary configuration

The wallet can use either the bundled Nexus Core binary or an override supplied by `NEXUS_CORE_BINARY_PATH`, `NEXUS_CORE_BINARY`, or the Core settings screen. The unsafe cases are malformed paths, relative paths, directories, non-executable POSIX files, and non-`.exe` Windows targets.

The branch normalizes configured paths, handles matching shell quotes and `~` home-directory prefixes, requires absolute paths, and returns structured Core binary status data for UI and startup error messages.

### Core process detection

Core shutdown and running-state detection must identify the intended Nexus Core process without matching unrelated processes by substring. The branch parses process-list output, ignores PID 1, parses Windows CSV task output, and compares commands against the configured binary path and binary name.

### Privileged Electron IPC

Renderer-accessible IPC calls must not forward arbitrary object shapes, paths, menu templates, or protocol values directly into main-process Electron APIs. The branch adds type and allowlist checks for dialog options, app path names, menu roles, virtual keyboard options, Core parameters, updater booleans, file server inputs, context menu webContents ownership, and proxy request URLs.

### Core binary settings UI

The Core settings screen needs an explicit way to choose an external Core binary without forcing users to type paths manually. The branch keeps the Core Binary Path field and adds a Browse button that writes the selected file path into the existing settings form field.

## Implementation Summary

- `src/main/core.js`
- Adds Core binary path normalization and structured binary status reporting.
- Validates file existence, absolute paths, file-vs-directory state, POSIX execute permission, and Windows executable extension.
- Improves running-process lookup for Windows, macOS, and Linux.
- Makes Core shutdown a no-op when no Core PID is found.

- `src/main/main.js`
- Adds explicit sanitizers for renderer IPC inputs.
- Restricts dialog, app path, menu, updater, file-server, Core, keyboard, webContents, and proxy request inputs before they reach privileged APIs.

- `src/App/Settings/Core/EmbeddedCoreSettings.tsx`
- Adds a Browse button for `embeddedCoreBinaryPath`.
- Updates the active form field directly when a Core binary is selected.

- `package.json` and `package-lock.json`
- Keep the runtime requirement aligned with Node `>=22.12.0` and npm `>=10.9.0`.

- `README.md`
- Keeps setup instructions aligned with the current Node, npm, and Electron requirements.

## Validation Expectations

- Install dependencies with `npm install`.
- Build production bundles with `npm run build`.
- Confirm the build includes the main, renderer, module preload, and window preload bundles.
- Treat existing dependency audit findings as pre-existing unless a dependency is added or updated.

## Review Notes

- The branch intentionally keeps a single PR scope because the merged base changes and the follow-up hardening overlap in Core startup, Core settings, and Electron IPC.
- No new runtime dependencies are required.
- The highest-risk areas for review are Core process matching edge cases and Electron IPC input compatibility with existing renderer callers.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@
},
"engines": {
"node": ">=22.12.0",
"npm": ">=10.x"
"npm": ">=10.9.0"
},
"overrides": {
"react": "$react",
Expand Down
54 changes: 25 additions & 29 deletions src/App/Settings/Core/EmbeddedCoreSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'path';
import { ipcRenderer } from 'electron';
import { useField } from 'react-final-form';

import Form from 'components/Form';
import SettingsField from 'components/SettingsField';
Expand Down Expand Up @@ -68,19 +69,7 @@ export default function EmbeddedCoreSettings() {
'Optional path to a Nexus Core binary to use instead of the bundled binary'
)}
>
<div className="flex stretch">
<Form.TextField
name="embeddedCoreBinaryPath"
style={{ flexGrow: 1 }}
/>
<Button
fitHeight
onClick={browseCoreBinary}
style={{ marginLeft: '1em' }}
>
{__('Browse')}
</Button>
</div>
<CoreBinaryPathField />
</SettingsField>

<TestnetSettings />
Expand All @@ -105,31 +94,38 @@ export default function EmbeddedCoreSettings() {
);
}

async function browseCoreBinary() {
let paths;
try {
paths = await ipcRenderer.invoke('show-open-dialog', {
function CoreBinaryPathField() {
const { input } = useField('embeddedCoreBinaryPath');

const pickCoreBinary = async () => {
const filePaths = await ipcRenderer.invoke('show-open-dialog', {
title: __('Select Nexus Core binary'),
properties: ['openFile'],
filters:
process.platform === 'win32'
? [{ name: 'Windows executable', extensions: ['exe'] }]
: undefined,
});
} catch (err: unknown) {
openErrorDialog({
message: __('Failed to open file picker') + ': ' + getErrorMessage(err),
});
return;
}

if (paths && paths[0]) {
updateSettings({ embeddedCoreBinaryPath: paths[0] });
}
}
if (filePaths?.[0]) {
input.onChange(filePaths[0]);
}
};
Comment on lines +100 to +113

function getErrorMessage(err: unknown) {
return err instanceof Error ? err.message : String(err);
return (
<div style={{ display: 'flex', width: '100%' }}>
<Form.TextField
name="embeddedCoreBinaryPath"
style={{ flexGrow: 1 }}
/>
<Button
onClick={pickCoreBinary}
style={{ height: consts.inputHeightEm + 'em', marginLeft: '0.5em' }}
>
{__('Browse')}
</Button>
</div>
);
}

function BasicSettings() {
Expand Down
Loading