Detect and warn when machine was set up without factory seal

Agent-Logs-Url: https://github.com/naturallaw777/staging_alpha/sessions/169de2bb-0655-4504-a270-8c0341c0d3dd

Co-authored-by: naturallaw777 <99053422+naturallaw777@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-04-07 17:48:38 +00:00
committed by GitHub
parent 85aca0d022
commit ac9ba4776c
6 changed files with 58 additions and 16 deletions

View File

@@ -2949,6 +2949,16 @@ async def api_security_status():
"The default system password may be known to the factory. "
"Please change your system and application passwords immediately."
)
elif status == "unsealed":
try:
with open(SECURITY_WARNING_FILE, "r") as f:
warning = f.read().strip()
except FileNotFoundError:
warning = (
"This machine was set up without the factory seal process. "
"Factory test data — including SSH keys, database contents, and wallet information — "
"may still be present on this system."
)
return {"status": status, "warning": warning}
@@ -3027,14 +3037,21 @@ async def api_change_password(req: ChangePasswordRequest):
except Exception as exc:
raise HTTPException(status_code=500, detail=f"Failed to write secrets file: {exc}")
# Clear legacy security status so the warning banner is removed
for path in (SECURITY_STATUS_FILE, SECURITY_WARNING_FILE):
try:
os.remove(path)
except FileNotFoundError:
pass
except Exception:
pass # Non-fatal; don't block a successful password change
# Clear legacy security status so the warning banner is removed — but only
# for "legacy" machines (pre-seal era). For "unsealed" machines, changing
# passwords is not enough; the factory residue (SSH keys, wallet data,
# databases) remains until a proper re-seal or re-install is performed.
try:
with open(SECURITY_STATUS_FILE, "r") as f:
current_status = f.read().strip()
if current_status == "legacy":
os.remove(SECURITY_STATUS_FILE)
try:
os.remove(SECURITY_WARNING_FILE)
except FileNotFoundError:
pass
except (FileNotFoundError, OSError):
pass
return {"ok": True}

View File

@@ -602,11 +602,19 @@ function renderAutolaunchToggle(enabled) {
var securityBanner = "";
if (_securityIsLegacy) {
var msg = _securityWarningMessage || "Your system may have factory default passwords. Please change your passwords to secure your system.";
var linkText, linkAction;
if (_securityStatus === "unsealed") {
linkText = "Contact Support";
linkAction = "openSupportModal(); return false;";
} else {
linkText = "Change Passwords";
linkAction = "openServiceDetailModal('root-password-setup.service', 'System Passwords', 'passwords'); return false;";
}
securityBanner =
'<div class="security-inline-banner">' +
'<span class="security-inline-icon">⚠</span>' +
'<span class="security-inline-text">' + msg + '</span>' +
'<a class="security-inline-link" href="#" onclick="openServiceDetailModal(\'root-password-setup.service\', \'System Passwords\', \'passwords\'); return false;">Change Passwords</a>' +
'<a class="security-inline-link" href="#" onclick="' + linkAction + '">' + linkText + '</a>' +
'</div>';
}

View File

@@ -5,9 +5,10 @@
async function checkLegacySecurity() {
try {
var data = await apiFetch("/api/security/status");
if (data && data.status === "legacy") {
if (data && (data.status === "legacy" || data.status === "unsealed")) {
_securityIsLegacy = true;
_securityWarningMessage = data.warning || "This machine may have a known factory password. Please change your passwords immediately.";
_securityStatus = data.status;
_securityWarningMessage = data.warning || "This machine may have a security issue. Please review your system security.";
}
} catch (_) {
// Non-fatal — silently ignore if the endpoint is unreachable

View File

@@ -626,8 +626,11 @@ function openSystemChangePasswordModal(unit, name, icon) {
resultEl.textContent = "✅ System password changed successfully.";
submitBtn.textContent = "Change Password";
submitBtn.disabled = false;
// Hide the legacy security banner if it's visible
if (typeof _securityIsLegacy !== "undefined" && _securityIsLegacy) {
// Hide the legacy security banner if it's visible — but only for
// "legacy" status machines. For "unsealed" machines, changing passwords
// is not enough; the factory residue remains until a proper re-seal or re-install.
if (typeof _securityIsLegacy !== "undefined" && _securityIsLegacy &&
(typeof _securityStatus === "undefined" || _securityStatus !== "unsealed")) {
_securityIsLegacy = false;
var banner = document.querySelector(".security-inline-banner");
if (banner) banner.remove();

View File

@@ -101,6 +101,7 @@ const $upgradeCloseBtn = document.getElementById("upgrade-close-btn");
// Legacy security warning state (populated by checkLegacySecurity in security.js)
var _securityIsLegacy = false;
var _securityStatus = "ok"; // "ok", "legacy", or "unsealed"
var _securityWarningMessage = "";
// System status banner