Dev-branch audit (docs/_archive/security-audit-dev-2026-07-22.md) re-found the
master issues (absent on dev) plus new ones in dev-only code. Applied here;
full-node build + test suite green; the subtle fixes were adversarially re-verified.
Ported from the master remediation (adapted to dev's code):
- bootstrap: reject zip-slip / path-traversal archive members (isSafeArchivePath)
before writing (S2-1). (dev already fail-closes on a missing checksum.)
- xmrig updater: fail closed when a signature is required but no key is pinned (F1-1).
- http_download.httpGetString: 16 MiB hard cap + MAXFILESIZE on the shared
metadata/price fetch (F1-2 / caps the updater + exchange paths at one site).
- rpc_client: explicit SSL_VERIFYPEER/VERIFYHOST (F4-1) and a 256 MiB response
cap in WriteCallback (F4-3).
- lite_connection_service: reject remote http:// lite servers, loopback only (L1-1).
Loopback is matched by a strict dotted-decimal 127.0.0.0/8 check (not a
startsWith("127.") prefix, which would wrongly accept 127.0.0.1.evil.com), with
userinfo/fragment stripping.
- lite controller: propagate encrypt/decrypt save() failure instead of reporting
success (F7-1).
- xmrig_manager: chmod(0600) the pool config before writing secrets (F5-2).
- app: clear the copied secret from the OS clipboard on shutdown (F3b-1).
- export_transactions: neutralize CSV/spreadsheet formula injection (F13-1).
- build pipeline: build-from-source lite backend + remove the self-attested
CMake signature gate (F15-1); pinned+verified appimagetool (F15-3/4);
verified Sapling params in setup.sh (F15-6); build.sh exits 0 on success.
(F14-1 empty-quoted-arg and F8-2 NUL-termination were already fixed on dev.)
Dev-only findings:
- rpc_client.callRaw: scrub the raw buffer + parsed tree (templated scrubJsonSecrets
for ordered_json) so console dumpprivkey/z_exportkey keys don't linger in freed
heap (N1-1).
- seed_wallet_creator: wipe the exported mnemonic on the failure path so a discarded
failed result never carries a live seed (W1-2).
- export_all_keys: write the plaintext key dump 0600 + atomically via
writeFileAtomically (U1-2).
- chat_database: restrict chat_messages.sqlite and its WAL/SHM sidecars to owner-only (C3-1).
Not done (need a decision, documented in the report):
- Chat header metadata (cid/z/p) rides outside the AEAD (C1/C2) — binding it is a
wire-protocol change requiring SilentDragonXLite interop review.
- Bootstrap lacks an offline-rooted signature (S2-2 residual) — needs signing infra.
- Console scrollback retains console-typed key-export output in plaintext (N1-1
residual) — inherent to an echoing console; would need output redaction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
169 lines
5.5 KiB
Bash
Executable File
169 lines
5.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# DragonX ImGui Wallet - AppImage Creation Script
|
|
# Copyright 2024-2026 The Hush Developers
|
|
# Released under the GPLv3
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
BUILD_DIR="${SCRIPT_DIR}/build/linux"
|
|
APPDIR="${BUILD_DIR}/AppDir"
|
|
VERSION="1.2.0"
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
RED='\033[0;31m'
|
|
NC='\033[0m'
|
|
|
|
print_status() { echo -e "${GREEN}[*]${NC} $1"; }
|
|
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# Check prerequisites
|
|
if [ ! -f "${BUILD_DIR}/bin/ObsidianDragon" ]; then
|
|
print_error "Binary not found. Run build.sh --linux-release first."
|
|
exit 1
|
|
fi
|
|
|
|
# Check for appimagetool — pinned to a tagged release and SHA-256 verified before we exec it.
|
|
# The old "continuous" tag is a moving, unverified network download that runs on the release
|
|
# builder; verify it or refuse to package.
|
|
APPIMAGETOOL_URL="https://github.com/AppImage/appimagetool/releases/download/1.9.0/appimagetool-x86_64.AppImage"
|
|
APPIMAGETOOL_SHA256="46fdd785094c7f6e545b61afcfb0f3d98d8eab243f644b4b17698c01d06083d1"
|
|
APPIMAGETOOL=""
|
|
if command -v appimagetool &> /dev/null; then
|
|
APPIMAGETOOL="appimagetool" # maintainer's own trusted system install
|
|
else
|
|
AT="${BUILD_DIR}/appimagetool-x86_64.AppImage"
|
|
if [ ! -f "$AT" ] || ! echo "${APPIMAGETOOL_SHA256} ${AT}" | sha256sum -c --status; then
|
|
print_status "Downloading appimagetool 1.9.0 (pinned)..."
|
|
wget -q -O "$AT" "$APPIMAGETOOL_URL"
|
|
if ! echo "${APPIMAGETOOL_SHA256} ${AT}" | sha256sum -c --status; then
|
|
print_error "appimagetool SHA-256 verification failed — refusing to use it"
|
|
rm -f "$AT"
|
|
exit 1
|
|
fi
|
|
chmod +x "$AT"
|
|
fi
|
|
APPIMAGETOOL="$AT"
|
|
fi
|
|
|
|
print_status "Creating AppDir structure..."
|
|
rm -rf "${APPDIR}"
|
|
mkdir -p "${APPDIR}/usr/bin"
|
|
mkdir -p "${APPDIR}/usr/lib"
|
|
mkdir -p "${APPDIR}/usr/share/applications"
|
|
mkdir -p "${APPDIR}/usr/share/icons/hicolor/256x256/apps"
|
|
mkdir -p "${APPDIR}/usr/share/ObsidianDragon/res"
|
|
|
|
# Copy binary
|
|
print_status "Copying binary..."
|
|
cp "${BUILD_DIR}/bin/ObsidianDragon" "${APPDIR}/usr/bin/"
|
|
|
|
# Copy resources
|
|
print_status "Copying resources..."
|
|
cp -r "${BUILD_DIR}/bin/res/"* "${APPDIR}/usr/share/ObsidianDragon/res/" 2>/dev/null || true
|
|
|
|
# Create desktop file
|
|
print_status "Creating desktop file..."
|
|
cat > "${APPDIR}/usr/share/applications/ObsidianDragon.desktop" << EOF
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=DragonX Wallet
|
|
Comment=DragonX Cryptocurrency Wallet
|
|
Exec=ObsidianDragon
|
|
Icon=ObsidianDragon
|
|
Categories=Finance;Network;
|
|
Terminal=false
|
|
StartupNotify=true
|
|
EOF
|
|
|
|
# Copy desktop file to root
|
|
cp "${APPDIR}/usr/share/applications/ObsidianDragon.desktop" "${APPDIR}/"
|
|
|
|
# Create icon (simple SVG placeholder if no icon exists)
|
|
print_status "Creating icon..."
|
|
if [ -f "${SCRIPT_DIR}/res/icons/dragonx-256.png" ]; then
|
|
cp "${SCRIPT_DIR}/res/icons/dragonx-256.png" "${APPDIR}/usr/share/icons/hicolor/256x256/apps/ObsidianDragon.png"
|
|
else
|
|
# Create a simple SVG icon as placeholder
|
|
cat > "${APPDIR}/ObsidianDragon.svg" << 'EOF'
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg width="256" height="256" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
<rect width="256" height="256" rx="32" fill="#1a1a1a"/>
|
|
<circle cx="128" cy="128" r="80" fill="none" stroke="#2e7d32" stroke-width="8"/>
|
|
<text x="128" y="145" font-family="Arial, sans-serif" font-size="72" font-weight="bold"
|
|
fill="#4caf50" text-anchor="middle">DX</text>
|
|
</svg>
|
|
EOF
|
|
# Convert SVG to PNG if rsvg-convert is available
|
|
if command -v rsvg-convert &> /dev/null; then
|
|
rsvg-convert -w 256 -h 256 "${APPDIR}/ObsidianDragon.svg" > \
|
|
"${APPDIR}/usr/share/icons/hicolor/256x256/apps/ObsidianDragon.png"
|
|
fi
|
|
fi
|
|
|
|
# Copy icon to root
|
|
cp "${APPDIR}/usr/share/icons/hicolor/256x256/apps/ObsidianDragon.png" "${APPDIR}/" 2>/dev/null || \
|
|
cp "${APPDIR}/ObsidianDragon.svg" "${APPDIR}/ObsidianDragon.png" 2>/dev/null || true
|
|
|
|
# Create AppRun script
|
|
print_status "Creating AppRun..."
|
|
cat > "${APPDIR}/AppRun" << 'EOF'
|
|
#!/bin/bash
|
|
SELF=$(readlink -f "$0")
|
|
HERE=${SELF%/*}
|
|
|
|
# Set up resource paths
|
|
export DRAGONX_RES_PATH="${HERE}/usr/share/ObsidianDragon/res"
|
|
|
|
# Find libraries
|
|
export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
|
|
|
|
# Change to resource directory for relative paths
|
|
cd "${HERE}/usr/share/ObsidianDragon"
|
|
|
|
exec "${HERE}/usr/bin/ObsidianDragon" "$@"
|
|
EOF
|
|
chmod +x "${APPDIR}/AppRun"
|
|
|
|
# Bundle required libraries (basic set)
|
|
print_status "Bundling libraries..."
|
|
LIBS_TO_BUNDLE=(
|
|
"libSDL3.so"
|
|
)
|
|
|
|
for lib in "${LIBS_TO_BUNDLE[@]}"; do
|
|
LIB_PATH=$(ldconfig -p | grep "$lib" | head -1 | awk '{print $NF}')
|
|
if [ -n "$LIB_PATH" ] && [ -f "$LIB_PATH" ]; then
|
|
cp "$LIB_PATH" "${APPDIR}/usr/lib/" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
# Also copy SDL3 from build if exists
|
|
if [ -f "${BUILD_DIR}/_deps/sdl3-build/libSDL3.so" ]; then
|
|
cp "${BUILD_DIR}/_deps/sdl3-build/libSDL3.so"* "${APPDIR}/usr/lib/" 2>/dev/null || true
|
|
fi
|
|
|
|
# Create AppImage
|
|
print_status "Creating AppImage..."
|
|
cd "${BUILD_DIR}"
|
|
|
|
ARCH=$(uname -m)
|
|
APPIMAGE_NAME="DragonX_Wallet-${VERSION}-${ARCH}.AppImage"
|
|
|
|
# Run appimagetool
|
|
ARCH="${ARCH}" "${APPIMAGETOOL}" "${APPDIR}" "${APPIMAGE_NAME}"
|
|
|
|
if [ -f "${APPIMAGE_NAME}" ]; then
|
|
# Copy to release/linux/ for clean output
|
|
OUT_DIR="${SCRIPT_DIR}/release/linux"
|
|
mkdir -p "${OUT_DIR}"
|
|
cp "${APPIMAGE_NAME}" "${OUT_DIR}/"
|
|
print_status "AppImage created successfully!"
|
|
print_status "Output: ${OUT_DIR}/${APPIMAGE_NAME}"
|
|
ls -lh "${OUT_DIR}/${APPIMAGE_NAME}"
|
|
else
|
|
print_error "AppImage creation failed"
|
|
exit 1
|
|
fi
|