| name | cloud-infrastructure-security |
| description | Enforce cloud security best practices across AWS, Vercel, Railway, and Cloudflare deployments. Always activate this skill when the user is deploying to a cloud platform, writing or reviewing IaC (Terraform, CloudFormation, Pulumi), configuring IAM roles or policies, managing secrets, setting up CI/CD pipelines, configuring databases or storage, implementing logging/monitoring, or asking about cloud security — even if they don't explicitly mention security. When in doubt, activate. A missed security check is harder to fix than an unrequested one. |
Cloud & Infrastructure Security Skill
This skill ensures cloud infrastructure, CI/CD pipelines, and deployment configurations follow security best practices and comply with industry standards.
Workflow
When this skill activates:
- Identify the scope from user context — which cloud(s), which services, which stage (new build vs. review vs. pre-deploy).
- Navigate to the relevant section(s) below. For broad requests, cover all applicable sections. For narrow ones (e.g., "set up CI/CD"), go straight to that section.
- Surface the applicable checklist and code patterns for the user's specific stack. Adapt examples to the user's language/framework when possible.
- Run the pre-deployment checklist any time a deployment is imminent — even if unsolicited. Cloud misconfigurations are the leading cause of data breaches; a quick checklist review is always worth it.
- Flag misconfigurations proactively. If you spot an issue in code the user shares (an open security group, a public RDS instance, hardcoded credentials), call it out immediately — don't wait to be asked.
1. IAM & Access Control
The principle of least privilege is the single most impactful security control in cloud environments. Overly broad permissions are the root cause of most privilege escalation attacks.
Least Privilege Policies
iam_role:
permissions:
- s3:GetObject
- s3:ListBucket
resources:
- arn:aws:s3:::my-bucket/*
iam_role:
permissions:
- s3:*
resources:
- "*"
Service Accounts & OIDC
Prefer short-lived federated credentials over long-lived access keys. OIDC lets services like GitHub Actions assume roles without storing any secret.
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1
MFA
aws iam enable-mfa-device \
--user-name admin \
--serial-number arn:aws:iam::123456789:mfa/admin \
--authentication-code1 123456 \
--authentication-code2 789012
Checklist
2. Secrets Management
Secrets in code or environment variables are accidents waiting to happen — they end up in logs, error traces, and git history. Store them in a managed service with auditing and rotation.
Cloud Secrets Managers
import { SecretsManager } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManager({ region: 'us-east-1' });
const secret = await client.getSecretValue({ SecretId: 'prod/api-key' });
const apiKey = JSON.parse(secret.SecretString!).key;
const apiKey = process.env.API_KEY;
Automatic Rotation
aws secretsmanager rotate-secret \
--secret-id prod/db-password \
--rotation-lambda-arn arn:aws:lambda:region:account:function:rotate \
--rotation-rules AutomaticallyAfterDays=30
Checklist
3. Encryption
Encryption should be non-negotiable for any data touching production — at rest to protect against storage breaches, in transit to prevent interception.
Encryption at Rest
# ✅ CORRECT: Encrypted RDS instance
resource "aws_db_instance" "main" {
storage_encrypted = true
kms_key_id = aws_kms_key.rds.arn
# ... other config
}
# ✅ CORRECT: Encrypted S3 bucket (enforce via bucket policy)
resource "aws_s3_bucket_server_side_encryption_configuration" "main" {
bucket = aws_s3_bucket.main.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3.arn
}
bucket_key_enabled = true
}
}
Encryption in Transit
# ✅ CORRECT: Enforce HTTPS-only on S3 via bucket policy
resource "aws_s3_bucket_policy" "enforce_tls" {
bucket = aws_s3_bucket.main.id
policy = jsonencode({
Statement = [{
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = ["${aws_s3_bucket.main.arn}/*", aws_s3_bucket.main.arn]
Condition = { Bool = { "aws:SecureTransport" = "false" } }
}]
})
}
# Enforce TLS 1.2+ on RDS (parameter group)
resource "aws_db_parameter_group" "tls" {
family = "postgres15"
parameter {
name = "rds.force_ssl"
value = "1"
}
}
Checklist
4. Network Security
Your network perimeter is the outermost layer of defense. Keep it tight — anything publicly exposed is an attack surface.
VPC & Security Groups
# ✅ CORRECT: Minimal-ingress security group
resource "aws_security_group" "app" {
name = "app-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"] # Internal VPC only
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # HTTPS outbound only
}
}
# ❌ WRONG: Never open all ports to the internet
resource "aws_security_group" "bad" {
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Common Misconfigurations to Catch
aws s3api put-bucket-acl --bucket my-bucket --acl public-read
aws s3api put-bucket-acl --bucket my-bucket --acl private
aws s3api put-bucket-policy --bucket my-bucket --policy file://policy.json
# ❌ Publicly accessible RDS — extremely dangerous
resource "aws_db_instance" "bad" {
publicly_accessible = true
}
# ✅ Private RDS in VPC
resource "aws_db_instance" "good" {
publicly_accessible = false
vpc_security_group_ids = [aws_security_group.db.id]
db_subnet_group_name = aws_db_subnet_group.private.name
}
Checklist
5. Logging & Monitoring
You can't defend what you can't see. Comprehensive logging is the foundation of incident detection, forensics, and compliance.
CloudWatch / Structured Logging
import { CloudWatchLogsClient } from '@aws-sdk/client-cloudwatch-logs';
const logSecurityEvent = async (event: SecurityEvent) => {
await cloudwatch.putLogEvents({
logGroupName: '/aws/security/events',
logStreamName: 'authentication',
logEvents: [{
timestamp: Date.now(),
message: JSON.stringify({
type: event.type,
userId: event.userId,
ip: event.ip,
result: event.result,
})
}]
});
};
Alerting
Set up alarms for high-signal security events. Don't wait to be breached before noticing.
aws cloudwatch put-metric-alarm \
--alarm-name "RootAccountUsage" \
--metric-name "RootAccountUsageCount" \
--namespace "CloudTrailMetrics" \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--alarm-actions arn:aws:sns:us-east-1:123456789:SecurityAlerts
Checklist
6. CI/CD Pipeline Security
Your pipeline has broad production access — it's a high-value target. Treat it with the same rigor as your production environment.
Secure GitHub Actions Workflow
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Secret scanning
uses: trufflesecurity/trufflehog@main
- name: Audit dependencies
run: npm audit --audit-level=high
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
aws-region: us-east-1
- name: Deploy
run: ./scripts/deploy.sh
Supply Chain Security
{
"scripts": {
"install": "npm ci",
"audit": "npm audit --audit-level=moderate",
"check": "npm outdated"
}
}
Checklist
7. CDN & Edge Security (Cloudflare)
Cloudflare is your outermost perimeter. Configure it correctly and you absorb DDoS, filter malicious traffic, and add headers before requests ever reach your origin.
Security Headers via Workers
export default {
async fetch(request: Request): Promise<Response> {
const response = await fetch(request);
const headers = new Headers(response.headers);
headers.set('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
headers.set('X-Frame-Options', 'DENY');
headers.set('X-Content-Type-Options', 'nosniff');
headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
headers.set('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
headers.set('Content-Security-Policy', "default-src 'self'; script-src 'self'");
return new Response(response.body, { status: response.status, headers });
}
};
WAF Configuration
Enable via Cloudflare dashboard or Terraform (cloudflare_ruleset):
- OWASP Core Ruleset + Cloudflare Managed Ruleset
- Rate limiting on sensitive endpoints (auth, password reset)
- Bot Fight Mode
- Geo-blocking if your user base doesn't span high-risk regions
Checklist
8. Backup & Disaster Recovery
Backups are only valuable if they can actually restore you. Automate everything and test restores on a schedule.
Automated Backups
resource "aws_db_instance" "main" {
allocated_storage = 20
engine = "postgres"
backup_retention_period = 30 # 30 days
backup_window = "03:00-04:00"
maintenance_window = "mon:04:00-mon:05:00"
deletion_protection = true # Prevent accidental deletion
enabled_cloudwatch_logs_exports = ["postgresql"]
}
Checklist
9. Compliance (GDPR / HIPAA / SOC 2)
Compliance requirements vary by regulation. Flag them early — they affect architecture decisions (data residency, encryption key control, logging) that are painful to change later.
GDPR: Document all PII data flows. Implement data subject rights (access, erasure, portability). Sign DPAs with all processors. 72-hour breach notification to supervisory authority. Minimize data collected and retained.
HIPAA: BAAs with all vendors touching PHI. Audit log all PHI access. Minimum necessary access standard. PHI encrypted at rest and in transit (§3).
SOC 2: Formalize security policies, access reviews, and IR procedures. Collect evidence continuously (logs, change records, reviews). Vendor risk program.
Checklist:
10. Incident Response
Having a plan before an incident is the difference between a recoverable event and a catastrophe.
Steps: Detect → Contain → Investigate → Eradicate → Recover → Post-mortem
aws iam update-access-key \
--access-key-id AKIAIOSFODNN7EXAMPLE \
--status Inactive \
--user-name compromised-user
aws iam put-user-policy \
--user-name compromised-user \
--policy-name EmergencyDenyAll \
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*"}]}'
Key principles: preserve logs before remediating (evidence!), rotate all credentials after containment, write a blameless post-mortem within 5 business days.
Checklist:
Pre-Deployment Security Checklist
Run this before every production deployment:
Resources