Detecting Shadow OpenClaw Agents in Your Organisation
Someone in your engineering org has spun up an OpenClaw agent with a personal CLI token. Here's how to detect it within minutes — not at the next audit.
Every NHI program eventually faces the same uncomfortable question: how many automated actors are running against our systems that we don't know about?
For OpenClaw specifically, the answer is "more than you think." OpenClaw is easy to install, easy to point at credentials, and easy to deploy to a Render service or a teammate's laptop. The official deploy path is paved; the unofficial one — "use your personal CLI token, paste it into IDENTITY.md, and run it on a VM" — is even easier.
This post is about catching the second kind. The mechanism is shadow agent detection: server-side fingerprinting that flags any human credential being used by what looks like an OpenClaw agent.
The shadow-agent pattern
Here's how it usually plays out:
- A developer wants to try OpenClaw against your production environment.
- They have a personal
secr_tok_*CLI token (or a session cookie from a browser login). - The proper path is to create a scoped
secr_agent_*identity, but that requires admin permission. - Instead, they paste their personal token into IDENTITY.md or an environment variable on a Render service.
- OpenClaw runs. It works. Nobody notices.
From the secr API's point of view, this looks like normal human traffic — except the User-Agent header reads openclaw/1.2.3 or OpenClaw-Agent/0.5 instead of secr-cli/1.0 or a browser string. That's the signal.
Fingerprinting
The shadow-agent detector runs on every authenticated request that uses a CLI token or a session cookie (not on secr_agent_* traffic — those are already identified as agents, by definition). The check:
- Read the
User-Agentheader. - Match it against
KNOWN_AI_AGENTS— a curated list includingopenclaw*,*openclaw*,moltbot*,claude*,cursor*,*copilot*,aider*, and others. - If matched, compute a fingerprint:
SHA-256(userAgent::tokenType::tokenId). - Insert (or update) a row in
shadow_agentswith the matched name, vendor, and framework slug —openclawfor the OpenClaw family. - If it's a new fingerprint, also insert an
nhi_anomaliesrow at severityhighand dispatch anhi.shadow_agentwebhook.
Each subsequent request from the same fingerprint increments accessCount, merges new source IPs, and recomputes a risk level (low / medium / high) based on volume and IP/project diversity.
What the dashboard shows
In /dashboard/nhi/shadow-agents, each detected entry renders with:
- The matched agent name (
OpenClaw) - The vendor (
OpenClaw) - A coloured framework badge — for OpenClaw specifically, this is a warning-amber pill, distinct from the neutral pills for Claude Code, Cursor, etc.
- Risk level (low / medium / high)
- Status (active / dismissed / resolved)
- Source IPs, access count, last seen
- Token type (
cli_tokenorsession) and the human owner
The framework badge is what makes OpenClaw stand out at a glance. If a manager scans the page weekly, they don't have to read user-agent strings to spot the OpenClaw deployments — they just look for the amber pills.
What you do with a detection
Three options for each entry:
Resolve
This is the right answer when the agent should exist — someone genuinely needs an OpenClaw deployment, they just used the wrong credential. You:
- Have them create a proper
secr_agent_*identity with project/environment/allowlist scoping. - In the dashboard, click Resolve and link the shadow row to the new agent identity.
- The shadow row's status becomes
resolvedwith a back-reference, so the audit trail is preserved.
Dismiss
The agent is known and safe but doesn't need a separate identity (rare for OpenClaw). Click Dismiss with a note. The status becomes dismissed. It stops appearing in the active list but stays in the audit history.
Investigate, then revoke
The agent is unauthorised. The action is on the credential, not the shadow row:
- Find the human owner of the
cli_tokenorsession. - Have a conversation about what their OpenClaw agent is doing.
- Revoke the credential they used (
secr token revoke). - The shadow row stays in the historical record.
The dashboard's Risk column helps prioritise: a row with risk=high (50+ accesses, multiple IPs, multiple projects) is a "this week" task; risk=low is a "next sprint" task.
The OpenClaw posture rule
Beyond detection, the compliance report has a specific rule for OpenClaw agents that are registered but lack proper scoping:
"OpenClaw-fingerprinted agent
support-botis missing scoping (projectId, secretAllowlist); recreate with --project, --env, and --allowlist"
This fires when:
- There's a registered
secr_agent_*identity (so it's not a shadow agent, just a known agent) - The
nhi_baselines.knownUserAgentsfor that agent contains an OpenClaw-pattern string (so it's being used by an OpenClaw deployment) - The agent is missing one of:
projectId,environmentId,secretAllowlist
This is the post-shadow-detection insight: even your managed OpenClaw agents should have all three scope fields. The full posture story is in the NHI posture checklist.
Tuning detection
A few practical notes from running this in real deployments:
False positives are rare but possible
The KNOWN_AI_AGENTS list is conservative. If your team has a service that legitimately calls itself openclaw-internal-tool, the detector will flag it. Two fixes:
- Rename it to something that doesn't match the patterns
- Or accept the detection and dismiss the entries with a note
Detection runs fire-and-forget
The check is async to keep the request path fast. If your test environment runs the detector against truncated tables, expect a brief gap before the row appears (usually < 500ms). The await new Promise(r => setTimeout(r, 500)) pattern in tests covers this.
Deletion of the underlying user cascades
If a human user is deleted, their shadow rows are deleted too (onDelete: cascade on userId). The audit log still has the original events; you just lose the aggregated shadow view. If you need to preserve the shadow rows after offboarding, dismiss them explicitly first.
The framework column is forward-compatible
Today, framework is openclaw, claude-code, or null. As we identify more autonomous-agent frameworks, that list grows. The schema doesn't need to change; the detector is data-driven from KNOWN_AI_AGENTS.
What it costs to leave on
Effectively zero. The detection check is one regex match plus one DB upsert per matched request. Total p99 added latency is sub-millisecond. The webhook dispatch is fire-and-forget. There's no batch job, no pollers, no daemon to maintain.
The only ongoing cost is reviewing the dashboard. Once a week, scan the active shadow agents, resolve / dismiss / investigate, and move on.
The closing point
You can't govern what you can't see. Shadow agent detection turns "we don't know what OpenClaw deployments exist in our org" into "we have an active list of every OpenClaw deployment, the credential it's using, and the risk it represents."
That's the first half of NHI for AI agents. The second half is making sure the managed agents are configured correctly — see the posture checklist for that.
Next: The OpenClaw NHI posture checklist — the full posture rules with remediation for each.
The OpenClaw plugin (@secr/openclaw-plugin) is on ClawHub and free for 1 agent. Install reference → · The /agents pillar · Approve tool calls from Telegram · Approval webhooks
Ready to get started?
Stop sharing secrets over Slack. Get set up in under two minutes.
Create your account