imported trust tier: a deliberately cautious posture that treats the skill’s contents as untrusted until you say otherwise.
This page covers how to import, what actually lands on disk, the trust model an imported skill runs under, and — honestly — what the import-time scan does and does not prove.
How to Import
There are two ways to import a skill. From the CLI:skills_manage tool: the import action takes the same parameters. It stays behind the tool’s admin-trust + approval + orch:skill triple gate — importing is never a silent, unattended action.
Sources
An archive may also be supplied as base64 bytes (
archiveBytes) rather than a URL — this is how an uploaded file reaches the pipeline. Whichever way the bytes arrive, they funnel into the same acquire -> unpack -> map -> scan -> install pipeline.
Registry import (well-known index)
source: "wellknown" installs a skill by name from a registry that publishes the /.well-known/skills/index.json convention. You give the registry origin with --registry (the tool parameter is registry), and <ref> is the skill name to look up in that registry’s index — not a URL. The index advertises each skill’s name and its file paths; Comis fetches index.json, finds your named skill, and fetches its advertised files.
The registry must be allowlisted first. A well-known import only proceeds if the registry’s origin is listed in the agent’s skills.import.registries allowlist. A registry that is not allowlisted refuses flatly, before any network fetch — and this refusal is not overridable by --confirm. Allowlisting a registry is a deliberate config edit, kept out-of-band from the import call; --confirm narrowly acknowledges a content change on a re-import (below), it never authorizes a new registry. The allowlist is default-empty, so no registry imports happen until you add one.
Every fetch — the index and each advertised file — goes through the same SSRF guard (DNS-pinned, metadata-blocked) and byte caps as an archive import. Each advertised path is validated, and a single unsafe path (absolute, .. traversal, or otherwise escaping) rejects the whole bundle rather than skipping the one file. The resolved files then enter the same acquire -> map -> scan -> install pipeline every source shares, so a well-known skill lands prompt-only at the imported trust tier with the same honest exec caveat — importing it adds instructions the agent may read, never the authority to run anything. The provenance record additionally pins the registry origin the skill came from, and a listed well-known skill reports source: "wellknown" plus that registry in its provenance summary.
Re-importing the same (registry, name) follows the same re-import rule as any source: identical content is a no-op, and changed remote bytes refuse unless you pass --confirm, which swaps in the new content and re-pins the hash.
ClawHub import
source: "clawhub" installs a skill from ClawHub by its @owner/slug identifier. <ref> is the @owner/slug — not a URL — and the registry is inferred, so you do not pass --registry. As with a well-known import, it only proceeds if the clawhub token is in the agent’s skills.import.registries allowlist; a non-allowlisted clawhub refuses flatly, and that refusal is not overridable by --confirm.
The verdict is checked before the release downloads. ClawHub resolution is an install-resolver flow: Comis fetches the install decision and the skill’s scan verdict, evaluates the verdict, and only then downloads the release archive. A release whose verdict is malicious, blockedFromDownload, quarantined, or revoked (or is otherwise reason-flagged as blocked) is refused before a single artifact byte is fetched — the download never happens. This is a hard security stop, not a warnable class: --confirm never overrides it.
Non-official publishers must be acknowledged. By default (requireOfficialPublisher is true), a skill from a non-official publisher records officialPublisher: false and requires --confirm to install — pulling an unofficial @owner/slug is a deliberate, acknowledged act, on a fresh install as much as on an update. Unlike a blocking verdict, this is a warnable class: acknowledged, not forbidden. When one import trips both warnable classes at once — a non-official publisher and a changed-content re-import (a pin divergence) — a single --confirm acknowledges both, and the response enumerates each acknowledged class in its warnings.
The official/non-official signal is asserted by the registry itself (its self-claimed publisher channel), so
requireOfficialPublisher is a publisher-provenance signal, not a cryptographic guarantee — a compromised registry could claim official. It is one honesty check among the layers below; the integrity floor an import actually rests on is the self-computed content hash (next) plus TLS, not this flag. Allowlisting a registry with clawhub is itself the deliberate trust decision.X-ClawHub-Artifact-Sha256), Comis verifies the downloaded bytes against it and rejects a mismatch — the header is checked when present and is never required. The always-present integrity floor is Comis’s own content hash, computed over the installed file set and pinned in provenance (the release is fetched over TLS from clawhub.ai), independent of any server-sent hash.
The resolved release then enters the same acquire -> unpack -> map -> scan -> install pipeline every source shares, so a ClawHub skill lands prompt-only at the imported trust tier — bundled MCP servers persist disabled, dynamic context forced off, text-only — with clawhub recorded as its registry and officialPublisher in its provenance summary. The same honest limit applies as for every import: it adds instructions the agent may read, never the authority to run anything, and the import scan is a strong deterministic net, not a proof of safety.
What Actually Lands: Text-Only Import
An import keeps only UTF-8 text files. Everything that could carry an execution vector is dropped before anything is written, and each drop is logged with a warning naming the exact trigger:- Anything under a
scripts/directory - Any entry that arrived with a Unix executable bit
- Any file with a known executable, script, or compiled-binary extension
- Any file that is not valid UTF-8 text
The Staged Pipeline
Every import — regardless of source — passes through the same ordered stages. A rejection at any stage is atomic: the staging area is removed and zero files reach your live skills directory.1
Acquire
Fetch the bytes. Archive URLs go through the SSRF guard with a compressed-size cap; GitHub directories are walked through the fixed-host Contents API.
2
Unpack (bounded)
Archives are unpacked by in-house readers that reject absolute paths,
.. traversal segments, symlink and hardlink entries, and over-depth paths, while stream-counting uncompressed bytes against a total cap. The size caps are operator-dialable.3
Map the manifest
A skill authored for another ecosystem — or in a legacy Comis form — is converged onto the spec-pure
SKILL.md shape. Fields with no internal home are dropped with a warning naming each key; an executable-entrypoint declaration is never carried across. See the manifest mapping reference.4
Scan (fail-closed, pre-write)
The content scanner runs on the SKILL.md body and every kept text file before anything is written. Any CRITICAL finding rejects the whole import. This scan is unconditional — it does not consult the load-time
contentScanning toggles. See Security Scanning.5
Install + pin provenance
Only the kept text files move into the live skills directory, under a serialized lock, and a provenance record is pinned recording the source, a content hash over the installed files, and the scan verdict. The install is stamped the
imported trust tier.The Imported Trust Tier
A bundled skill that ships with Comis is platform-trusted. An imported skill is not — and the tier has teeth that make that distinction real, not cosmetic:- Prompt-only. No executables land (see above), so there is nothing to run directly.
- Dynamic context is off. Shell-command execution inside a skill body (
enableDynamicContext) is forced off for an imported skill regardless of the global setting — an imported skill can never opt itself into running commands during context assembly. - Bundled MCP servers persist disabled. If an imported skill declares MCP servers, those entries are written with
enabled: falseand are never auto-connected at install. You opt in per server, and each connect re-runs the supply-chain (OSV) check at the connect site. There is intentionally no “auto-connect bundled MCP” configuration knob. - The model sees the tier. A listed imported skill carries
source: "imported"and a content-free provenance summary (acquisition channel, hash prefix, import timestamp), so both operators and the agent can tell a platform skill from an imported one.
<dataDir>/skill-provenance.json, owner-only). Because the imported skills directory is the same one bundled skills seed into, the provenance record is the only thing that marks a skill imported — and it is advisory downward only: a record can demote a skill to the imported tier, but its absence never elevates one.
What the Scan Proves — and What It Does Not
The import-time scan is a strong, deterministic safety net: it runs fail-closed on all staged text before any write, catches six categories of known-dangerous patterns, and cannot be silently disabled for imports. It meaningfully raises the bar against a hostile skill. This is defense in depth: the scan is one layer, and the tool policy plus sandbox are the layers that actually bound what an agent can do with what a skill tells it.Re-Importing and Updates
Re-importing a name that is already under provenance re-runs the full pipeline (the scan always runs again) and compares the recomputed content hash:- Identical hash — an idempotent no-op.
- Divergent hash — refuses unless you pass
--confirm, which swaps in the new content and re-pins the record. - A name with no provenance record, or whose record names a different source — refuses flatly. This is not overridable by
--confirm; delete the existing skill first, then import.
There is no
force override for import. --confirm narrowly acknowledges a content change on a re-import of the same source — it never overwrites an unrelated or platform-trusted skill of the same name. Editing an imported skill locally re-pins its hash and marks it locally modified, so the change is visible rather than silently diverging from the pinned content.Migrating Skills Imported Before the Pipeline
Provenance is forward-only. A skill installed by an older import path — before the staged pipeline existed — has no provenance record, so it keeps its path-derived source and is not retroactively stampedimported. There is deliberately no heuristic backfill: guessing a trust tier from a directory on disk is exactly the mistake the provenance store exists to prevent.
To bring such a skill under provenance, delete it and re-import it through the pipeline. The re-import scans it, records provenance, and stamps the imported tier — the same sanctioned path as any first import.
Configuration
The bounded-unpack caps live under each agent’sskills.import block. The defaults are conservative; raise them only if you knowingly import large skills. See skills.import in the config reference.
Security Scanning
The six-category scanner that runs fail-closed at import time
Skill Manifest
The SKILL.md format and the foreign-frontmatter mapping table
MCP Integration
How bundled MCP servers work — and why imported ones start disabled
Tool Policy
Bound what any agent can do, whatever a skill tells it
