ai

OpenClaw's Credential Problem Is Not a Secrets Problem

OpenClaw stores every API key in one plaintext file. Every skill reads the same file. ClawHavoc proved what happens next. The fix isn't encryption. It's a delegation model that already exists.

Back in January, we published a checklist for securing OpenClaw. Sandboxing, allow-lists, secret hygiene, audit logs. Good operational advice. We stand by it.

Two weeks later, security researchers found 341 malicious skills on ClawHub. The number kept climbing. By February, it was over 800, roughly 20% of the entire registry.

The campaign, tracked as ClawHavoc, targeted one thing above everything else: the plaintext credentials sitting in ~/.clawdbot/.env.

Our checklist told developers to keep secrets out of files that the agent can casually read. That was correct. But it treated the problem as a configuration issue, something you fix by being more careful with your .env. Watching ClawHavoc unfold, it became clear that the problem runs deeper than that. You can encrypt the file, rotate the keys, and use a secrets manager. A compromised skill still gets the same access as every other skill. There's no boundary between the skill checking your calendar and the one that just exfiltrated your GitHub token to a webhook on a shady server.

The problem isn't how the credentials are stored. The problem is that there's no delegation model at all.

What We Mean by Delegation

When you connect OpenClaw to Gmail, GitHub, Slack, or Google Calendar, the agent stores a token or API key for each service in a single flat file. Every skill reads that same file. There are no scopes, no per-skill boundaries, no way to say "this skill can search my email but not send messages." The agent holds one ring of keys and every skill can grab any key on the ring.

We've seen this pattern before. It's how web applications worked before OAuth. You'd give a third-party app your actual username and password so it could access your data. If that app were compromised, the attacker would have everything. OAuth solved this by introducing a delegation layer: the user authenticates once, and the third party gets a scoped, time-limited token instead of raw credentials.

Mobile platforms took it further. When an app wants camera access, it asks. You can grant camera access without granting microphone access. If a malicious app gets camera access, it still can't read your contacts. Each app operates within its declared permission scope.

OpenClaw skills have none of this. No permission declaration at install time, no scoped tokens, no consent screen. The parallel to pre-OAuth web apps isn't an analogy. It's a literal architectural description.

What ClawHavoc Looked Like from Where We Sit

At Auth0, we work on identity and authorization infrastructure for AI agents. So when ClawHavoc hit, we weren't just reading the headlines. We were looking at the attack chain and recognizing every link in it as something the auth layer should have caught.

A single attacker uploaded 354 malicious packages to ClawHub in what looks like an automated run. The only requirement to publish a skill was a GitHub account that was one week old. No identity verification for publishers, no permission scope declarations, no code review. One of the malicious skills was gamed to the number one spot on ClawHub and downloaded thousands of times before anyone flagged it.

The skills were disguised as crypto wallets, YouTube utilities, and Google Workspace integrations. Many used typosquatting. And across nearly all of them, the primary target was ~/.clawdbot/.env. Some skills silently exfiltrated credentials to external webhooks. Others opened reverse shells. Deleted API keys persisted in .bak files, so even tokens you thought you'd rotated were still available.

Because OpenClaw often runs on dedicated, always-on machines (Mac minis are popular for this), those credentials were accessible around the clock. A single compromised skill gave an attacker persistent access to every service the agent could reach.

Here's what would have been different with a proper delegation layer in place.

The agent wouldn't hold long-lived plaintext credentials. It would request short-lived, scoped tokens through a token exchange. A token for Gmail can't access GitHub. A token for reading calendar events can't send emails. And if a skill manages to exfiltrate a token, it expires.

The skill wouldn't have the same access as the agent. Token exchange means each skill gets only the access it needs for its declared purpose. The calendar skill doesn't need to see your SSH keys. The email search skill doesn't need write access to your repositories.

And the whole chain would be auditable. Who authenticated, which skill requested which token, for which service, at what time. ClawHavoc went undetected for weeks, partly because there was no audit trail to trigger alerts.

These aren't hypothetical mitigations. This is what Auth0 Token Vault does. It manages OAuth connections to third-party services, stores refresh tokens securely, and issues scoped access tokens on demand through a token exchange flow. We built it because we saw the delegation gap in agentic architectures before ClawHavoc made it front-page news.

A Tool You Can Use Right Now

Deepu K Sasidharan, on our DevRel team, built Auth0 Token Vault CLI, an open-source CLI that brings Token Vault to OpenClaw directly. It ships as a ClawHub skill and also works with Claude Code.

