Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ee024f9
fix: clarify Pro2 firmware update workflow guard
wabicai Aug 7, 2026
8727b08
Merge branch 'hotfix/v6.5.2' into fix/firmware-upgrade-pro2
wabicai Aug 8, 2026
aaf1141
refactor: migrate desktop and webembed to rspack v2 (#12427)
huhuanming Jul 15, 2026
61702a7
fix: align rspack production config with x
wabicai Aug 8, 2026
777b993
fix: correct Pro2 portfolio currency conversion
wabicai Aug 8, 2026
d6432bd
docs: translate firmware workflow comments
wabicai Aug 8, 2026
9b83ab0
fix: address Pro2 firmware workflow review feedback
wabicai Aug 8, 2026
1c1cc48
fix: keep switched firmware wallets manageable
wabicai Aug 8, 2026
868350b
fix: support manifest-driven Pro2 resources
wabicai Aug 8, 2026
ac49ba2
fix: align Pro2 and Neo firmware update titles
wabicai Aug 8, 2026
b99f8d4
fix: sync locale translations
wabicai Aug 8, 2026
73ccaa1
chore: merge hotfix/v6.5.2
wabicai Aug 8, 2026
cfe579e
fix: load protocol v2 resource archives
wabicai Aug 8, 2026
987590d
fix: enable remote resource archive updates
wabicai Aug 8, 2026
8072f02
fix: address firmware update review feedback
wabicai Aug 8, 2026
4c7dd2c
chore: align hardware sdk alpha versions
wabicai Aug 8, 2026
620f7a9
fix: show protocol v2 update versions
wabicai Aug 8, 2026
f4b326c
fix: mark resource archive download state
wabicai Aug 8, 2026
b20afe5
fix: show protocol v2 component versions
wabicai Aug 8, 2026
3788f84
fix: harden protocol v2 firmware updates
wabicai Aug 8, 2026
043e751
chore: remove unrelated locale changes
wabicai Aug 8, 2026
d88f785
chore: align locale with hotfix base
wabicai Aug 8, 2026
a644f11
fix: honor protocol v2 forced update targets
wabicai Aug 8, 2026
70c825e
fix: handle protocol v2 resource update overrides
wabicai Aug 8, 2026
5393997
chore: update hardware sdk to 1.2.0-alpha.84
wabicai Aug 8, 2026
c432fa7
refactor: route firmware artifacts through unified downloader
wabicai Aug 8, 2026
e4fe0b8
fix: validate protocol v2 plan targets exactly
wabicai Aug 8, 2026
ea0e866
fix: bind firmware host to prepared plan
wabicai Aug 9, 2026
dee6fe8
fix: allow current firmware artifact host
wabicai Aug 9, 2026
8c52b59
fix: compare Protocol V2 resources by default
wabicai Aug 9, 2026
40ca854
chore: update hardware sdk to 1.2.0-alpha.86
wabicai Aug 9, 2026
e0b9f58
chore: update hardware sdk to 1.2.0-alpha.87
wabicai Aug 9, 2026
cd8b4d0
fix: allow pre-release firmware artifact hosts in developer mode (#12…
originalix Aug 9, 2026
6b655d7
fix: validate Protocol V2 firmware plans early
wabicai Aug 9, 2026
8fd41bb
chore: fix firmware artifact lint wording
wabicai Aug 9, 2026
583d3d6
fix: consume prepared plans without duplicate inputs
wabicai Aug 9, 2026
69eaf7c
style: format prepared plan assertion
wabicai Aug 9, 2026
af5b419
fix: address protocol v2 firmware review
wabicai Aug 9, 2026
4ea6512
chore: fix firmware UI test import order
wabicai Aug 9, 2026
56c831a
fix: support serial-less protocol v2 updates
wabicai Aug 9, 2026
567687f
chore: update hardware sdk to 1.2.0-alpha.92
wabicai Aug 9, 2026
7432a03
chore: update hardware sdk to alpha.98
wabicai Aug 9, 2026
d245846
chore: update hardware sdk to alpha.99
wabicai Aug 10, 2026
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
6 changes: 3 additions & 3 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
},
"dependencies": {
"@napi-rs/keyring": "^1.3.0",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.77",
"@onekeyfe/hd-core": "1.2.0-alpha.77",
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.77",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.99",
"@onekeyfe/hd-core": "1.2.0-alpha.99",
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.99",
"proper-lockfile": "^4.1.2"
}
}
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"clean": "rimraf ./build-electron && rimraf .tamagui && rimraf ./app/build && rimraf ./app/dist && rimraf __generated__",
"clean:build": "rimraf ./build-electron && rimraf ./app/build && rimraf ./app/dist && rimraf ./node_modules/.cache",
"start": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" yarn dev",
"start:rspack": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" yarn dev:rspack",
"start:rspack": "cross-env NODE_OPTIONS=\"--max-old-space-size=16384\" yarn dev:rspack",
"install-app-deps": "electron-builder install-app-deps && node scripts/apply-runtime-patches.js && node scripts/verify-runtime-patches.js",
"dev": "npx concurrently \"yarn build:main:dev\" \"yarn dev:renderer\" \"cross-env LAUNCH_ELECTRON=true node scripts/dev.js\"",
"dev:rspack": "npx concurrently \"yarn build:main:dev\" \"yarn dev:renderer:rspack\" \"cross-env LAUNCH_ELECTRON=true node scripts/dev.js\"",
Expand Down
1 change: 0 additions & 1 deletion apps/web-embed/postbuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ echo "Syncing web-build to iOS assets..."
rsync -r -c -v ./web-build/ ../mobile/ios/OneKeyWallet/web-embed/

