security: eliminate unwrap/expect/panic on untrusted input paths (Fase 2 HIGH)

- db.rs: Replace all stmt.read/bind().unwrap() with safe match/if let + error logging
- db.rs: Replace execute_insert() expect() with safe prepare + rollback on error
- db.rs: Replace get_total_transaction_number() unwrap() with safe match/Result propagation
- bal-server.rs: Replace fs::read_to_string().expect() with match + 500 error
- bal-server.rs: Replace idx/amount.try_into().unwrap() with i64::try_from(...).unwrap_or()
- bal-server.rs: echo_pub_key returns 500 instead of panic on file read failure
- docs/08_security_audit.md: Update status for panic/DoS vulnerabilities to 'Fixed'
- All tests pass: cargo test (5 tests: 3 SQL injection + 2 panic regression)
- Build verified: cargo check --bin=bal-server --bin=bal-pusher (0 errors)
This commit is contained in:
2026-07-16 14:56:25 -04:00
parent 0fdefcfd0f
commit 167869b881
3 changed files with 177 additions and 56 deletions

View File

@@ -135,8 +135,15 @@ async fn echo_home(cfg: &MyConfig) -> Result<Response<BoxBody<Bytes, hyper::Erro
async fn echo_pub_key(
cfg: &MyConfig,
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
let pub_key = fs::read_to_string(&cfg.pub_key_path)
.expect(format!("Failed to read public key file {}", cfg.pub_key_path).as_str());
let pub_key = match fs::read_to_string(&cfg.pub_key_path) {
Ok(s) => s,
Err(e) => {
error!("Failed to read public key file {}: {}", cfg.pub_key_path, e);
let mut response = Response::new(full("Internal Server Error: Failed to read public key".to_owned()));
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
return Ok(response);
}
};
Ok(Response::new(full(pub_key)))
}
async fn echo_stats(
@@ -514,11 +521,11 @@ async fn echo_push(
}
sqlouts = format!("{sqlouts} SELECT ?, ?, ?, ?");
pouts.push((lineout, Value::String(txid.to_string())));
pouts.push((lineout + 1, Value::Integer(idx.try_into().unwrap())));
pouts.push((lineout + 1, Value::Integer(i64::try_from(idx).unwrap_or(-1))));
pouts.push((lineout + 2, Value::String(script_pubkey.to_string())));
pouts.push((
lineout + 3,
Value::Integer(amount.to_sat().try_into().unwrap()),
Value::Integer(i64::try_from(amount.to_sat()).unwrap_or(0)),
));
lineout += 4;
}