fix: Phase 3 — command injection, unwrap/expect panics, unsigned image acceptance
- VPN key gen: replaced sh -c with format string (command injection) with
safe stdin piping to wg pubkey
- Secrets manager: replaced .unwrap() on path.parent() with proper error
- Tor proxy: replaced .expect("valid proxy") with continue on error
- Image verifier: added require_signatures flag, strict mode rejects
unsigned images and missing cosign binary
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,28 +6,46 @@ use std::process::Command;
|
||||
use tracing::{info, warn};
|
||||
|
||||
pub struct ImageVerifier {
|
||||
cosign_public_key: Option<String>, // Public key for verification
|
||||
cosign_public_key: Option<String>,
|
||||
require_signatures: bool,
|
||||
}
|
||||
|
||||
impl ImageVerifier {
|
||||
pub fn new(cosign_public_key: Option<String>) -> Self {
|
||||
Self { cosign_public_key }
|
||||
Self { cosign_public_key, require_signatures: false }
|
||||
}
|
||||
|
||||
|
||||
/// Create a verifier that requires all images to be signed.
|
||||
pub fn new_strict(cosign_public_key: Option<String>) -> Self {
|
||||
Self { cosign_public_key, require_signatures: true }
|
||||
}
|
||||
|
||||
/// Verify a container image signature
|
||||
pub async fn verify_image(&self, image: &str, signature: Option<&str>) -> Result<bool> {
|
||||
if signature.is_none() && self.cosign_public_key.is_none() {
|
||||
if self.require_signatures {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Image '{}' has no signature and no cosign key is configured. \
|
||||
All container images must be signed for production use.",
|
||||
image
|
||||
));
|
||||
}
|
||||
warn!("No signature provided for image: {}", image);
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
|
||||
// Check if cosign is available
|
||||
let cosign_available = Command::new("cosign")
|
||||
.arg("version")
|
||||
.output()
|
||||
.is_ok();
|
||||
|
||||
|
||||
if !cosign_available {
|
||||
if self.require_signatures {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Cosign binary not found. Install cosign to verify container image signatures."
|
||||
));
|
||||
}
|
||||
warn!("Cosign not available, skipping signature verification");
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,9 @@ impl SecretsManager {
|
||||
.join(app_id)
|
||||
.join(format!("{}.secret", secret_id));
|
||||
|
||||
fs::create_dir_all(secret_path.parent().unwrap()).await?;
|
||||
let parent = secret_path.parent()
|
||||
.ok_or_else(|| anyhow::anyhow!("Invalid secret path: no parent directory for {:?}", secret_path))?;
|
||||
fs::create_dir_all(parent).await?;
|
||||
|
||||
let encrypted = self
|
||||
.encrypt(value.as_bytes())
|
||||
|
||||
Reference in New Issue
Block a user