echo "Postbuild completed successfully."

40 changes: 20 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,21 +158,21 @@
"@onekeyfe/cross-inpage-provider-injected": "2.2.73",
"@onekeyfe/cross-inpage-provider-types": "2.2.73",
"@onekeyfe/extension-bridge-hosted": "2.2.73",
"@onekeyfe/hd-ble-sdk": "1.2.0-alpha.77",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.77",
"@onekeyfe/hd-core": "1.2.0-alpha.77",
"@onekeyfe/hd-shared": "1.2.0-alpha.77",
"@onekeyfe/hd-transport": "1.2.0-alpha.77",
"@onekeyfe/hd-transport-electron": "1.2.0-alpha.77",
"@onekeyfe/hd-web-sdk": "1.2.0-alpha.77",
"@onekeyfe/hwk-adapter-core": "1.2.0-alpha.77",
"@onekeyfe/hwk-ledger-adapter": "1.2.0-alpha.77",
"@onekeyfe/hwk-ledger-connector-ble": "1.2.0-alpha.77",
"@onekeyfe/hwk-ledger-connector-webhid": "1.2.0-alpha.77",
"@onekeyfe/hwk-trezor-adapter": "1.2.0-alpha.77",
"@onekeyfe/hwk-trezor-connector-electron-ble": "1.2.0-alpha.77",
"@onekeyfe/hwk-trezor-connector-rn-ble": "1.2.0-alpha.77",
"@onekeyfe/hwk-trezor-connector-webusb": "1.2.0-alpha.77",
"@onekeyfe/hd-ble-sdk": "1.2.0-alpha.99",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.99",
"@onekeyfe/hd-core": "1.2.0-alpha.99",
"@onekeyfe/hd-shared": "1.2.0-alpha.99",
"@onekeyfe/hd-transport": "1.2.0-alpha.99",
"@onekeyfe/hd-transport-electron": "1.2.0-alpha.99",
"@onekeyfe/hd-web-sdk": "1.2.0-alpha.99",
"@onekeyfe/hwk-adapter-core": "1.2.0-alpha.99",
"@onekeyfe/hwk-ledger-adapter": "1.2.0-alpha.99",
"@onekeyfe/hwk-ledger-connector-ble": "1.2.0-alpha.99",
"@onekeyfe/hwk-ledger-connector-webhid": "1.2.0-alpha.99",
"@onekeyfe/hwk-trezor-adapter": "1.2.0-alpha.99",
"@onekeyfe/hwk-trezor-connector-electron-ble": "1.2.0-alpha.99",
"@onekeyfe/hwk-trezor-connector-rn-ble": "1.2.0-alpha.99",
"@onekeyfe/hwk-trezor-connector-webusb": "1.2.0-alpha.99",
"@onekeyfe/onekey-cross-webview": "2.2.73",
"@polkadot/extension-inject": "0.54.1",
"@polkadot/types": "14.3.1",
Expand Down Expand Up @@ -416,11 +416,11 @@
"@reown/appkit-ethers5-react-native": "https://github.com/OneKeyHQ/app-modules#9d96daccc13625e5b3c8b236f9357956b049b884",
"@reown/appkit-scaffold-react-native": "https://github.com/OneKeyHQ/app-modules#ef39e1c6682f8b50dc019a851f6e2211392d353a",
"@reown/appkit-scaffold-utils-react-native": "https://github.com/OneKeyHQ/app-modules#aa31ef69e5058bb822c40f0a706ee9bdd191b005",
"@onekeyfe/hd-core": "1.2.0-alpha.77",
"@onekeyfe/hd-shared": "1.2.0-alpha.77",
"@onekeyfe/hd-transport": "1.2.0-alpha.77",
"@onekeyfe/hd-transport-http": "1.2.0-alpha.77",
"@onekeyfe/hd-transport-web-device": "1.2.0-alpha.77",
"@onekeyfe/hd-core": "1.2.0-alpha.99",
"@onekeyfe/hd-shared": "1.2.0-alpha.99",
"@onekeyfe/hd-transport": "1.2.0-alpha.99",
"@onekeyfe/hd-transport-http": "1.2.0-alpha.99",
"@onekeyfe/hd-transport-web-device": "1.2.0-alpha.99",
"promise": "^8.3.0",
"metro": "0.83.2",
"metro-babel-transformer": "0.83.2",
Expand Down
141 changes: 139 additions & 2 deletions packages/kit-bg/src/desktopApis/DesktopApiFirmwareArtifact.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@ describe('DesktopApiFirmwareArtifact URL admission', () => {
new URL('https://web.onekey-asset.com/firmware.bin'),
),
).toBe(true);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://common.onekey-asset.com/firmware.bin'),
),
).toBe(true);
expect(
isFirmwareArtifactUrlAllowed(
new URL(
'https://pub-d5c080673b4e4e9dae7e03680340378d.r2.dev/firmware.bin',
'https://pub-568cac7a13bf4c42b7a8113ffffc6793.r2.dev/firmware.bin',
),
),
).toBe(true);
).toBe(false);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://web.onekey-asset.com.evil.test/firmware.bin'),
Expand All @@ -46,6 +51,90 @@ describe('DesktopApiFirmwareArtifact URL admission', () => {
).toBe(false);
});

