Detection rules reference
Every rule Ironheights ships, in plain language: what it looks for, why it matters, how it scores, where it misfires, and what it cannot see. 17 rules read skill files during scan (and run in the browser scanner); 4 more join scan in the CLI; 4 come from verify; 9 from audit-config; 1 is an optional model note.
What do the Ironheights rules check?
Ironheights 0.3.0 has 35 rules. 17 content rules match risky patterns in skill files, such as remote scripts piped to a shell, credential paths, and instruction overrides. The rest cover MCP configs (3), the advisory feed (1), baseline integrity (4), OpenClaw config (9) and an optional model note (1).
All rules
All 35 rules
IH-EXEC-001criticalRemote content piped into an interpreterFetching remote text and passing it straight to a shell or runtime executes attacker-controlled code.Executionscan+100 ptsIH-EXEC-002highPrerequisite install from an external URLSkills sometimes tell the agent to install a tool from a URL or git link before doing anything else. Each command is reported once, on the line that contains it.Executionscan+40 ptsIH-EXEC-003highDynamic code executioneval, the Function constructor, and shell-enabled subprocess calls run strings as code.Executionscan+40 ptsIH-NET-001mediumUndeclared network destinationA skill that contacts a host outside the allowlist can send data somewhere the user did not expect. A download, install, or fetch instruction is a contact, and so is a paste site or a file-drop host. A homepage field, a license URL, a schema link, or an official API host in prose is not a contact.Networkscan+15 ptsIH-NET-002highPossible exfiltrationA sensitive read and an outbound request in the same few lines can move credentials off the machine. Telling the agent to send a credential path to a URL counts.Networkscan+40 ptsIH-CRED-001highAccess to a sensitive pathReferences to keys, browser stores, wallets, shell history, or OpenClaw auth files expose credentials. A credential directory such as ~/.ssh, ~/.aws, ~/.gnupg, or ~/.azure counts with or without a file name after it. Windows forms count too: ~\.ssh, %USERPROFILE%\.ssh, and AppData paths for Chrome, Firefox, or the credential store.Credentialsscan+40 ptsIH-CRED-002highHard-coded secretPrivate keys and live tokens checked into a skill can be copied by anyone who reads the skill.Credentialsscan+40 ptsIH-CRED-003mediumSecret asked for in chat or memoryAsking the user to paste a secret into chat or memory stores it in the transcript.Credentialsscan+15 ptsIH-INJ-001highInstruction overridePhrases that tell the agent to ignore prior rules are a common way to hide malicious steps.Prompt injectionscan+40 ptsIH-INJ-002highHidden contentInvisible characters, HTML comments, and huge base64 blobs can hide instructions from a person reading the file.Prompt injectionscan+40 ptsIH-INJ-003highWeaken agent safeguardsInstructions to disable approvals or edit agent files change the trust boundary of the assistant.Prompt injectionscan+40 ptsIH-OBF-001mediumObfuscated codePacked or encoded payloads are used to hide a command from a person reviewing the skill.Obfuscationscan+15 ptsIH-PERSIST-001highPersistence mechanismScheduled tasks, login hooks, and shell startup files keep code running after the skill is closed.Persistencescan+40 ptsIH-PRIV-001highPrivilege or OS protection bypasssudo, broad chmod, and commands that turn off Gatekeeper or firewall protections weaken the host.Privilegescan+40 ptsIH-BIN-001highBundled executable or archiveExecutables and archives shipped inside a skill can hide an installer. Archives are flagged and never extracted.Binariesscan+40 ptsIH-FS-001mediumSuspicious filesystem accessSymlinks that leave the skill, path traversal, and hidden files can read or hide data outside the skill.Filesystemscan+15 ptsIH-META-001lowSkill metadata problemOpenClaw discovers a skill from SKILL.md frontmatter. Missing fields make the skill harder to identify and review.Metadatascan+5 ptsIH-MCP-001highMCP server launched from a remote commandAn MCP config that starts a server with curl piped into a shell, or with npx of a package that is not pinned to a version, runs code the operator has not reviewed. A shell pipe is critical. A pinned package such as name@1.2.3, a local path, and a local node script are not.MCP configscan+40 ptsIH-MCP-002highSecret in an MCP server environmentA literal secret in an MCP server env block is copied onto disk and into the server process. A reference such as ${API_KEY} is not a literal.MCP configscan+40 ptsIH-MCP-003mediumMCP server given a broad filesystem rootA filesystem MCP server pointed at /, a drive root, or a home directory can read far more than the project. A subdirectory such as ./notes or /home/alex/projects/notes is not a broad root.MCP configscan+15 ptsIH-INT-001highSkill file modifiedA file in an installed skill no longer matches the saved baseline.Integrityverify+40 ptsIH-INT-002mediumNew skill fileA file or skill directory appeared after the baseline was created.Integrityverify+15 ptsIH-INT-003mediumSkill file removedA file that was in the baseline is gone.Integrityverify+15 ptsIH-INT-004highWatched agent file changedAn agent instruction, personality, memory, or config file changed since the baseline.Integrityverify+40 ptsIH-ADV-001criticalAdvisory feed matchThe cached signed advisory feed lists this skill name, a file content hash, or an indicator host. The match is reported only when a local cache is present. Scan does not contact the network to refresh the feed.Advisory feedscan+100 ptsIH-CFG-001highGateway bind is not loopbackgateway.bind is lan, tailnet, custom, auto, or an all-interfaces address, or gateway.tailscale.mode is funnel. OpenClaw's native check gateway.bind_no_auth covers a remote bind without a shared secret, and gateway.tailscale_funnel covers public Funnel. This rule only reads the config value. It does not probe the listener. auto is medium because the effective bind is chosen at runtime. Funnel and 0.0.0.0 are critical.OpenClaw configaudit-config+40 ptsIH-CFG-002criticalGateway auth is missing or a placeholdergateway.auth.mode is none or trusted-proxy, a non-loopback bind has no auth object, or the token or password in the file is empty or a known placeholder. Native checks gateway.bind_no_auth, gateway.loopback_no_auth, gateway.token_placeholder_value, and gateway.trusted_proxy_auth overlap this rule. A loopback bind that omits auth is not flagged: OpenClaw's default is authenticated, and the token may live in OPENCLAW_GATEWAY_TOKEN, which this command does not read. trusted-proxy is critical because the proxy becomes the auth boundary; proxy IPs and headers are left to the native audit.OpenClaw configaudit-config+100 ptsIH-CFG-003criticalDM policy is openA channel dmPolicy (or dm.policy) is open, so anyone can DM the agent. This matches the native check channels.<channel>.dm.open. Mutable allowFrom entries and name matching are not reimplemented.OpenClaw configaudit-config+100 ptsIH-CFG-004highGroup policy is openA channel groupPolicy is open, so any member of a group can talk to the agent. Severity rises to critical when the same config also enables host exec, elevated tools, or an open DM policy. Native security.exposure.open_groups_with_elevated and security.exposure.open_channels_with_exec cover the live combination; this rule only reads the file.OpenClaw configaudit-config+40 ptsIH-CFG-005highPlaintext secret in OpenClaw configA token, password, secret, or API key is a literal string in the config file. ${ENV} references and SecretRef objects (source env, file, exec, or store) are not literals. Placeholder literals are reported as IH-CFG-002 instead. Evidence is the key path plus <redacted>. Native config.secrets.gateway_password_in_config and config.secrets.hooks_token_in_config are the overlapping checks; other secret keys in the file are reported here too.OpenClaw configaudit-config+40 ptsIH-CFG-006criticalOpenClaw config permissionsOn POSIX, the config file is group-writable, world-writable, world-readable, or group-readable. A symlink is reported at medium severity because OpenClaw documents that a symlinked openclaw.json is unsupported. Native checks fs.config.perms_world_readable, fs.config.perms_writable, fs.config.perms_group_readable, and fs.config.symlink. Windows ACLs are not Unix mode bits. This rule does not report permission findings on Windows and does not run icacls. OpenClaw's audit does.OpenClaw configaudit-config+100 ptsIH-CFG-007highDangerous tool permissionstools.exec.security or an agent exec security is full, exec ask is off while security is not deny, or tools.elevated is enabled. Elevated allowFrom containing * is critical. Native tools.exec.security_full_configured and tools.elevated.allowFrom.<channel>.wildcard overlap this rule. Interpreter allowlists, safeBins, and approval-file drift are left to the native audit.OpenClaw configaudit-config+40 ptsIH-CFG-008mediumSkills load from an extra directoryskills.load.extraDirs or skills.load.allowSymlinkTargets is set. Extra directories are the lowest-precedence skill roots and are trusted by the operator. OpenClaw tells you to keep allowSymlinkTargets narrow. A home directory, a filesystem root, or a path that contains .. is critical. Other extra directories are medium. The native audit does not have this check; it does have skills.workspace.symlink_escape, which walks the workspace and is not repeated here.OpenClaw configaudit-config+15 ptsIH-CFG-009mediumSandbox disabled while tools can actSandbox mode is off, or sandbox.docker is set while mode is off, and the file also enables host exec, elevated tools, or an open room. A personal agent with sandbox off and tools.exec.security deny is a documented OpenClaw pattern and stays quiet. Native sandbox.docker_config_mode_off and the security.exposure.open_groups_with_runtime_or_fs checks overlap the noisy cases. Docker bind mounts, seccomp, and AppArmor are not reimplemented.OpenClaw configaudit-config+15 ptsIH-LLM-001infoAdvisory model reviewAn optional language-model review added a note. This is not a pattern rule and it does not scan files by itself. The model sees redacted skill text and the deterministic findings, and it can be wrong. The note never changes the verdict or the exit code. It appears only after `scan --llm` or `review`, and only when the model output matched the review schema.Model reviewreview+0 pts
How severity turns into a verdict
Each finding adds points: critical 100, high 40, medium 15, low 5. A skill is block when any finding is critical or the total reaches 80; it is review when any finding is high or medium or the total reaches 15. You can change both thresholds, turn rules off, or change a rule's severity in the config. See configuration.
The rule list and metadata on this site are checked against the CLI's docs/rules.md on every build, so the ids, severities, and summaries here match the released scanner. Rules describe known patterns. A skill that matches none of them can still be harmful, and files larger than 1 MiB are skipped without being read and make the verdict incomplete, so they are never covered; read Limitations.