Container Kit leverages Tauri’s security model, Rust’s memory safety, and macOS sandboxing to provide a secure desktop application for container management.
Security Architecture
Multi-Layer Security
Container Kit implements security at multiple layers:
Frontend Security
TypeScript with strict typing prevents many runtime errors and type confusion attacks.
IPC Boundary
Tauri’s command system validates all messages between frontend and backend.
Rust Memory Safety
Rust’s ownership model prevents buffer overflows, use-after-free, and data races.
macOS Sandboxing
Application runs with limited permissions, requesting access only when needed.
Tauri Security Model
Content Security Policy
Tauri enforces a Content Security Policy to prevent XSS attacks:
{
"app" : {
"security" : {
"csp" : null
}
}
}
In production, configure a strict CSP to prevent inline scripts and unauthorized resource loading.
Command Allowlist
Only explicitly registered Tauri commands are accessible from the frontend:
let spectabuilder = Builder :: < tauri :: Wry > :: new () . commands ( collect_commands! [
greet ,
run_container_command_with_stdin ,
execute_with_elevated_command ,
get_default_shell ,
stream_container_command
]);
builder
. invoke_handler ( spectabuilder . invoke_handler ())
. run ( tauri :: generate_context! ())
Never expose commands that execute arbitrary shell commands without validation.
Type-Safe IPC
All commands use Specta for compile-time type safety:
#[tauri :: command]
#[specta :: specta]
pub async fn execute_with_elevated_command (
command : String ,
args : Vec < String >,
) -> Result < CommandResult , String > {
// Implementation
}
TypeScript bindings are automatically generated:
src/lib/models/bindings.ts
export async function execute_with_elevated_command (
command : string ,
args : string []
) : Promise < CommandResult >
Privilege Escalation
Container operations often require elevated privileges. Container Kit handles this securely:
Elevated Command Execution
src-tauri/src/commands/system.rs
use elevated_command :: Command ;
#[tauri :: command]
#[specta :: specta]
pub async fn execute_with_elevated_command (
command : String ,
args : Vec < String >,
) -> Result < CommandResult , String > {
let is_elevated = Command :: is_elevated ();
let mut cmd = StdCommand :: new ( & command );
cmd . args ( & args );
let output = if is_elevated {
// Already elevated - execute directly
cmd . output () . map_err ( | e | e . to_string ()) ?
} else {
// Request elevation with macOS system prompt
let mut elevated_cmd = Command :: new ( cmd );
elevated_cmd . name ( "ContainerKit" . to_string ());
elevated_cmd . icon ( include_bytes! ( "../../icons/icon.icns" ) . to_vec ());
elevated_cmd . output () . map_err ( | e | e . to_string ()) ?
};
Ok ( CommandResult {
signal : output . status . signal (),
stdout : String :: from_utf8_lossy ( & output . stdout) . to_string (),
stderr : String :: from_utf8_lossy ( & output . stderr) . to_string (),
code : output . status . code (),
})
}
Key Security Features
Checks if the app is already running with elevated privileges before requesting elevation: let is_elevated = Command :: is_elevated ();
Uses macOS’s native elevation dialog, showing the app name and icon: elevated_cmd . name ( "ContainerKit" . to_string ());
elevated_cmd . icon ( include_bytes! ( "../../icons/icon.icns" ) . to_vec ());
This prevents spoofing and provides clear user consent.
Always validate commands before execution: // Whitelist allowed commands
const ALLOWED_COMMANDS : & [ & str ] = & [ "container" , "docker" , "podman" ];
if ! ALLOWED_COMMANDS . contains ( & command . as_str ()) {
return Err ( "Unauthorized command" . to_string ());
}
Container CLI Security
Sidecar Binary
Container Kit bundles the Apple Container CLI as a sidecar binary:
{
"bundle" : {
"externalBin" : [
"binaries/sidecar/apple-container/bin/container"
],
"resources" : [
"binaries/sidecar/apple-container/**/*"
]
}
}
Benefits
Version Control Bundles a specific, tested version of the container CLI, preventing version conflicts.
Path Isolation Uses bundled binary instead of system PATH, preventing PATH injection attacks.
Integrity Binary is included in the signed app bundle, verified by macOS Gatekeeper.
No System Dependency Works without requiring system-wide CLI installation.
Command Execution
src/lib/services/containerization/utils.ts
import { Command } from '@tauri-apps/plugin-shell' ;
export function createContainerCommand ( args : string []) : Command < string > {
// Uses bundled sidecar binary
return Command . create ( 'container' , args );
}
The sidecar binary path is automatically resolved by Tauri, ensuring consistent execution across environments.
Database Security
Data Protection
The SQLite database is stored in the application data directory:
~/Library/Application Support/com.ethercorps.container-kit/container-kit.db
File Permissions
SQL Injection Prevention
Connection Security
The database file inherits macOS user-level permissions, readable only by the current user.
Drizzle ORM uses parameterized queries, preventing SQL injection: // Safe - parameterized
await db . select (). from ( registry ). where ( eq ( registry . id , userId ));
// Unsafe - string concatenation (don't do this)
await sqlite . execute ( `SELECT * FROM registry WHERE id = ' ${ userId } '` );
Database connections are short-lived and always closed: try {
rows = await sqlite . select ( sql , params );
} finally {
await sqlite . close ();
}
Sensitive Data
Never store passwords or secrets in plain text. Use macOS Keychain for sensitive credentials: import { Store } from '@tauri-apps/plugin-store' ;
const store = new Store ( 'settings.json' );
// Store non-sensitive settings
await store . set ( 'theme' , 'dark' );
// For passwords, use macOS Keychain instead
Command Arguments
Validate all user input before passing to shell commands:
export function validateContainerId ( id : string ) : boolean {
// Only allow alphanumeric and common safe characters
return / ^ [ a-zA-Z0-9_- ] + $ / . test ( id );
}
export async function startContainer ( id : string ) : Promise < Output > {
if ( ! validateContainerId ( id )) {
throw new Error ( 'Invalid container ID' );
}
const command = createContainerCommand ([ 'start' , id ]);
return await command . execute ();
}
export function sanitizeImageName ( name : string ) : string {
// Remove potentially dangerous characters
return name . replace ( / [ ^ a-zA-Z0-9:._/- ] / g , '' );
}
export function sanitizeUrl ( url : string ) : string {
try {
const parsed = new URL ( url );
// Only allow https and http
if ( ! [ 'https:' , 'http:' ]. includes ( parsed . protocol )) {
throw new Error ( 'Invalid protocol' );
}
return parsed . toString ();
} catch {
throw new Error ( 'Invalid URL' );
}
}
Hardened Runtime
macOS hardened runtime provides additional security:
{
"bundle" : {
"macOS" : {
"hardenedRuntime" : true ,
"minimumSystemVersion" : "26.0"
}
}
}
Runtime Protections
Code Signing
App is signed with a Developer ID certificate, verified by macOS Gatekeeper.
Library Validation
Only Apple-signed or same-team-signed libraries can be loaded.
Memory Protections
Prevents code injection and runtime modification.
Notarization
App is notarized by Apple, scanned for malware before distribution.
Update Security
Container Kit supports secure auto-updates:
{
"plugins" : {
"updater" : {
"pubkey" : "dW50cnVzdGVkIGNvbW1lbnQ6..."
}
}
}
Signed Updates
Signature Verification
HTTPS Only
Integrity Checks
Updates are signed with a private key and verified with the embedded public key: . plugin ( tauri_plugin_updater :: Builder :: new () . build ())
Update manifests and downloads use HTTPS exclusively.
Downloaded updates are hashed and verified before installation.
Security Checklist
Best Practices
Principle of Least Privilege Request elevated permissions only when necessary, not on app launch.
Defense in Depth Layer multiple security controls - validation, type safety, sandboxing.
Fail Securely On errors, deny access rather than falling back to permissive behavior.
Security Updates Keep dependencies updated and monitor security advisories.
Reporting Security Issues
DO NOT create public GitHub issues for security vulnerabilities.Email security issues to: [email protected] Include:
Description of the vulnerability
Steps to reproduce
Potential impact
Suggested fixes (if any)
Next Steps
Performance Learn about performance optimizations and benchmarking
Architecture Understand the overall application architecture