it('skips hostname pinning only for pre-release downloads', () => {
const allow = { allowPreReleaseHosts: true };
expect(
isFirmwareArtifactUrlAllowed(
new URL(
'https://pub-568cac7a13bf4c42b7a8113ffffc6793.r2.dev/firmware.bin',
),
allow,
),
).toBe(true);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://leonbucket.blob.core.windows.net/pro2/resource.zip'),
allow,
),
).toBe(true);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://web.onekey-asset.com/firmware.bin'),
allow,
),
).toBe(true);
expect(
isFirmwareArtifactUrlAllowed(
new URL(
'https://pub-568cac7a13bf4c42b7a8113ffffc6793.r2.dev/firmware.bin',
),
{ allowPreReleaseHosts: false },
),
).toBe(false);
// Structural checks still apply while hostname pinning is skipped.
expect(
isFirmwareArtifactUrlAllowed(
new URL('http://leonbucket.blob.core.windows.net/resource.zip'),
allow,
),
).toBe(false);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://leonbucket.blob.core.windows.net:8443/resource.zip'),
allow,
),
).toBe(false);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://user:pass@leonbucket.blob.core.windows.net/res.zip'),
allow,
),
).toBe(false);
expect(
isFirmwareArtifactUrlAllowed(
new URL('https://leonbucket.blob.core.windows.net/res.zip#fragment'),
allow,
),
).toBe(false);
});

