← back to Norma Platform
SECURITY incident 2026-07-29: agent-base fail-closed on empty AUTH_PASSWORD + bind 127.0.0.1 by default (was the empty-password all-interfaces RCE vector)
19d20a6a903ce7149da80b3d7d447fd01a54dc38 · 2026-07-29 21:18:31 -0700 · Steve
Files touched
M agents/shared/agent-base.js
Diff
commit 19d20a6a903ce7149da80b3d7d447fd01a54dc38
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 29 21:18:31 2026 -0700
SECURITY incident 2026-07-29: agent-base fail-closed on empty AUTH_PASSWORD + bind 127.0.0.1 by default (was the empty-password all-interfaces RCE vector)
---
agents/shared/agent-base.js | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/agents/shared/agent-base.js b/agents/shared/agent-base.js
index e5ff800..429361a 100644
--- a/agents/shared/agent-base.js
+++ b/agents/shared/agent-base.js
@@ -128,7 +128,8 @@ function createAgentServer({ name, port, skills = {}, cronJobs = [], dashboard =
const decoded = Buffer.from(authHeader.slice(6), 'base64').toString('utf-8');
const [user, pass] = decoded.split(':');
- if (user !== AUTH_USER || pass !== AUTH_PASS) {
+ // Defense-in-depth: an empty AUTH_PASS must never authenticate (incident 2026-07-29).
+ if (!AUTH_PASS || user !== AUTH_USER || pass !== AUTH_PASS) {
return res.status(403).json({ error: 'Invalid credentials' });
}
@@ -365,8 +366,16 @@ setTimeout(()=>location.reload(),15000);
// ──────────────────────────────────────
function start() {
registerFallbacks(); // after caller's custom routes → no shadowing
- app.listen(port, () => {
- console.log(`[${new Date().toISOString()}] [${name}] Agent running on port ${port}`);
+ // Fail-closed: refuse to start with an empty password. An unset AUTH_PASSWORD +
+ // the old all-interfaces bind was the credential-stealer RCE vector (incident 2026-07-29).
+ if (!AUTH_PASS) {
+ console.error(`[${new Date().toISOString()}] [${name}] FATAL: AUTH_PASSWORD is empty — refusing to start (incident 2026-07-29 empty-password exposure). Set AUTH_PASSWORD in this agent's .env.`);
+ process.exit(1);
+ }
+ // Bind loopback by default; a fronting proxy can widen via BIND_HOST. Never 0.0.0.0 implicitly.
+ const host = process.env.BIND_HOST || '127.0.0.1';
+ app.listen(port, host, () => {
+ console.log(`[${new Date().toISOString()}] [${name}] Agent running on ${host}:${port}`);
console.log(`[${new Date().toISOString()}] [${name}] Skills: ${Object.keys(skills).join(', ') || 'none'}`);
console.log(`[${new Date().toISOString()}] [${name}] Cron jobs: ${cronJobs.length}`);
← 0ecc4bb instagram-agent fully LIVE: real token installed, monitor/di
·
back to Norma Platform
·
login: standard username/password only (remove Google/Apple df259fc →