# Threat Model and Security Implementation Details of the Agent Skills System

> Explore the threat model and security implementation details of the agent skills system. Learn how defense-in-depth, filesystem isolation, and crypto integrity protect against attacks.

- Repository: [TechLeads.club 💎/agent-skills](https://github.com/tech-leads-club/agent-skills)
- Tags: security
- Published: 2026-05-18

---

**The agent skills system implements a defense-in-depth architecture that mitigates malicious payloads, credential theft, supply chain attacks, and prompt injection through open-source transparency, filesystem isolation, cryptographic lockfile integrity, and automated security scanning.**

The `tech-leads-club/agent-skills` repository provides a curated, hardened skill registry designed to prevent the attack vectors identified in modern AI agent ecosystems. Understanding the threat model and security implementation details of the agent skills system is essential for developers installing third-party capabilities or contributing new skills to the registry. The following sections dissect the four primary threat categories and the specific technical controls implemented across the CLI, lockfile service, and MCP server.

## Threat Model Overview

According to the [SECURITY.md § Threat Model](https://github.com/tech-leads-club/agent-skills/blob/main/SECURITY.md#L9-L19), the system addresses four high-impact attack vectors identified in the Snyk 2026 Agent Threat Report:

- **Malicious Payloads**: Public marketplaces risk obfuscated binaries and black-box instructions. The Agent Skills system counters this by maintaining 100% open-source skills where every line is readable and auditable ([SECURITY.md § Open Source](https://github.com/tech-leads-club/agent-skills/blob/main/SECURITY.md#L13-L16)).

- **Credential Theft**: Silent exfiltration of environment variables is prevented through static CI/CD analysis that blocks skills containing suspicious network calls or secret access patterns ([SECURITY.md § Static Analysis](https://github.com/tech-leads-club/agent-skills/blob/main/SECURITY.md#L16-L18)).

- **Supply-Chain Attacks**: Malicious updates to existing skills are mitigated through immutable lockfiles with SHA-256 content hashing, ensuring skills cannot change without explicit upgrade authorization ([SECURITY.md § Lockfile Integrity](https://github.com/tech-leads-club/agent-skills/blob/main/SECURITY.md#L84-L101)).

- **Prompt Injection**: Hidden jailbreak instructions are prevented through mandatory human code-review of every prompt and strict curation policies ([SECURITY.md § Human Curation](https://github.com/tech-leads-club/agent-skills/blob/main/SECURITY.md#L18-L19)).

## Defense-in-Depth Security Implementation

### Input Sanitization and Path Validation

The CLI installer service validates all skill names before filesystem interaction. The `sanitizeName` function in [[`packages/cli/src/services/installer.ts`](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/installer.ts)](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/installer.ts#L4-L14) implements a whitelist-based filter:

```typescript
// packages/cli/src/services/installer.ts
export const sanitizeName = (name: string): string => {
  return (
    name
      .replace(/[\\/]/g, '')               // Remove path separators
      .replace(/[\0:*?"<>|]/g, '')         // Strip null/Windows-forbidden chars
      .replace(/^\.+|\s+$/g, '')           // Strip leading/trailing dots/spaces
      .replace(/\.{2,}/g, '')              // Collapse consecutive dots (no "..")
      .replace(/^\.+/, '')                 // No leading dots (hidden files)
      .substring(0, 255) || 'unnamed-skill'
  )
}

```

This prevents null byte injection, path separator poisoning, and directory traversal via dot sequences.

### Filesystem Isolation and Symlink Protection

After sanitization, the `isPathSafe` function performs strict path containment verification. Every resolved target must remain within the designated base directory:

```typescript
// packages/cli/src/services/installer.ts
export const isPathSafe = (basePath: string, targetPath: string): boolean => {
  const normalizedBase = normalize(resolve(basePath))
  const normalizedTarget = normalize(resolve(targetPath))
  return (
    normalizedTarget.startsWith(normalizedBase + sep) ||
    normalizedTarget === normalizedBase
  )
}

```

*Source:* [installer.ts § isPathSafe](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/installer.ts#L17-L23)

The installer additionally validates symlinks using `lstat` rather than `stat`, resolving the ultimate target to prevent directory traversal via symlink chains or loops ([installer.ts § Symlink validation](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/installer.ts#L63-L70)).

### Lockfile Integrity and Supply Chain Protection

The lockfile service in [[`packages/cli/src/services/lockfile.ts`](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/lockfile.ts)](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/lockfile.ts#L5-L33) ensures tamper-evident skill management through three mechanisms:

1. **Zod Schema Validation**: Strict type checking prevents malformed lockfiles.
2. **Atomic Writes**: The `writeLockfile` function writes to a temporary file before renaming, eliminating corruption during concurrent operations.
3. **SHA-256 Content Hashing**: Each skill entry stores a cryptographic hash of its files, enabling detection of on-disk modifications.

```typescript
// packages/cli/src/services/lockfile.ts
export const LockfileSchema = z.object({
  version: z.literal(2),
  skills: z.record(
    z.object({
      agents: z.array(z.string()),
      hash: z.string(), // SHA-256 of skill files
      installedAt: z.string().datetime(),
    })
  ),
})

export const writeLockfile = async (data: any) => {
  const tempPath = LOCKFILE_PATH + '.tmp'
  await promises.writeFile(tempPath, JSON.stringify(data, null, 2))
  await promises.rename(tempPath, LOCKFILE_PATH)
}

```

### Immutable Audit Logging

All skill lifecycle events are recorded in an append-only audit log. The [`logAction`](https://github.com/tech-leads-club/agent-skills/blob/main/packages/cli/src/services/audit.ts#L6-L9) function in [`audit.ts`](https://github.com/tech-leads-club/agent-skills/blob/main/audit.ts) writes JSON Lines entries to `~/.config/agent-skills/audit.log`, creating an immutable forensic trail:

```typescript
// packages/cli/src/services/audit.ts
export const logAction = async (entry: Record<string, any>) => {
  const line = JSON.stringify(entry) + '\n'
  await fs.appendFile(AUDIT_LOG_PATH, line, { encoding: 'utf8' })
}

```

### Automated Security Scanning

Before publication, every skill undergoes automated Snyk Agent Scanning. The CI pipeline uses a cached SHA-256 hash to skip unchanged skills, consulting the [`security-scan-allowlist.yaml`](https://github.com/tech-leads-club/agent-skills/blob/main/security-scan-allowlist.yaml) for managed false-positives. The scanning process blocks releases containing vulnerabilities or suspicious patterns ([SECURITY.md § Scanning](https://github.com/tech-leads-club/agent-skills/blob/main/SECURITY.md#L15-L34)).

### MCP Server Request Validation

The MCP server (`packages/mcp`) operates in a **read-only, diskless** mode. The [`fetch_skill_files`](https://github.com/tech-leads-club/agent-skills/blob/main/packages/mcp/src/utils.ts#L1-L7) function validates every requested file against the registry manifest before fetching from the CDN:

```typescript
// packages/mcp/src/utils.ts
export const fetch_skill_files = async (skillId: string, files: string[]) => {
  const allowedFiles = await getAllowedFiles(skillId)
  const invalid = files.filter(f => !allowedFiles.includes(f))
  if (invalid.length) {
    throw new Error(`Requested files not in skill manifest: ${invalid.join(', ')}`)
  }
  // Safe CDN fetch with encodeURIComponent...
}

```

This prevents path traversal attacks through the Model Context Protocol interface.

## Practical Security Examples

### Installing a Skill with Validation

When executing `npx agent-skills install codenavi --agent cursor`, the system performs:

1. **Name sanitization** via `sanitizeName` to remove path traversal sequences.
2. **Path containment** verification via `isPathSafe` ensuring installation stays within `~/.cache/agent-skills/`.
3. **Symlink resolution** to prevent indirect directory escapes.
4. **Hash computation** and atomic lockfile update.
5. **Audit logging** of the installation event:

```bash

# Resulting audit log entry

{"action":"install","skillName":"codenavi","agents":["cursor"],"success":1,"timestamp":"2026-04-12T08:30:00Z"}

```

### Verifying Lockfile Integrity

Programmatically verify skill integrity using the lockfile service:

```typescript
import { readLockfile } from '@tech-leads-club/agent-skills/cli/src/services/lockfile'

async function verifySkillIntegrity(skillName: string) {
  const lock = await readLockfile()
  const entry = lock.skills[skillName]
  
  if (!entry) throw new Error('Skill not installed')
  console.log(`SHA-256: ${entry.hash}`)
  console.log(`Installed: ${entry.installedAt}`)
  return entry.hash
}

```

### Secure MCP File Access

Requesting skill files through the MCP server automatically enforces manifest validation:

```typescript
import { fetch_skill_files } from '@tech-leads-club/agent-skills/mcp/src/utils'

// This succeeds only if 'templates/README.md' is in the skill manifest
const content = await fetch_skill_files('codenavi', ['templates/README.md'])

// This throws an error - file not in manifest
const illegal = await fetch_skill_files('codenavi', ['../../etc/passwd'])

```

## Summary

The agent skills system implements comprehensive threat model and security implementation details across multiple architectural layers:

- **Input validation** through `sanitizeName` regex filtering and `isPathSafe` path containment prevents directory traversal and injection attacks.
- **Supply chain security** via Zod-validated lockfiles with SHA-256 hashing ensures skill immutability and tamper detection.
- **Operational security** through append-only audit logging and atomic file operations supports forensic investigation.
- **Runtime protection** in the MCP server enforces manifest-based access controls, while automated Snyk scanning eliminates vulnerable code before publication.
- **Transparency guarantees** through mandatory open-source review and human curation mitigate prompt injection and malicious payloads.

## Frequently Asked Questions

### What are the main security threats addressed by the agent skills system?

The threat model focuses on four categories identified in the Snyk 2026 Agent Threat Report: malicious payloads through obfuscated code, credential theft via secret exfiltration, supply-chain attacks through unauthorized skill updates, and prompt injection hijacking LLM behavior. Each threat is mitigated through specific technical controls including open-source transparency, static analysis, cryptographic lockfiles, and human review processes.

### How does the system prevent path traversal attacks?

Path traversal is mitigated through a two-layer defense: first, the `sanitizeName` function strips path separators, null bytes, and dot sequences from skill names; second, the `isPathSafe` function verifies that every resolved absolute path remains within the designated base directory. Symbolic links are resolved using `lstat` rather than `stat` to prevent symlink-based directory escapes.

### What ensures that installed skills haven't been tampered with?

The lockfile integrity mechanism stores a SHA-256 cryptographic hash of every skill's files at installation time. The `readLockfile` function validates the lockfile against a strict Zod schema, and any on-disk modification to skill files would invalidate the stored hash, triggering a security violation on the next verification.

### How does the MCP server prevent unauthorized file access?

The MCP server operates read-only and validates all file requests against the skill registry manifest. The `fetch_skill_files` function rejects any requested file not explicitly listed in the manifest, preventing access to sensitive system files or directory traversal via the Model Context Protocol interface. No write operations are performed by the MCP server, minimizing the attack surface.