it('opens the pre-release admission only for the literal boolean true', () => {
// The flag crosses an IPC boundary, so it may arrive as any JSON value.
// Only `true` may widen the allowlist: a truthy coercion here would let a
// malformed or hostile payload skip hostname pinning.
const devUrl = new URL('https://leonbucket.blob.core.windows.net/res.zip');
for (const value of [
undefined,
null,
false,
0,
1,
'true',
'false',
{},
[],
]) {
expect(
isFirmwareArtifactUrlAllowed(devUrl, {
allowPreReleaseHosts: value as never,
}),
).toBe(false);
}
expect(
isFirmwareArtifactUrlAllowed(devUrl, { allowPreReleaseHosts: true }),
).toBe(true);
});

it('probes its root and keeps the minimum lease lifecycle in memory', async () => {
const adapter = new DesktopApiFirmwareArtifact({
desktopApi: {} as never,
Expand All @@ -63,6 +152,54 @@ describe('DesktopApiFirmwareArtifact URL admission', () => {
});
});

it('enforces host admission at the download entry point, not just the predicate', async () => {
const adapter = new DesktopApiFirmwareArtifact({
desktopApi: {} as never,
});
const transactionId = 'fwtx:00000000-0000-4000-8000-000000000009';
const lease = await adapter.createLease(transactionId);
const input = {
taskId: 'resource',
transactionId,
leaseRef: lease.leaseRef,
artifactId: 'resource',
url: 'https://leonbucket.blob.core.windows.net/pro2/resource.zip',
route: { routeType: 'domain' } as const,
expectedSize: 1,
expectedSha256: 'a'.repeat(64),
maxBytes: 1,
overallDeadlineSeconds: 1,
};

await expect(adapter.download(input)).rejects.toThrow(
'ARTIFACT_INVALID_INPUT',
);
// A non-boolean value must not coerce its way past hostname pinning.
await expect(
adapter.download({
...input,
allowPreReleaseHosts: 'true' as never,
}),
).rejects.toThrow('ARTIFACT_INVALID_INPUT');
// Skipping hostname pinning requires pinned content.
await expect(
adapter.download({
...input,
expectedSha256: undefined,
allowPreReleaseHosts: true,
}),
).rejects.toThrow('ARTIFACT_INVALID_INPUT');
// Admitted: dev flag plus a pinned SHA-256 reaches the network stage.
await expect(
adapter.download({ ...input, allowPreReleaseHosts: true }),
).rejects.toThrow('ARTIFACT_NETWORK_FAILED');

await adapter.releaseLease({
leaseRef: lease.leaseRef,
disposition: 'safeCancelled',
});
});

it('rejects cancelled transactions until their lease is released', async () => {
const adapter = new DesktopApiFirmwareArtifact({
desktopApi: {} as never,
Expand Down
26 changes: 22 additions & 4 deletions packages/kit-bg/src/desktopApis/DesktopApiFirmwareArtifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const FINAL_ARTIFACT_GRACE_MS = 24 * 60 * 60 * 1000;
const PARTIAL_ARTIFACT_GRACE_MS = 7 * 24 * 60 * 60 * 1000;
const FIRMWARE_ARTIFACT_HOSTNAMES = new Set([
'common.onekey-asset.com',
'pub-d5c080673b4e4e9dae7e03680340378d.r2.dev',
'web.onekey-asset.com',
]);

Expand Down Expand Up @@ -91,13 +90,23 @@ const assertSafeInteger = (value: number, label: string): void => {
}
};

export const isFirmwareArtifactUrlAllowed = (url: URL): boolean =>
// allowPreReleaseHosts is only sent by bg while developer mode +
// "Use pre-release config" are on: pre-release artifacts live in
// developer-owned buckets whose hostnames cannot be pinned in advance. The
// structural checks below still apply, and validateDownloadInput additionally
// requires a pinned SHA-256 for these downloads, so every admitted artifact is
// covered by a reviewed hostname or by pinned content.
export const isFirmwareArtifactUrlAllowed = (
url: URL,
options?: { allowPreReleaseHosts?: boolean },
): boolean =>
url.protocol === 'https:' &&
url.port === '' &&
!url.username &&
!url.password &&
!url.hash &&
FIRMWARE_ARTIFACT_HOSTNAMES.has(url.hostname.toLowerCase());
(options?.allowPreReleaseHosts === true ||
FIRMWARE_ARTIFACT_HOSTNAMES.has(url.hostname.toLowerCase()));

const validatePortableEntryName = (
name: string,
Expand Down Expand Up @@ -487,7 +496,16 @@ class DesktopApiFirmwareArtifact implements IFirmwareArtifactAdapter {

private validateDownloadInput(input: IDownloadInput): void {
const url = new URL(input.url);
if (!isFirmwareArtifactUrlAllowed(url)) {
const allowPreReleaseHosts = input.allowPreReleaseHosts === true;
// Dropping hostname pinning is only acceptable against pinned content, so
// a pre-release artifact without a pinned digest must never be admitted.
if (allowPreReleaseHosts && input.expectedSha256 === undefined) {
throw new FirmwareArtifactDesktopError(
'ARTIFACT_INVALID_INPUT',
'Pre-release firmware artifacts require a pinned SHA-256',
);
}
if (!isFirmwareArtifactUrlAllowed(url, { allowPreReleaseHosts })) {
throw new FirmwareArtifactDesktopError(
'ARTIFACT_INVALID_INPUT',
'Firmware URL is outside the reviewed artifact host allowlist',
Expand Down
8 changes: 2 additions & 6 deletions packages/kit-bg/src/services/ServiceDevSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
devSettingsPersistAtom,
firmwareUpdateDevSettingsPersistAtom,
getDevSettingsNetworkThrottleEnabled,
getGatedFirmwareUpdateDevSetting,
} from '../states/jotai/atoms/devSettings';

import ServiceBase from './ServiceBase';
Expand Down Expand Up @@ -308,12 +309,7 @@ class ServiceDevSetting extends ServiceBase {
public async getFirmwareUpdateDevSettings<
T extends IFirmwareUpdateDevSettingsKeys,
>(key: T): Promise<IFirmwareUpdateDevSettings[T] | undefined> {
const dev = await devSettingsPersistAtom.get();
if (!dev.enabled) {
return undefined;
}
const fwDev = await firmwareUpdateDevSettingsPersistAtom.get();
return fwDev[key];
return getGatedFirmwareUpdateDevSetting(key);
}

@backgroundMethod()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export interface IFirmwareArtifactAdapter {
expectedSha256?: string;
maxBytes: number;
overallDeadlineSeconds: number;
// Set by bg only while developer mode + "Use pre-release config" are on;
// pre-release artifact hosts (developer buckets) are not pinned in advance.
allowPreReleaseHosts?: boolean;
}): Promise<IFirmwareArtifactReceipt>;
cancelDownloads(transactionId: string): Promise<void>;
materialize(input: {
Expand Down
Loading
Loading