Appearance
Code Audit
This guide explains how to audit this codebase for correctness and for suspicious behavior. Always verify, never trust.
Audit Goal
For each server endpoint and frontend page, verify:
- Input is validated.
- Only expected data is read or returned.
- Side effects are intentional and minimal.
- Errors use the expected API contract.
- There is no hidden data exfiltration, remote code execution, or unauthorized network access.
Fast Endpoint Audit Workflow
Use this repeatable flow for any file in server/api/**.
- Identify the route and method from the filename.
- Confirm input validation (
AppConstants.BASE_VALIDATION_SCHEMA,zod,getQuery,readBody). - Confirm the endpoint creates
BitcoinRpcClient(nodeIndex)only when needed. - Confirm RPC methods called are exactly the methods expected for that route.
- Confirm output shape uses
ApiResponse<T>and never includes credentials or sensitive runtime config. - Confirm
catchreturnssendErrorResponse(event, error). - Search for suspicious patterns: extra external URLs, shell execution, dynamic eval, file writes.
Endpoint-by-Endpoint Expectations
Core endpoints
GET /api/getNodeNames(server/api/getNodeNames.get.ts)- Expected: return only
host,name, and default flags from configured credentials. - Red flag: returning
user,password, full credential object, or environment values.
- Expected: return only
POST /api/getDashboard(server/api/getDashboard.post.ts)- Expected: validate
nodeIndex, call dashboard-related RPC methods, assemble combined dashboard payload. - Red flag: additional unrelated RPC calls, filesystem access, or outbound web calls.
- Expected: validate
POST /api/getNodeInfo(server/api/getNodeInfo.post.ts)- Expected: validate
nodeIndex, gather node status data in parallel, return oneNodeInfoobject. - Red flag: writes/modifications to node state, non-read RPC methods.
- Expected: validate
GET /api/getPeerInfo(server/api/getPeerInfo.get.ts)- Expected: validate
nodeIndex, returngetpeerinfoonly. - Red flag: any ban action or mutation inside this route.
- Expected: validate
GET /api/getTransaction(server/api/getTransaction.get.ts)- Expected: validate
nodeIndexandtxidlength, callgetrawtransaction. - Red flag: accepting arbitrary command input or skipping txid validation.
- Expected: validate
POST /api/getVisualizer(server/api/getVisualizer.post.ts)- Expected: validate
nodeIndex, read mempool and block data, use in-memory caches only. - Red flag: persistent disk writes, unbounded cache growth, or hidden external APIs.
- Expected: validate
Ban endpoints
GET /api/ban/listBanned(server/api/ban/listBanned.get.ts)- Expected: read-only list of bans.
POST /api/ban/setBan(server/api/ban/setBan.post.ts)- Expected: validate
nodeIndex,ipAddress, and boundedbanTime, then set ban. - Note: the file currently has a TODO for stricter IP validation.
- Expected: validate
POST /api/ban/removeBan(server/api/ban/removeBan.post.ts)- Expected: validate input and remove ban for target IP.
POST /api/ban/clearBanned(server/api/ban/clearBanned.post.ts)- Expected: validate
nodeIndex, clear all bans. - Red flag: route accessible without intended auth policy in your deployment.
- Expected: validate
Geo endpoints
GET /api/geoip/:ip(server/api/geoip/[ip].ts)- Expected: validate IP, lookup in local GeoLite database, return location fields.
- Red flag: network calls to unexpected third-party APIs.
POST /api/geoip/batch(server/api/geoip/batch.post.ts)- Expected: validate input array and IPs, lookup locally, return location list.
- Red flag: accepting massive unbounded arrays without limits.
Auth/session endpoints
POST /api/login(server/api/login.post.ts)- Expected: validate password presence, verify hash, set user session only.
- Red flag: logging passwords, returning session secrets, or bypass when hash exists.
POST /api/logout(server/api/logout.post.ts)- Expected: clear session when auth is enabled.
GET /api/session(server/api/session.get.ts)- Expected: return auth mode and authenticated boolean only.
- Red flag: returning raw session payload/cookies.
Endpoint Example Audit
Example from server/api/getNodeInfo.post.ts:
ts
const { nodeIndex } = AppConstants.BASE_VALIDATION_SCHEMA.parse(
await readBody(event)
);
const rpcClient = new BitcoinRpcClient(nodeIndex);
const [
blockchainInfo,
networkInfo,
mempoolInfo,
miningInfo,
netTotals,
memoryInfo,
difficulty,
indexInfo,
] = await Promise.all([
rpcClient.blockchain.getBlockchainInfo(),
rpcClient.network.getNetworkInfo(),
rpcClient.mempool.getMempoolInfo(),
rpcClient.mining.getMiningInfo(),
rpcClient.network.getNetTotals(),
rpcClient.mempool.getMemoryInfo(),
rpcClient.mining.getDifficulty(),
rpcClient.config.getIndexInfo(),
]);How to verify it only does what it claims:
- Input is constrained to allowed
nodeIndexschema. - Only read-only RPC methods are called.
- No filesystem access, no subprocesses, no external URLs.
- Output is assembled into
NodeInfoand returned viaApiResponse<NodeInfo>.
Fast Frontend Audit Workflow
Use this for files in app/pages/**, plus key components.
- List each API call in the file (
$fetchorfetch). - Confirm endpoint path and payload are expected for that view.
- Confirm no credentials/tokens are stored in localStorage or sent to third-party URLs.
- Confirm route params are parsed and used only as needed (
nodeIndex). - Confirm data is displayed, not executed as code.
- Check timers/intervals are cleaned up in
onUnmounted/onBeforeUnmount.
Frontend Data Access Map
App bootstrap and shell
app/app.vue- Calls store method that loads node names once.
app/stores/bitcoin.ts- Calls
GET /api/getNodeNamesand stores minimal node metadata.
- Calls
app/layouts/default.vue- Calls
POST /api/logoutonly for sign-out flow.
- Calls
app/middleware/auth.global.ts- Uses
useUserSession()and route redirects; no custom network calls.
- Uses
Main pages
app/pages/index.vue- Calls
POST /api/getDashboardwith{ nodeIndex }. - Verifies
response.ok,payload.success, andpayload.databefore rendering.
- Calls
app/pages/system/[i].vue- Calls
POST /api/getNodeInfowith{ nodeIndex }.
- Calls
app/pages/mempool/[i].vue- Calls
POST /api/getNodeInfoand embeds visualizer component.
- Calls
app/components/block-visualizer-html.vue- Calls
POST /api/getVisualizerwith{ nodeIndex }. - Polls on interval and clears timers on unmount.
- Calls
app/pages/peers/[i].vue- Calls
GET /api/getPeerInfo?nodeIndex=...andPOST /api/geoip/batch. - Also resolves unknown hostnames through
https://dns.google/resolvebefore geo lookup.
- Calls
app/pages/ban/[i].vue- Calls
GET /api/ban/listBannedandPOST /api/ban/removeBan.
- Calls
app/components/peer-details.vue- Calls
POST /api/ban/setBanfor peer ban action.
- Calls
app/pages/login.vue- Calls
POST /api/login, then fetches session state.
- Calls
Frontend Example Audit
Example from app/pages/system/[i].vue:
ts
const response = await $fetch<ApiResponse<NodeInfo>>('/api/getNodeInfo', {
method: 'POST',
body: { nodeIndex },
});
if (response.success && response.data) {
nodeInfo.value = response.data;
}How to verify it only gets what it needs:
- Single endpoint call for page purpose (system metrics).
- Input is only
nodeIndex; no unrelated fields. - Render logic consumes
response.datafields directly. - No write/mutation endpoint calls from this page.
How to Spot Malicious or Strange Code
Search for these patterns in both server/** and app/**.
- Dynamic code execution:
eval,new Function, dynamicimport()from user input. - Shell execution:
child_process,exec,spawn. - Unexpected network egress:
fetch('http...'),axios('http...'), WebSocket clients to unknown hosts. - Secret leakage: logging auth headers, passwords, credential objects, runtime config secrets.
- Covert persistence: writing hidden files, cron-like timers that do not clean up.
- Obfuscation signs: encoded payloads, large base64 blobs, misleading variable names around network calls.
Practical Verification Checklist
- Build a route-to-RPC matrix and confirm each endpoint calls only expected RPC methods.
- Confirm all endpoint errors normalize through
sendErrorResponse. - Confirm no endpoint returns credentials or session internals.
- Confirm frontend pages call only required endpoints for that screen.
- Confirm frontend code does not send node data to third-party APIs except explicitly expected behavior.
- Confirm all polling intervals and observers are cleaned up on unmount.
- Confirm ban and auth flows are explicit, minimal, and visible in UI actions.
Notes for This Repository
- The endpoint and page patterns are mostly thin and easy to audit because business logic is centralized in
server/utils/bitcoinRpcClient.tsand response normalization inserver/utils/errors.ts. - The biggest ongoing audit priority is keeping input validation strict (especially IP validation on ban routes) and watching for new outbound network calls that are not required for node monitoring.