aws-cloudformation-security — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited aws-cloudformation-security (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Create production-ready security infrastructure using AWS CloudFormation templates. This skill covers KMS encryption, Secrets Manager, IAM security with least privilege, VPC security configurations, ACM certificates, parameter security, secure outputs, cross-stack references, CloudWatch Logs encryption, defense in depth strategies, and security best practices.
Follow these steps to create security infrastructure with CloudFormation:
Create customer-managed keys for encryption:
Resources:
EncryptionKey:
Type: AWS::KMS::Key
Properties:
Description: Customer-managed key for data encryption
KeyPolicy:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- kms:Decrypt
- kms:GenerateDataKey
Resource: "*"
- Effect: Allow
Principal:
AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
Action:
- kms:*
Resource: "*"
KeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: !Sub "${AWS::StackName}/encryption-key"
TargetKeyId: !Ref EncryptionKeyValidate: aws kms get-key-policy --key-id <key-id> --output text
Store and retrieve sensitive data securely:
Resources:
DatabaseSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub "${AWS::StackName}/database"
Description: Database credentials
SecretString: !Sub |
{
"username": "admin",
"password": "${DatabasePassword}",
"engine": "mysql",
"host": "${DatabaseEndpoint}",
"port": 3306
}
KmsKeyId: !Ref EncryptionKey
SecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
Properties:
SecretId: !Ref DatabaseSecret
RotationLambdaARN: !Ref RotationLambda.Arn
RotationRules:
AutomaticallyAfterDays: 30Validate: aws secretsmanager describe-secret --secret-id <secret-name>
Create roles and policies with minimal required permissions:
Resources:
ExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: SpecificPermissions
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource: !Sub "${DataBucket.Arn}/*"Validate: aws iam simulate-principal-policy --policy-source-arn <role-arn> --action-names s3:GetObject --resource-arns <bucket-arn>
Implement network security with security groups and NACLs:
Resources:
ApplicationSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Application security group
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
ApplicationNACL:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
NACLEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref ApplicationNACL
RuleNumber: 100
Protocol: "6"
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 443
To: 443Validate: aws ec2 describe-security-groups --group-ids <sg-id> --query 'SecurityGroups[0].IpPermissions'
Manage TLS/SSL certificates for secure communication:
Resources:
Certificate:
Type: AWS::ACM::Certificate
Properties:
DomainName: !Ref DomainName
SubjectAlternativeNames:
- !Sub "www.${DomainName}"
- !Sub "api.${DomainName}"
DomainValidationOptions:
- DomainName: !Ref DomainName
ValidationDomain: !Ref DomainName
Tags:
- Key: Environment
Value: !Ref Environment
# DNS validation record
DnsValidationRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: !Ref HostedZone
Name: !Sub "_${DomainName}."
Type: CNAME
TTL: 300
ResourceRecords:
- !Ref CertificateValidate: aws acm describe-certificate --certificate-arn <arn> --query 'Certificate.Status'
Use SecureString for sensitive parameter values:
Resources:
DatabasePasswordParameter:
Type: AWS::SSM::Parameter
Properties:
Name: !Sub "/${AWS::StackName}/database/password"
Type: SecureString
Value: !Ref DatabasePassword
Description: Database master password
KmsKeyId: !Ref EncryptionKey
# Reference in other resources
DatabaseInstance:
Type: AWS::RDS::DBInstance
Properties:
MasterUsername: admin
MasterUserPassword: !Ref DatabasePasswordParameterValidate: aws ssm get-parameter --name <param-name> --with-decryption --query 'Parameter.Type'
Export only non-sensitive values from stacks:
Outputs:
# Safe to export
KMSKeyArn:
Description: KMS Key ARN for encryption
Value: !GetAtt EncryptionKey.Arn
Export:
Name: !Sub "${AWS::StackName}-KMSKeyArn"
SecretArn:
Description: Secret ARN (not the secret value)
Value: !Ref DatabaseSecret
Export:
Name: !Sub "${AWS::StackName}-SecretArn"
# DO NOT export sensitive data
# Incorrect:
# SecretValue:
# Value: !GetAtt DatabaseSecret.SecretStringValidate: aws cloudformation list-exports --query "Exports[?Name=='<stack-name>-KMSKeyArn']"
Enable encryption for log groups:
Resources:
EncryptedLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/applications/${ApplicationName}"
RetentionInDays: 30
KmsKeyId: !Ref EncryptionKeyValidate: aws logs describe-log-groups --log-group-name-prefix <prefix> --query 'logGroups[0].kmsKeyId'
Resources:
# KMS Key with proper policy
AppKey:
Type: AWS::KMS::Key
Properties:
KeyPolicy:
Statement:
- Effect: Allow
Principal:
AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
Action: kms:*
Resource: "*"
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- kms:Decrypt
- kms:GenerateDataKey
Resource: "*"
# Secrets Manager with rotation
DbSecret:
Type: AWS::SecretsManager::Secret
Properties:
SecretString: !Sub '{"password":"${DbPassword}"}'
KmsKeyId: !Ref AppKey
RotationRules:
AutomaticallyAfterDays: 30Resources:
LambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: AccessPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action: s3:GetObject
Resource: !Sub "${Bucket.Arn}/*"For comprehensive examples with VPC security groups, ACM certificates, and complete encrypted infrastructure stacks, see examples.md.
For detailed constraints including cost considerations and quota management, see constraints.md.
For detailed implementation guidance, see:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.