From 7a3614552b22087552d81ac93e78a52562a25f28 Mon Sep 17 00:00:00 2001 From: damocles Date: Sun, 26 Jul 2026 15:02:29 +0200 Subject: [PATCH 1/2] hive-priv: redact password-bearing lines before logging forgejo admin output --- hive-priv/src/main.rs | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/hive-priv/src/main.rs b/hive-priv/src/main.rs index 9610d605..905679ae 100644 --- a/hive-priv/src/main.rs +++ b/hive-priv/src/main.rs @@ -1366,6 +1366,21 @@ fn validate_forge_admin_arg(arg: &str) -> Result<()> { Ok(()) } +/// Redact a line before it hits the (root-readable, but still +/// unnecessarily exposed) host journal. `forgejo admin user create +/// --random-password` prints the generated password straight to stdout — +/// case-insensitive substring match on "password" is deliberately broad +/// (not pinned to forgejo's exact wording, which can change across +/// versions) so any password-bearing line gets caught rather than relying +/// on a phrase that could silently drift out of sync. +fn redact_password_line(line: &str) -> std::borrow::Cow<'_, str> { + if line.to_ascii_lowercase().contains("password") { + std::borrow::Cow::Borrowed("[redacted: line mentions a password]") + } else { + std::borrow::Cow::Borrowed(line) + } +} + /// Run `forgejo admin ` inside the `hive-forge` container as the /// `forgejo` unix user. Requires root (for nsenter into the container's /// namespaces). Returns `(stdout, stderr)`. @@ -1394,10 +1409,10 @@ async fn run_forge_admin(args: &[String]) -> Result<(String, String)> { let stdout = String::from_utf8_lossy(&out.stdout).into_owned(); let stderr = String::from_utf8_lossy(&out.stderr).into_owned(); for line in stdout.lines() { - tracing::info!(target: "forgejo-admin", "{line}"); + tracing::info!(target: "forgejo-admin", "{}", redact_password_line(line)); } for line in stderr.lines() { - tracing::warn!(target: "forgejo-admin", "{line}"); + tracing::warn!(target: "forgejo-admin", "{}", redact_password_line(line)); } if !out.status.success() { bail!( @@ -1986,10 +2001,26 @@ async fn sync_agent_tmpfiles(agents: &[String]) -> Result<(String, String)> { #[cfg(test)] mod tests { - use super::write_state_file_nofollow; + use super::{redact_password_line, write_state_file_nofollow}; use std::path::PathBuf; use std::sync::atomic::{AtomicU32, Ordering}; + #[test] + fn redacts_lines_mentioning_password_case_insensitively() { + assert_eq!( + redact_password_line("New password: hunter2"), + "[redacted: line mentions a password]" + ); + assert_eq!( + redact_password_line("PASSWORD=hunter2"), + "[redacted: line mentions a password]" + ); + assert_eq!( + redact_password_line("User \"foo\" was successfully created."), + "User \"foo\" was successfully created." + ); + } + /// Unique scratch dir per test, no external tempfile dep. fn scratch() -> PathBuf { static CTR: AtomicU32 = AtomicU32::new(0); From ff62bf2235abb7ac5622531e54e6b6257f16d766 Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 26 Jul 2026 14:56:33 +0200 Subject: [PATCH 2/2] dashboard: move infra container logs to dedicated INFRA tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit logs.html/logs.js previously showed infra containers (hive-ci, hive-forge, hive-gateway, hive-matrix) in an optgroup within the AGENT tab selector. This was confusing because infra containers don't run the per-agent hive daemons, making the unit filter meaningless for them. Changes: - Add INFRA tab (between AGENT and SYSTEM) with its own container selector and full-machine-journal fetch (no unit filter). - Remove the infra optgroup from the AGENT tab — it now shows agents only. - loadContainerLists() replaces loadAgentList(): fetches /api/state once and populates both selectors, avoiding a duplicate network request. - Deep-link (?agent=hive-ci) now routes to the INFRA tab when the named container is an infra container, falling back to AGENT otherwise. - Remove syncUnitSelectForSelection() — no longer needed since the AGENT tab no longer contains infra containers. - Extend the 30s timestamp ticker to cover the INFRA tab fetch time. No backend changes: /api/journal/{name} already supports infra container names. --- frontend/packages/dashboard/src/logs.html | 23 ++- frontend/packages/dashboard/src/logs.js | 203 +++++++++++++--------- 2 files changed, 146 insertions(+), 80 deletions(-) diff --git a/frontend/packages/dashboard/src/logs.html b/frontend/packages/dashboard/src/logs.html index a682c241..037e1b01 100644 --- a/frontend/packages/dashboard/src/logs.html +++ b/frontend/packages/dashboard/src/logs.html @@ -15,8 +15,8 @@ + Four sub-tabs: AGENT, INFRA, SYSTEM, AUDIT. Build log history has + moved to /builds.html (the build lifecycle hub). -->