Fix: ElizaOS AgentSkillsService “SKILLS_AUTO_LOAD” Boolean Setting Bug
In autonomous AI agent architectures deployed on ElizaOS (formerly ai16z), configuring modular capabilities and safety boundaries is done through environment variables and character configuration files (character.json).
When deploying on-chain trading agents or automated DeFi node operators, administrators frequently disable dynamic external skill downloads by setting:
{
"name": "DeFiSentinel",
"settings": {
"SKILLS_AUTO_LOAD": false,
"CLAWHUB_AUTO_LOAD": false,
"SKILLS_AUTO_REFRESH": true
}
}
However, upon runtime startup, developers discover a critical flaw: the agent completely ignores the false setting. The agent connects to remote repositories (such as ClawHub), pulls third-party skill modules into local storage, and initializes unexpected action handlers:
[2026-09-11 11:42:01] [AgentSkillsService] Initializing skills subsystem...
[2026-09-11 11:42:02] [AgentSkillsService] AutoLoad active (SKILLS_AUTO_LOAD=false detected as enabled).
[2026-09-11 11:42:03] [ClawHub] Querying remote index for installed actions...
[2026-09-11 11:42:04] [AgentSkillsService] Warning: AutoRefresh daemon failed to start (expected string 'true').
1. Code-Level Root Cause Analysis
The vulnerability resides within @elizaos/plugin-agent-skills/src/service.ts. In the AgentSkillsService constructor and initialization lifecycle, settings are read via runtime.getSetting(...):
// Vulnerable Implementation in @elizaos/plugin-agent-skills/src/service.ts
this.autoLoad = config?.autoLoad ??
(runtime.getSetting("SKILLS_AUTO_LOAD") !== "false" &&
runtime.getSetting("CLAWHUB_AUTO_LOAD") !== "false");
this.autoRefreshEnabled = config?.autoRefresh ??
runtime.getSetting("SKILLS_AUTO_REFRESH") === "true";
The Type Incompatibility
In the ElizaOS core runtime, runtime.getSetting(key: string) is typed as:
$$\text{getSetting}: \text{string} \to \text{string} \mid \text{boolean} \mid \text{number} \mid \text{null}$$
When a setting is injected via .env, process environment variables arrive as strings ("false"). However, when settings are declared in character.json or provided dynamically via plugin configurations, modern JSON parsers supply native JavaScript primitives:
runtime.getSetting("SKILLS_AUTO_LOAD")returnsfalse(boolean).- The expression evaluates:
false !== "false". - Because the types differ (
booleanvsstring), the inequality evaluates totrue.
As a consequence, setting SKILLS_AUTO_LOAD: false inadvertently enables autoloading.
Conversely, for SKILLS_AUTO_REFRESH:
runtime.getSetting("SKILLS_AUTO_REFRESH")returnstrue(boolean).- The expression evaluates:
true === "true". - Because
boolean !== string, the check evaluates tofalse, and the refresh daemon silently never runs.
(This exact type coercion flaw is also present in other ElizaOS modules; see our analysis on ElizaOS VisionService Boolean Env Setting Disabled Fix).
2. Security Implications for Web3 Agents
For crypto-native agents managing private keys, delegating transaction intents, or monitoring mempools, uncontrolled skill acquisition presents severe hazards:
- Supply Chain Hijacking: ClawHub or community registry compromises could lead an agent to load compromised tool definitions.
- Memory Poisoning: Dynamically loaded skills register prompt templates and action extractors that can alter transaction limits or gas thresholds.
- Bandwidth & Rate-Limit Spikes: Background polling of unregistered endpoints burns through API rate limits and network sockets.
3. Remediation Protocols
Strategy 1: Immediate Front-End Patch (Character & Environment Config)
Until packages are updated upstream, force string literals in both .env and character.json.
In .env:
SKILLS_AUTO_LOAD="false"
CLAWHUB_AUTO_LOAD="false"
SKILLS_AUTO_REFRESH="true"
In character.json (explicit string quotes instead of booleans):
{
"name": "DeFiSentinel",
"settings": {
"SKILLS_AUTO_LOAD": "false",
"CLAWHUB_AUTO_LOAD": "false",
"SKILLS_AUTO_REFRESH": "true"
}
}
Strategy 2: Patching AgentSkillsService via Utility Normalization
If compiling ElizaOS from source or maintaining an internal monorepo, patch the loader with a universal boolean parser:
// utils/settingParser.ts
export function parseBooleanSetting(
value: string | boolean | number | null | undefined,
defaultValue: boolean = false
): boolean {
if (value === undefined || value === null) {
return defaultValue;
}
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'string') {
const normalized = value.trim().toLowerCase();
if (normalized === 'true' || normalized === '1' || normalized === 'yes') {
return true;
}
if (normalized === 'false' || normalized === '0' || normalized === 'no') {
return false;
}
}
if (typeof value === 'number') {
return value !== 0;
}
return defaultValue;
}
Update packages/plugin-agent-skills/src/service.ts:
import { parseBooleanSetting } from './utils/settingParser';
// Safe initialization
const skillsAutoLoad = parseBooleanSetting(
runtime.getSetting("SKILLS_AUTO_LOAD"),
true // Default if not specified
);
const clawHubAutoLoad = parseBooleanSetting(
runtime.getSetting("CLAWHUB_AUTO_LOAD"),
true // Default if not specified
);
this.autoLoad = config?.autoLoad ?? (skillsAutoLoad && clawHubAutoLoad);
this.autoRefreshEnabled = config?.autoRefresh ?? parseBooleanSetting(
runtime.getSetting("SKILLS_AUTO_REFRESH"),
false
);
Strategy 3: Hardened Runtime Wrapper (Plugin Defense-in-Depth)
For production deployments where you cannot alter @elizaos/plugin-agent-skills directly, intercept settings in your agent’s bootstrap file:
import { IAgentRuntime, Character } from '@elizaos/core';
export function sanitizeCharacterSettings(character: Character): Character {
const sanitized = { ...character };
if (!sanitized.settings) return sanitized;
const targetBooleanKeys = [
'SKILLS_AUTO_LOAD',
'CLAWHUB_AUTO_LOAD',
'SKILLS_AUTO_REFRESH',
'ENABLE_OBJECT_DETECTION',
'ENABLE_POSE_DETECTION'
];
for (const key of targetBooleanKeys) {
if (typeof sanitized.settings[key] === 'boolean') {
// Coerce to string representation to appease strict string comparisons
sanitized.settings[key] = String(sanitized.settings[key]);
}
}
return sanitized;
}
4. Operational Verification Checklist
To confirm that your ElizaOS node is properly protected against unwanted skill loads:
- Inspect Agent Startup Logs: Verify that no
[ClawHub] Querying remote indexmessages appear during initialization. - Audit Action Registry: Print
runtime.actions.map(a => a.name)upon startup to ensure only your explicitly whitelisted plugins are registered. - Verify Local Cache Directory: Ensure the
.skillsorclawhub_cachefolder in the agent’s root directory remains empty.