Auth0 Token Vault CLI ClawHub skill flow diagram

The setup replaces the plaintext .env model entirely:

# Install auth0-tv
npm install -g auth0-token-vault-cli

# Install the skill in OpenClaw
npx clawhub@latest install auth0-token-vault

# Run the guided setup (configures Auth0 tenant + Token Vault)
auth0-tv init

# Connect services individually, each with its own scoped token
auth0-tv connect gmail
auth0-tv connect calendar
auth0-tv connect github
auth0-tv connect slack
# Or connect any Auth0 connection by name
auth0-tv connect my-enterprise-idp --scopes "openid,profile" --allowed-domains "api.example.com"

After setup, the agent accesses services through auth0-tv instead of reading raw tokens from a file:

auth0-tv gmail search "from:boss@company.com"
auth0-tv calendar events
auth0-tv github issues octocat/Hello-World
auth0-tv slack search "project update"
auth0-tv fetch my-enterprise-idp https://api.example.com/users/me

Here are a few things under the hood that are worth spelling out.

Credentials are stored in the OS keyring, not a plaintext file. The agent authenticates through a browser-based OAuth PKCE flow and never sees your password.

Each service connection is independent. Connecting Gmail doesn't grant Slack access. Revoking GitHub doesn't break your calendar. This is the scoping that ~/.clawdbot/.env never had.

Outbound network access is restricted per service. A Gmail token can only hit *.googleapis.com. A GitHub token can only hit api.github.com. A malicious skill that somehow grabs a token can't use it to call arbitrary endpoints. You can explicitly add extra allowed domains, but the default is deny.

This scoping holds even when skills need to go beyond the built-in commands. The CLI includes a fetch passthrough that lets the agent make authenticated API calls to any endpoint a service supports, but the domain restriction still applies:

# Known services (use default allowed domains)
auth0-tv fetch github https://api.github.com/user
auth0-tv fetch gmail https://gmail.googleapis.com/gmail/v1/users/me/messages
auth0-tv fetch slack https://slack.com/api/conversations.list
auth0-tv fetch github https://api.github.com/repos/octocat/Hello-World/issues -X POST -d '{"title":"Bug"}'
auth0-tv fetch github https://api.github.com/user -H "Accept: application/vnd.github.v3+json"
auth0-tv fetch slack https://slack.com/api/chat.postMessage -X POST --data-file ./payload.json

# Custom connections (requires --allowed-domains set during connect)
auth0-tv fetch my-enterprise-idp https://api.example.com/users/me

The agent gets full API flexibility without holding the credentials directly. If a skill calls auth0-tv fetch github against a domain that isn't api.github.com, the request is blocked. That's the kind of enforcement that a plaintext .env file can never provide, no matter how well you encrypt it.

And because everything flows through Token Vault, revoking access is centralized. You revoke it in one place and every downstream token becomes invalid.

Going Deeper with Fine-Grained Authorization

Token Vault handles which services an agent can reach. Fine-Grained Authorization (FGA) handles what it can do within those services.

FGA lets you define resource-level access controls. Not just "this agent can access Google Drive" but "this agent can read files in the Projects folder, not the Finance folder." You express relationships between users, agents, and resources, and FGA evaluates them at request time.

The combination matters. Token Vault scopes the service. FGA scopes the resources within the service. Both live outside the agent, where a malicious skill can't override them, and a confused model can't misconfigure them.

The Pattern Repeats

OpenClaw is not the last agent framework that will face this. It's the first one where the consequences played out at scale, publicly, with real credential theft. Every agent framework that connects to third-party services on behalf of users will hit the same question: how does the agent prove it's authorized to act, and how do you limit what it can do?

We keep coming back to the same answer. Not because we're selling it (though we are), but because it's the same answer the industry arrived at for web apps, mobile apps, and API integrations over the past fifteen years. OAuth, scoped tokens, token exchange, fine-grained authorization. The patterns are proven. The work is in applying them to agents, where the thing requesting access is not a human clicking through a consent screen but an autonomous system acting on a human's behalf.

That's what Auth0 for AI Agents is. If you're running OpenClaw today, auth0-tv gets you there fast. If you're building agentic applications, the full platform gives you user authentication, Token Vault for delegated third-party access, and FGA for resource-level controls. If you prefer a thin proxy for the same purpose, check out Auth0 Token Vault Proxy, a Rust CLI built by the same author.

The goal isn't to make agents less capable. It's to make sure the capabilities come with boundaries that are actually enforced.