From security-snyk
Use when fixing Snyk IaC alerts — cloud misconfiguration remediation patterns per provider (Terraform, CloudFormation, Kubernetes) with concrete configuration examples
How this skill is triggered — by the user, by Claude, or both
Slash command
/security-snyk:snyk-iac-remediationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Snyk IaC scans Infrastructure-as-Code (Terraform, CloudFormation, Kubernetes, ARM templates) to identify cloud misconfigurations. This skill provides fix patterns per provider and resource type.
Snyk IaC scans Infrastructure-as-Code (Terraform, CloudFormation, Kubernetes, ARM templates) to identify cloud misconfigurations. This skill provides fix patterns per provider and resource type.
Vulnerability: Bucket exposed to public access / unencrypted
Fix Pattern:
resource "aws_s3_bucket" "example" {
bucket = "my-bucket"
}
# Block public access
resource "aws_s3_bucket_public_access_block" "example" {
bucket = aws_s3_bucket.example.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Enable encryption at rest
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.example.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.example.arn
}
}
}
# Enable versioning
resource "aws_s3_bucket_versioning" "example" {
bucket = aws_s3_bucket.example.id
versioning_configuration {
status = "Enabled"
}
}
# Enable access logging
resource "aws_s3_bucket_logging" "example" {
bucket = aws_s3_bucket.example.id
target_bucket = aws_s3_bucket.log_bucket.id
target_prefix = "logs/"
}
Vulnerability: Ingress from 0.0.0.0/0 (entire internet)
Fix Pattern:
# Bad: open to everyone
resource "aws_security_group" "bad" {
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # INSECURE
}
}
# Good: restrict to specific IPs
resource "aws_security_group" "good" {
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["192.168.1.0/24"] # Specific network
}
}
# Good: use security group references
resource "aws_security_group" "bastion" {
# Allow traffic from bastion only
}
resource "aws_security_group_rule" "app_from_bastion" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
security_group_id = aws_security_group.app.id
source_security_group_id = aws_security_group.bastion.id
}
Vulnerability: Wildcard permissions (Action = "", Resource = "")
Fix Pattern:
# Bad: overly permissive
resource "aws_iam_policy" "bad" {
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "s3:*" # INSECURE: all S3 actions
Resource = "*" # INSECURE: all resources
}
]
})
}
# Good: least privilege
resource "aws_iam_policy" "good" {
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:ListBucket"
]
Resource = [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
})
}
# Good: with conditions
resource "aws_iam_policy" "conditional" {
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "s3:GetObject"
Resource = "arn:aws:s3:::my-bucket/*"
Condition = {
IpAddress = {
"aws:SourceIp" = "192.168.1.0/24"
}
}
}
]
})
}
Vulnerability: Unencrypted database / no backup / no deletion protection
Fix Pattern:
resource "aws_db_instance" "example" {
identifier = "my-database"
# Enable encryption at rest
storage_encrypted = true
kms_key_id = aws_kms_key.example.arn
# Enable automated backups
backup_retention_period = 30
backup_window = "03:00-04:00"
# Protect from accidental deletion
deletion_protection = true
# Enable Multi-AZ for high availability
multi_az = true
# Enforce strong password
password = random_password.db_password.result
# Disable public IP assignment
publicly_accessible = false
# Enable audit logging
enabled_cloudwatch_logs_exports = ["error", "general", "slowquery"]
skip_final_snapshot = false
final_snapshot_identifier = "my-database-final-snapshot"
}
Vulnerability: No VPC / unrestricted execution role
Fix Pattern:
# Restrict Lambda execution role
resource "aws_iam_role" "lambda_role" {
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
# Attach minimal permissions
resource "aws_iam_role_policy" "lambda_policy" {
role = aws_iam_role.lambda_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
Resource = "arn:aws:logs:*:*:*"
}
]
})
}
# Run in VPC for network isolation
resource "aws_lambda_function" "example" {
function_name = "my-function"
role = aws_iam_role.lambda_role.arn
vpc_config {
subnet_ids = [aws_subnet.private.id]
security_group_ids = [aws_security_group.lambda.id]
}
timeout = 60
# Use Graviton2 for better security/performance
architectures = ["arm64"]
environment {
variables = {
# Never hardcode secrets
LOG_LEVEL = "INFO"
}
}
}
Vulnerability: Running as root / privileged access
Fix Pattern:
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
# Pod-level security context
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:1.0.0
# Container-level security context
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
Vulnerability: No network segmentation (all pods can communicate)
Fix Pattern:
# Deny all ingress by default
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
---
# Allow specific ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
spec:
podSelector:
matchLabels:
tier: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
---
# Deny egress to external networks
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-external-egress
spec:
podSelector:
matchLabels:
restrict-egress: "true"
policyTypes:
- Egress
egress:
- to:
- podSelector: {}
ports:
- protocol: TCP
port: 8080
Fix Pattern (Terraform):
resource "azurerm_storage_account" "example" {
account_replication_type = "RAGRS"
https_traffic_only_enabled = true
# Enable encryption with customer-managed keys
customer_managed_key {
key_vault_key_id = azurerm_key_vault_key.example.id
}
}
Fix Pattern (Terraform):
resource "google_storage_bucket" "example" {
location = "US"
# Enable uniform bucket-level access
uniform_bucket_level_access = true
# Encrypt with customer-managed key
encryption {
default_kms_key_name = google_kms_crypto_key.example.id
}
}
After applying fixes:
terraform validateterraform plansnyk iac test . --severity-threshold=high| Issue | Pattern | Fix |
|---|---|---|
| Public bucket | S3 block_public_acls | Set to true |
| Unencrypted DB | RDS storage_encrypted | Set to true |
| Open security group | Ingress 0.0.0.0/0 | Restrict to specific IPs |
| Wildcard IAM | Action = "*" | Specify exact actions |
| Root container | runAsUser = 0 | Set to non-zero user ID |
| Privileged pod | allowPrivilegeEscalation | Set to false |
| No network policy | None | Create deny-all + allow rules |
npx claudepluginhub gagandeepp/software-agent-teams --plugin security-snykGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.