mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
fix(security): replace .unwrap() panics in pairing store with proper error handling (#515)
The pairing store called .unwrap() on path.parent() in three locations (upsert_request, record_failed_approve, add_allow_from). If a path has no parent (root path or empty), this panics — a potential denial-of-service vector if an attacker can influence the path. Added InvalidPath variant to PairingStoreError and replaced all three .unwrap() calls with ok_or_else error propagation. This follows the project's no-panics-in-production policy. Locations fixed: - upsert_request (line ~227) - record_failed_approve (line ~322) - add_allow_from (line ~465) Co-authored-by: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
ac3c928853
commit
9b47dbbaed
+15
-3
@@ -30,6 +30,9 @@ pub enum PairingStoreError {
|
||||
#[error("Invalid channel: {0}")]
|
||||
InvalidChannel(String),
|
||||
|
||||
#[error("Invalid path: {0}")]
|
||||
InvalidPath(String),
|
||||
|
||||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
@@ -224,7 +227,10 @@ impl PairingStore {
|
||||
meta: Option<serde_json::Value>,
|
||||
) -> Result<UpsertResult, PairingStoreError> {
|
||||
let path = pairing_path(&self.base_dir, channel)?;
|
||||
fs::create_dir_all(path.parent().unwrap())?;
|
||||
let parent = path.parent().ok_or_else(|| {
|
||||
PairingStoreError::InvalidPath(format!("path has no parent: {}", path.display()))
|
||||
})?;
|
||||
fs::create_dir_all(parent)?;
|
||||
|
||||
let mut file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
@@ -319,7 +325,10 @@ impl PairingStore {
|
||||
|
||||
fn record_failed_approve(&self, channel: &str) -> Result<(), PairingStoreError> {
|
||||
let path = approve_attempts_path(&self.base_dir, channel)?;
|
||||
fs::create_dir_all(path.parent().unwrap())?;
|
||||
let parent = path.parent().ok_or_else(|| {
|
||||
PairingStoreError::InvalidPath(format!("path has no parent: {}", path.display()))
|
||||
})?;
|
||||
fs::create_dir_all(parent)?;
|
||||
|
||||
// Open (or create) and lock before reading so concurrent callers
|
||||
// don't clobber each other's writes.
|
||||
@@ -462,7 +471,10 @@ impl PairingStore {
|
||||
}
|
||||
|
||||
let path = allow_from_path(&self.base_dir, channel)?;
|
||||
fs::create_dir_all(path.parent().unwrap())?;
|
||||
let parent = path.parent().ok_or_else(|| {
|
||||
PairingStoreError::InvalidPath(format!("path has no parent: {}", path.display()))
|
||||
})?;
|
||||
fs::create_dir_all(parent)?;
|
||||
|
||||
let file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
|
||||
Reference in New Issue
Block a user