On September 7, 2026, grith.ai published "An agent skill can hand a stranger your shell — hours after you installed it". Two days earlier, Jeff Dickey (creator of mise) announced packslip, a signed release manifest that vendors publish alongside their binaries. Both pieces hit the same structural problem from opposite angles: the Agent Skills ecosystem has solved distribution. It has not solved authority.
The format distributes code. It does not bound it.
The Agent Skills specification defines a portable folder format. A skill contains a SKILL.md with frontmatter (name, description, license, compatibility, metadata) and an optional scripts/ directory for executable Python, Bash and JavaScript. The authoring guide shows skills invoking uvx, npx, bunx, deno run and go run — packages resolved at execution time.
What the specification does not provide is a portable way to limit what that code can do. The allowed-tools frontmatter field names high-level tool categories (e.g. Read, Bash(git:*)) but the spec marks it experimental, notes support varies between clients, and crucially: it names tools rather than authority. Read does not answer which paths. Bash(git:*) does not answer which repository, remote or credentials. It says nothing about child processes, DNS, listening sockets or secrets.
So the portable format has a standard place for executable code, but no standard way to bound that code's effects.
Progressive disclosure delays the risk
Skills use progressive disclosure. At startup, an agent sees each skill's name and description. When a task matches, it loads the full SKILL.md. It reads supporting files and runs bundled scripts only when the instructions call for them.
That is good context management. It is awkward security timing.
The developer may inspect and install a skill on Monday. On Thursday, during an unrelated-looking repository task, the agent decides the description matches and activates it. A plausible malicious chain then looks like this:
- The skill tells the agent to run
python3 scripts/report.pyas a routine preparation step. - The script searches for configuration that will supposedly improve its report.
- It reads a neighbouring project's
.env, a Git credential store or a cloud credential file. - It sends the result to an external endpoint or uses the developer's existing authenticated tooling to publish it.
- It returns a normal-looking report, so the user sees no obvious failure.
Nothing in that chain requires a memory-corruption exploit. The skill asks the agent to use capabilities the agent already has. The Markdown is a delayed control plane for code execution under ambient developer authority.
How dangerous is that? It depends on the agent's runtime posture
| Runtime posture | Consequence of a malicious skill |
|---|---|
| Read-only workspace, no network, no secrets | Mostly prompt manipulation and exposure of workspace content |
| Workspace write access plus package execution | Source tampering and dependency compromise |
| Home-directory reads plus outbound network | Credential and private-project exfiltration |
| Full shell with approval bypass | Developer-account compromise and persistence |
| CI runner with repository or deployment credentials | Supply-chain or production compromise |
Native agent sandboxes and approval prompts matter. They reduce risk when they are enabled and narrowly configured. They are not part of the portable skill contract, however, and a skill that works across many clients does not receive one consistent security boundary.
Packslip solves signed delivery. It does not solve behaviour.
Packslip is a vendor-published, Sigstore-signed manifest that sits alongside a release. It tells package managers (currently mise) which binaries to download, how to verify them, and — critically for this discussion — where to find matching shell completions and agent skills for that exact version.
{
"resources": [{
"kind": "skill",
"name": "hk-configure",
"repo": "skills/hk-configure"
}]
}
Mise downloads the declared skills into the tool version's installation directory. Making them available to the agent is a separate, opt-in step (mise skills sync --dir .agents/skills). The packslip announcement states the limit precisely: "A verified signature tells you where the instructions came from. It doesn't establish that they're appropriate for your project."
Signed skills are better than unsigned skills. Version pins, checksums, release-age delays and independent review all remove real supply-chain risks. They answer: who published this? Are these the bytes they signed? Did the contents change between releases? Has a reviewer approved this exact version?
They do not answer: which files may it read or modify? Which credentials may it use? Which processes may it spawn? Which hosts may receive data? Did its runtime behaviour match its declared purpose?
A trusted author can make a mistake. A legitimate release can contain an over-broad helper. An acquired or compromised publisher can sign malicious instructions perfectly. Provenance is necessary, but a valid signature is not a safety verdict.
What a real permissions manifest needs
A useful extension would declare concrete resources and effects, not just high-level tool names. For example:
requested-permissions:
filesystem:
read:
- '${workspace}/src/**'
- '${workspace}/package.json'
write:
- '${workspace}/generated/**'
process:
spawn:
- 'python3'
- 'git'
network:
connect:
- 'api.x.com:443'
secrets:
use:
- 'X_API_TOKEN'
This is illustrative, not current Agent Skills syntax. The important semantics are:
- The skill requests authority. It does not grant authority to itself. The host or an external policy must intersect the request with what the operator permits.
- Objects are explicit. Filesystem permissions name paths, network permissions name destinations, secret permissions name handles and process permissions name executable identities.
- Children inherit the boundary. Running an allowed
python3cannot become a tunnel around the policy. - Undeclared effects fail closed. A skill that requests workspace reads and then reaches for
~/.ssh/id_ed25519does not get a warning label. It gets a denied read. - Observed behaviour is recorded. The audit should show what was requested, granted, attempted and denied.
This direction already has research behind it. SkillGuard proposes treating skills as permission-bearing executable artefacts, combining manifests, deny-by-default runtime access control and behaviour monitoring. Its evaluation also shows why nobody should market manifests as a complete solution: the framework reduced attack success, but did not reduce it to zero.
Permission metadata is a contract. Runtime enforcement is what makes breaking the contract consequential.
Where Grith sits today
Grith does not currently parse SKILL.md, verify skill signatures or identify which active skill caused an operation. When Claude runs a skill, Grith sees the caller as the supervised Claude session, not as [email protected].
What Grith does provide is the enforcement layer underneath the agent:
grith exec --workspace-only -- claude
The skill can persuade Claude to run Python. It cannot persuade Grith that Python's subsequent syscalls did not happen.
| The skill tells the agent to... | Grith evaluates... |
|---|---|
| Run a bundled helper | The process spawn, arguments, executable provenance and child process tree |
Read an SSH key, .env or cloud credential |
The actual file path, sensitivity and resulting data taint |
| Send data elsewhere | DNS queries, destination, port, egress reputation and prior sensitive reads |
| Rewrite or delete files | The target path, operation risk, rate and destructive pattern |
Hand work to Docker, systemd-run or a desktop control socket |
The attempted authority delegation before work escapes the supervised tree |
With --workspace-only, filesystem access outside the project boundary is denied before the normal read-noise shortcuts. Necessary system runtime reads and paths explicitly trusted by the selected agent profile remain reachable. The sensitive-path, taint, egress and process filters still apply independently.
That final qualification matters. Grith's shipped Claude and Codex profiles trust their own state directories, including ~/.claude/** and ~/.codex/**, for routine operation. Skill files in those trees can currently be read and modified without a skill-specific decision. Grith limits the effects a skill causes elsewhere, but it is not yet a skill package manager or a per-skill capability system.
The missing join
The complete model has three separate layers:
- Signed delivery: establish publisher identity, version and exact bytes.
- Requested permissions: describe the maximum authority the skill says it needs.
- Runtime enforcement: constrain and audit the effects the agent actually attempts.
Packslip is pushing the first layer forward. The Agent Skills ecosystem needs to standardise the second. Grith already supplies much of the third at the agent-process boundary.
The next step is to join them: resolve the active skill to a canonical path and content hash, carry that identity into the syscall context, convert its requested permissions into subtractive runtime policy, and report declared versus observed behaviour. Crucially, those restrictions must run before convenience allowlists. Otherwise the most familiar paths and commands become the easiest place to hide.
This also gives skill authors something they do not have today: a testable least-authority contract. A PDF skill could prove that its integration tests touch only the selected document and output directory. An X publishing skill could prove that it connects only to the declared API host and never reads unrelated credentials. A release could fail if observed behaviour widens without a reviewed manifest change.
That is more useful than a badge saying "scanned". It is evidence.
A skill is not dangerous because it is Markdown
It is dangerous because Markdown can select code, and the code inherits authority that was granted to the agent for an entirely different reason.
The ecosystem is making skill discovery, installation, signing and synchronisation dramatically easier. That is good work. Before one-command installation becomes the default, the runtime contract needs to catch up.
For every skill, users should be able to answer four questions before and after it runs:
- Who shipped it?
- What authority did it request?
- What authority was actually granted?
- What did it attempt to do?
Today, an agent skill can bundle Python. It still can't declare which files that Python may read.
Signing the skill proves who made that decision. A permissions manifest makes the decision visible. Enforcement underneath the agent is what makes it real.
If this was useful, you can support my open-source work on Ko-fi or check out my services.