diff --git a/cmd/eos/main.c b/cmd/eos/main.c index 916e345..010be38 100644 --- a/cmd/eos/main.c +++ b/cmd/eos/main.c @@ -546,6 +546,12 @@ static int cmd_clean(const CliArgs *args) { return 0; } + /* Validate build_dir to prevent command injection */ + if (strpbrk(build_dir, ";|&><$()\"'")) { + EOS_ERROR("Invalid build directory path: %s (contains special characters)", build_dir); + return 1; + } + char cmd[1024]; #ifdef _WIN32 snprintf(cmd, sizeof(cmd), "if exist \"%s\" rmdir /s /q \"%s\"", build_dir, build_dir); diff --git a/pkg/src/fetch.c b/pkg/src/fetch.c index 2f9af2e..089559a 100644 --- a/pkg/src/fetch.c +++ b/pkg/src/fetch.c @@ -133,7 +133,18 @@ static int is_tarball(const char *url) { strstr(url, ".zip") != NULL); } +static int is_url_safe(const char *url) { + if (!url) return 0; + /* Basic check for common shell metacharacters */ + if (strpbrk(url, ";|><$()`'")) return 0; + return 1; +} + static EosResult fetch_git(const char *url, const char *dest) { + if (!is_url_safe(url)) { + EOS_ERROR("Potentially unsafe git URL detected: %s", url); + return EOS_ERR_FETCH; + } char cmd[2048]; snprintf(cmd, sizeof(cmd), "git clone --depth 1 \"%s\" \"%s\"", url, dest); EOS_INFO("Fetching (git): %s", url); @@ -142,6 +153,10 @@ static EosResult fetch_git(const char *url, const char *dest) { } static EosResult fetch_tarball(const char *url, const char *dest) { + if (!is_url_safe(url)) { + EOS_ERROR("Potentially unsafe source URL detected: %s", url); + return EOS_ERR_FETCH; + } MKDIR(dest); char archive[EOS_MAX_PATH]; @@ -189,6 +204,11 @@ EosResult eos_fetch_source(const char *url, const char *dest_dir, return EOS_OK; } + if (!is_url_safe(url)) { + EOS_ERROR("Potentially unsafe source URL detected: %s", url); + return EOS_ERR_FETCH; + } + /* Determine archive path for checksum verification */ char archive_path[EOS_MAX_PATH] = {0}; if (is_tarball(url)) { diff --git a/services/linux/src/linux_security.c b/services/linux/src/linux_security.c index b16f784..1636fd6 100644 --- a/services/linux/src/linux_security.c +++ b/services/linux/src/linux_security.c @@ -43,7 +43,16 @@ int eos_selinux_set_policy(EosSelinux *se, const char *policy_dir, return -1; } +static int is_path_safe(const char *path) { + if (!path) return 1; + if (strpbrk(path, ";|&><$()\"'")) return 0; + return 1; +} + int eos_selinux_install_to_rootfs(const EosSelinux *se, const char *rootfs_dir) { + if (!is_path_safe(se->policy_dir) || !is_path_safe(se->policy_name)) { + return -1; + } char path[1024]; /* Create /etc/selinux directory */ @@ -78,6 +87,9 @@ int eos_selinux_install_to_rootfs(const EosSelinux *se, const char *rootfs_dir) int eos_selinux_label_rootfs(const EosSelinux *se, const char *rootfs_dir) { if (se->mode == EOS_SELINUX_DISABLED) return 0; + if (!is_path_safe(rootfs_dir) || !is_path_safe(se->file_contexts)) { + return -1; + } #ifndef _WIN32 char cmd[2048]; if (se->file_contexts[0]) { diff --git a/services/os/src/os_services.c b/services/os/src/os_services.c index 3b80c10..45e3635 100644 --- a/services/os/src/os_services.c +++ b/services/os/src/os_services.c @@ -80,7 +80,17 @@ int eos_ota_set_source(EosOtaUpdate *ota, const char *url, return 0; } +static int is_url_safe(const char *url) { + if (!url) return 0; + if (strpbrk(url, ";|><$()`'")) return 0; + return 1; +} + int eos_ota_download(EosOtaUpdate *ota) { + if (!is_url_safe(ota->url)) { + ota->state = EOS_OTA_FAILED; + return -1; + } ota->state = EOS_OTA_DOWNLOADING; char cmd[2048]; #ifdef _WIN32 @@ -114,6 +124,10 @@ int eos_ota_verify(EosOtaUpdate *ota) { } int eos_ota_install(EosOtaUpdate *ota, const char *target_path) { + if (target_path && strpbrk(target_path, ";|&><$()\"'")) { + ota->state = EOS_OTA_FAILED; + return -1; + } ota->state = EOS_OTA_INSTALLING; char cmd[2048]; #ifdef _WIN32