Security Guidelines - reza899/AutoSDLC GitHub Wiki
#AutoSDLC #Security #Guidelines #BestPractices
← Back to Index | ← Monitoring Setup
This document provides comprehensive security guidelines for the AutoSDLC system, covering agent security, communication encryption, access control, vulnerability management, and compliance requirements. Security is paramount in an autonomous development system that has access to code repositories and development infrastructure.
graph TB
subgraph "Perimeter Security"
FW[Firewall]
WAF[Web Application Firewall]
DDoS[DDoS Protection]
end
subgraph "Network Security"
VPC[Virtual Private Cloud]
NSG[Network Security Groups]
TLS[TLS 1.3]
end
subgraph "Application Security"
AUTH[Authentication]
AUTHZ[Authorization]
RBAC[Role-Based Access]
MFA[Multi-Factor Auth]
end
subgraph "Agent Security"
ISO[Agent Isolation]
SEC[Secure Communication]
SIGN[Code Signing]
SAND[Sandboxing]
end
subgraph "Data Security"
ENC[Encryption at Rest]
TRANS[Encryption in Transit]
KEY[Key Management]
MASK[Data Masking]
end
FW --> VPC
VPC --> AUTH
AUTH --> ISO
ISO --> ENC
- Zero Trust Architecture: Never trust, always verify
- Least Privilege: Minimal permissions for all components
- Defense in Depth: Multiple layers of security
- Secure by Default: Security enabled out of the box
- Continuous Monitoring: Real-time threat detection
# k8s/security/agent-isolation.yaml
apiVersion: v1
kind: SecurityPolicy
metadata:
name: agent-isolation-policy
spec:
# Network isolation
networkPolicy:
podSelector:
matchLabels:
component: agent
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: autosdlc-prod
ports:
- protocol: TCP
port: 8081 # MCP server port
egress:
- to:
- namespaceSelector:
matchLabels:
name: autosdlc-prod
ports:
- protocol: TCP
port: 8080 # Main MCP server
- to: # GitHub API
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 443
# Process isolation
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
// security/AgentAuthentication.ts
import { JWK, JWS } from 'node-jose';
import crypto from 'crypto';
export class AgentAuthenticator {
private keyStore: JWK.KeyStore;
private trustedCAs: Set<string>;
async authenticateAgent(
agentId: string,
credential: AgentCredential
): Promise<AuthResult> {
// Verify agent certificate
const certValid = await this.verifyCertificate(credential.certificate);
if (!certValid) {
return { success: false, reason: 'Invalid certificate' };
}
// Verify agent signature
const signatureValid = await this.verifySignature(
credential.signature,
credential.certificate
);
if (!signatureValid) {
return { success: false, reason: 'Invalid signature' };
}
// Check agent authorization
const authorized = await this.checkAuthorization(agentId);
if (!authorized) {
return { success: false, reason: 'Agent not authorized' };
}
// Generate session token
const token = await this.generateSessionToken(agentId);
return {
success: true,
token,
expiresAt: new Date(Date.now() + 3600000) // 1 hour
};
}
private async verifyCertificate(cert: string): Promise<boolean> {
try {
const certificate = new crypto.X509Certificate(cert);
// Check if CA is trusted
const issuer = certificate.issuer;
if (!this.trustedCAs.has(issuer)) {
return false;
}
// Verify certificate chain
const chainValid = await this.verifyCertificateChain(certificate);
if (!chainValid) {
return false;
}
// Check expiration
const now = new Date();
if (certificate.validTo < now || certificate.validFrom > now) {
return false;
}
// Check revocation
const revoked = await this.checkRevocation(certificate);
if (revoked) {
return false;
}
return true;
} catch (error) {
console.error('Certificate verification failed:', error);
return false;
}
}
private async generateSessionToken(agentId: string): Promise<string> {
const key = await JWK.asKey({
kty: 'RSA',
use: 'sig',
key: this.signingKey
});
const payload = {
sub: agentId,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600,
aud: 'autosdlc',
iss: 'autosdlc-auth',
permissions: await this.getAgentPermissions(agentId)
};
const token = await JWS.createSign({ format: 'compact' }, key)
.update(JSON.stringify(payload))
.final();
return token.toString();
}
}
// security/SecureMCPChannel.ts
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
export class SecureMCPChannel {
private algorithm = 'aes-256-gcm';
private keyDerivation = 'pbkdf2';
async encryptMessage(
message: MCPMessage,
recipientKey: Buffer
): Promise<EncryptedMessage> {
// Generate random IV
const iv = randomBytes(16);
// Derive encryption key
const key = await this.deriveKey(recipientKey, iv);
// Create cipher
const cipher = createCipheriv(this.algorithm, key, iv);
// Encrypt message
const plaintext = JSON.stringify(message);
const encrypted = Buffer.concat([
cipher.update(plaintext, 'utf8'),
cipher.final()
]);
// Get auth tag
const authTag = cipher.getAuthTag();
return {
encrypted: encrypted.toString('base64'),
iv: iv.toString('base64'),
authTag: authTag.toString('base64'),
algorithm: this.algorithm,
timestamp: new Date().toISOString()
};
}
async decryptMessage(
encryptedMessage: EncryptedMessage,
privateKey: Buffer
): Promise<MCPMessage> {
// Decode components
const encrypted = Buffer.from(encryptedMessage.encrypted, 'base64');
const iv = Buffer.from(encryptedMessage.iv, 'base64');
const authTag = Buffer.from(encryptedMessage.authTag, 'base64');
// Derive decryption key
const key = await this.deriveKey(privateKey, iv);
// Create decipher
const decipher = createDecipheriv(this.algorithm, key, iv);
decipher.setAuthTag(authTag);
// Decrypt message
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final()
]);
// Parse and validate
const message = JSON.parse(decrypted.toString('utf8'));
// Verify timestamp (prevent replay attacks)
const messageTime = new Date(encryptedMessage.timestamp).getTime();
const now = Date.now();
if (now - messageTime > 300000) { // 5 minutes
throw new Error('Message too old - possible replay attack');
}
return message;
}
private async deriveKey(
masterKey: Buffer,
salt: Buffer
): Promise<Buffer> {
return new Promise((resolve, reject) => {
crypto.pbkdf2(masterKey, salt, 100000, 32, 'sha256', (err, key) => {
if (err) reject(err);
else resolve(key);
});
});
}
}
// security/AgentSandbox.ts
import { VM } from 'vm2';
import { Worker } from 'worker_threads';
export class AgentSandbox {
private resourceLimits = {
maxMemory: 512 * 1024 * 1024, // 512MB
maxCPUTime: 30000, // 30 seconds
maxFileSize: 10 * 1024 * 1024, // 10MB
allowedModules: [
'path',
'fs',
'crypto',
'util',
'@autosdlc/sdk'
]
};
async executeCode(
code: string,
context: ExecutionContext
): Promise<ExecutionResult> {
// Validate code
const validation = await this.validateCode(code);
if (!validation.safe) {
throw new SecurityError(`Code validation failed: ${validation.reason}`);
}
// Create isolated VM
const vm = new VM({
timeout: this.resourceLimits.maxCPUTime,
sandbox: {
console: this.createSafeConsole(),
require: this.createSafeRequire(),
process: this.createSafeProcess(),
__context: context
},
fixAsync: true,
eval: false,
wasm: false
});
try {
// Execute in worker thread for additional isolation
const result = await this.executeInWorker(vm, code);
// Validate output
const outputValidation = await this.validateOutput(result);
if (!outputValidation.safe) {
throw new SecurityError(`Output validation failed: ${outputValidation.reason}`);
}
return result;
} catch (error) {
// Log security event
await this.logSecurityEvent({
type: 'code_execution_failed',
agentId: context.agentId,
error: error.message,
code: this.sanitizeCode(code)
});
throw error;
}
}
private async validateCode(code: string): Promise<ValidationResult> {
// Check for dangerous patterns
const dangerousPatterns = [
/eval\s*\(/,
/Function\s*\(/,
/require\s*\(\s*['"`]child_process/,
/require\s*\(\s*['"`]cluster/,
/\.constructor\s*\(/,
/__proto__/,
/process\s*\.\s*exit/
];
for (const pattern of dangerousPatterns) {
if (pattern.test(code)) {
return {
safe: false,
reason: `Dangerous pattern detected: ${pattern}`
};
}
}
// Static analysis
const ast = await this.parseCode(code);
const staticAnalysis = await this.analyzeAST(ast);
return staticAnalysis;
}
private createSafeRequire() {
return (module: string) => {
if (!this.resourceLimits.allowedModules.includes(module)) {
throw new Error(`Module '${module}' is not allowed`);
}
// Return proxied module with limited capabilities
const originalModule = require(module);
return this.createModuleProxy(originalModule, module);
};
}
}
# security/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: autosdlc-admin
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: autosdlc-developer
rules:
- apiGroups: ["apps", "batch"]
resources: ["deployments", "jobs", "cronjobs"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log", "pods/exec"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: autosdlc-operator
rules:
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch", "delete"]
- apiGroups: ["monitoring.coreos.com"]
resources: ["prometheuses", "alertmanagers"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: autosdlc-viewer
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
// security/APIAuth.ts
import { OAuth2Server } from 'oauth2-server';
import { verify } from 'jsonwebtoken';
export class APIAuthenticator {
private oauth2Server: OAuth2Server;
private jwtSecret: string;
async authenticateRequest(
req: Request
): Promise<AuthenticationResult> {
// Check for API key
const apiKey = req.headers['x-api-key'];
if (apiKey) {
return await this.authenticateAPIKey(apiKey);
}
// Check for OAuth token
const authHeader = req.headers['authorization'];
if (authHeader?.startsWith('Bearer ')) {
const token = authHeader.substring(7);
return await this.authenticateOAuth(token);
}
// Check for JWT
const jwtToken = req.cookies?.['auth-token'];
if (jwtToken) {
return await this.authenticateJWT(jwtToken);
}
return {
authenticated: false,
reason: 'No authentication credentials provided'
};
}
async authorizeRequest(
auth: AuthenticationResult,
resource: string,
action: string
): Promise<AuthorizationResult> {
if (!auth.authenticated) {
return { authorized: false, reason: 'Not authenticated' };
}
// Get user permissions
const permissions = await this.getUserPermissions(auth.userId);
// Check resource access
const hasAccess = this.checkResourceAccess(
permissions,
resource,
action
);
if (!hasAccess) {
// Log authorization failure
await this.logAuthFailure({
userId: auth.userId,
resource,
action,
timestamp: new Date()
});
return {
authorized: false,
reason: 'Insufficient permissions'
};
}
return { authorized: true };
}
private async authenticateAPIKey(
apiKey: string
): Promise<AuthenticationResult> {
// Hash API key for comparison
const hashedKey = crypto
.createHash('sha256')
.update(apiKey)
.digest('hex');
// Look up key in database
const keyRecord = await this.db.apiKeys.findOne({
hashedKey,
active: true
});
if (!keyRecord) {
return {
authenticated: false,
reason: 'Invalid API key'
};
}
// Check rate limits
const rateLimitOk = await this.checkRateLimit(keyRecord.id);
if (!rateLimitOk) {
return {
authenticated: false,
reason: 'Rate limit exceeded'
};
}
// Update last used
await this.db.apiKeys.updateOne(
{ id: keyRecord.id },
{ $set: { lastUsed: new Date() } }
);
return {
authenticated: true,
userId: keyRecord.userId,
method: 'api_key'
};
}
}
// security/MFA.ts
import speakeasy from 'speakeasy';
import QRCode from 'qrcode';
export class MFAService {
async setupMFA(userId: string): Promise<MFASetup> {
// Generate secret
const secret = speakeasy.generateSecret({
length: 32,
name: `AutoSDLC (${userId})`,
issuer: 'AutoSDLC'
});
// Generate QR code
const qrCode = await QRCode.toDataURL(secret.otpauth_url);
// Store encrypted secret
const encryptedSecret = await this.encryptSecret(secret.base32);
await this.db.users.updateOne(
{ id: userId },
{
$set: {
mfa: {
secret: encryptedSecret,
enabled: false,
backupCodes: this.generateBackupCodes()
}
}
}
);
return {
qrCode,
secret: secret.base32,
backupCodes: await this.getBackupCodes(userId)
};
}
async verifyMFA(
userId: string,
token: string
): Promise<MFAVerification> {
// Get user's secret
const user = await this.db.users.findOne({ id: userId });
if (!user?.mfa?.secret) {
return { valid: false, reason: 'MFA not setup' };
}
// Decrypt secret
const secret = await this.decryptSecret(user.mfa.secret);
// Verify token
const verified = speakeasy.totp.verify({
secret,
encoding: 'base32',
token,
window: 2 // Allow 2 time steps for clock drift
});
if (verified) {
// Log successful MFA
await this.logMFAEvent({
userId,
type: 'verification_success',
timestamp: new Date()
});
return { valid: true };
}
// Check backup codes
const backupCodeValid = await this.verifyBackupCode(userId, token);
if (backupCodeValid) {
return { valid: true, usedBackupCode: true };
}
// Log failed MFA
await this.logMFAEvent({
userId,
type: 'verification_failed',
timestamp: new Date()
});
return { valid: false, reason: 'Invalid token' };
}
private generateBackupCodes(): string[] {
const codes = [];
for (let i = 0; i < 10; i++) {
codes.push(
crypto.randomBytes(4).toString('hex').toUpperCase()
);
}
return codes;
}
}
// security/DataEncryption.ts
import { createCipheriv, createDecipheriv } from 'crypto';
import { KMS } from 'aws-sdk';
export class DataEncryption {
private kms: KMS;
private algorithm = 'aes-256-gcm';
async encryptData(
data: any,
classification: DataClassification
): Promise<EncryptedData> {
// Serialize data
const plaintext = JSON.stringify(data);
// Get appropriate key based on classification
const dataKey = await this.getDataKey(classification);
// Generate IV
const iv = crypto.randomBytes(16);
// Create cipher
const cipher = createCipheriv(
this.algorithm,
dataKey.plaintext,
iv
);
// Encrypt
const encrypted = Buffer.concat([
cipher.update(plaintext, 'utf8'),
cipher.final()
]);
// Get auth tag
const authTag = cipher.getAuthTag();
return {
ciphertext: encrypted.toString('base64'),
iv: iv.toString('base64'),
authTag: authTag.toString('base64'),
keyId: dataKey.keyId,
classification,
algorithm: this.algorithm,
encryptedAt: new Date()
};
}
async decryptData(
encryptedData: EncryptedData
): Promise<any> {
// Get decryption key
const dataKey = await this.kms.decrypt({
CiphertextBlob: Buffer.from(encryptedData.keyId, 'base64')
}).promise();
// Create decipher
const decipher = createDecipheriv(
encryptedData.algorithm,
dataKey.Plaintext,
Buffer.from(encryptedData.iv, 'base64')
);
// Set auth tag
decipher.setAuthTag(
Buffer.from(encryptedData.authTag, 'base64')
);
// Decrypt
const decrypted = Buffer.concat([
decipher.update(
Buffer.from(encryptedData.ciphertext, 'base64')
),
decipher.final()
]);
// Parse and return
return JSON.parse(decrypted.toString('utf8'));
}
private async getDataKey(
classification: DataClassification
): Promise<DataKey> {
// Different keys for different data classifications
const keyAlias = this.getKeyAlias(classification);
// Generate data key
const response = await this.kms.generateDataKey({
KeyId: keyAlias,
KeySpec: 'AES_256'
}).promise();
return {
plaintext: response.Plaintext,
encrypted: response.CiphertextBlob,
keyId: response.KeyId
};
}
private getKeyAlias(classification: DataClassification): string {
const keyMap = {
[DataClassification.PUBLIC]: 'alias/autosdlc-public',
[DataClassification.INTERNAL]: 'alias/autosdlc-internal',
[DataClassification.CONFIDENTIAL]: 'alias/autosdlc-confidential',
[DataClassification.SECRET]: 'alias/autosdlc-secret'
};
return keyMap[classification];
}
}
# k8s/security/sealed-secrets.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: autosdlc-secrets
namespace: autosdlc-prod
spec:
encryptedData:
database-password: AgBvK5p...encrypted...
jwt-secret: AgCmN8x...encrypted...
github-token: AgDpQ9y...encrypted...
claude-api-key: AgErS0z...encrypted...
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: autosdlc-external-secrets
namespace: autosdlc-prod
spec:
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: autosdlc-secrets
creationPolicy: Owner
data:
- secretKey: database-password
remoteRef:
key: autosdlc/prod/database
property: password
- secretKey: jwt-secret
remoteRef:
key: autosdlc/prod/auth
property: jwt-secret
- secretKey: github-token
remoteRef:
key: autosdlc/prod/github
property: token
- secretKey: claude-api-key
remoteRef:
key: autosdlc/prod/claude
property: api-key
// security/KeyRotation.ts
export class KeyRotationService {
private rotationSchedule = {
api_keys: 90 * 24 * 60 * 60 * 1000, // 90 days
jwt_secrets: 30 * 24 * 60 * 60 * 1000, // 30 days
encryption_keys: 365 * 24 * 60 * 60 * 1000, // 1 year
certificates: 365 * 24 * 60 * 60 * 1000 // 1 year
};
async rotateKeys(): Promise<RotationResult> {
const results = [];
// Rotate API keys
const apiKeyRotation = await this.rotateAPIKeys();
results.push(apiKeyRotation);
// Rotate JWT secrets
const jwtRotation = await this.rotateJWTSecrets();
results.push(jwtRotation);
// Rotate encryption keys
const encKeyRotation = await this.rotateEncryptionKeys();
results.push(encKeyRotation);
// Rotate certificates
const certRotation = await this.rotateCertificates();
results.push(certRotation);
return {
timestamp: new Date(),
results,
success: results.every(r => r.success)
};
}
private async rotateAPIKeys(): Promise<KeyRotation> {
const keysToRotate = await this.getKeysNeedingRotation('api_keys');
const rotated = [];
for (const key of keysToRotate) {
try {
// Generate new key
const newKey = crypto.randomBytes(32).toString('hex');
// Create overlapping validity period
const overlap = 24 * 60 * 60 * 1000; // 24 hours
// Store new key
await this.db.apiKeys.insertOne({
id: uuid(),
userId: key.userId,
hashedKey: this.hashKey(newKey),
validFrom: new Date(),
validUntil: new Date(Date.now() + this.rotationSchedule.api_keys),
created: new Date()
});
// Schedule old key deactivation
await this.scheduleKeyDeactivation(key.id, overlap);
// Notify user
await this.notifyKeyRotation(key.userId, 'api_key', newKey);
rotated.push({
keyId: key.id,
userId: key.userId,
rotatedAt: new Date()
});
} catch (error) {
console.error(`Failed to rotate key ${key.id}:`, error);
}
}
return {
type: 'api_keys',
rotated: rotated.length,
success: true
};
}
}
# nginx/tls.conf
server {
listen 443 ssl http2;
server_name api.autosdlc.com;
# TLS 1.3 only
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# Strong ciphers only
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/ca-chain.pem;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;
# Certificate pinning
add_header Public-Key-Pins 'pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubDomains' always;
}
# k8s/security/network-policies.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: autosdlc-prod
spec:
podSelector: {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-ingress
namespace: autosdlc-prod
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agent-egress-policy
namespace: autosdlc-agents
spec:
podSelector:
matchLabels:
component: agent
policyTypes:
- Egress
egress:
# Allow DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# Allow MCP server
- to:
- namespaceSelector:
matchLabels:
name: autosdlc-prod
podSelector:
matchLabels:
app: mcp-server
ports:
- protocol: TCP
port: 8080
# Allow GitHub API
- to:
- ipBlock:
cidr: 140.82.112.0/20 # GitHub IP range
ports:
- protocol: TCP
port: 443
# .github/workflows/security-scan.yml
name: Security Scanning
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
jobs:
dependency-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Snyk vulnerability scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Run npm audit
run: |
npm audit --production
npm audit fix --force
- name: Run OWASP dependency check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'AutoSDLC'
path: '.'
format: 'HTML'
- name: Upload results
uses: actions/upload-artifact@v3
with:
name: dependency-scan-results
path: reports/
container-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Trivy container scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'autosdlc/agent:latest'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
- name: Upload Trivy results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
code-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
p/owasp-top-ten
// security/PatchManagement.ts
export class PatchManagementService {
async checkForPatches(): Promise<PatchReport> {
const vulnerabilities = await this.scanVulnerabilities();
const patches = await this.findAvailablePatches(vulnerabilities);
return {
critical: patches.filter(p => p.severity === 'critical'),
high: patches.filter(p => p.severity === 'high'),
medium: patches.filter(p => p.severity === 'medium'),
low: patches.filter(p => p.severity === 'low'),
summary: this.generatePatchSummary(patches)
};
}
async applyPatches(
patches: Patch[],
options: PatchOptions = {}
): Promise<PatchResult> {
const results = [];
// Sort by priority
const sortedPatches = this.prioritizePatches(patches);
for (const patch of sortedPatches) {
try {
// Test patch in staging
if (options.testFirst) {
const testResult = await this.testPatch(patch);
if (!testResult.success) {
results.push({
patch,
success: false,
reason: 'Failed testing',
details: testResult
});
continue;
}
}
// Apply patch
const applyResult = await this.applyPatch(patch);
// Verify application
const verified = await this.verifyPatch(patch);
results.push({
patch,
success: verified,
appliedAt: new Date()
});
// Log security event
await this.logSecurityEvent({
type: 'patch_applied',
patch: patch.id,
severity: patch.severity,
success: verified
});
} catch (error) {
results.push({
patch,
success: false,
error: error.message
});
}
}
return {
applied: results.filter(r => r.success).length,
failed: results.filter(r => !r.success).length,
results
};
}
}
// security/IncidentResponse.ts
export class IncidentResponseService {
private severityLevels = {
CRITICAL: { responseTime: 15, escalation: 'immediate' },
HIGH: { responseTime: 60, escalation: '1_hour' },
MEDIUM: { responseTime: 240, escalation: '4_hours' },
LOW: { responseTime: 1440, escalation: '24_hours' }
};
async handleSecurityIncident(
incident: SecurityIncident
): Promise<IncidentResponse> {
// 1. Detection & Analysis
const analysis = await this.analyzeIncident(incident);
// 2. Containment
const containment = await this.containIncident(incident, analysis);
// 3. Eradication
const eradication = await this.eradicateThreat(incident, analysis);
// 4. Recovery
const recovery = await this.recoverFromIncident(incident);
// 5. Post-Incident
const postIncident = await this.postIncidentAnalysis(incident);
// 6. Notification
await this.notifyStakeholders(incident, analysis);
return {
incidentId: incident.id,
severity: analysis.severity,
contained: containment.success,
eradicated: eradication.success,
recovered: recovery.success,
timeline: this.generateTimeline(incident),
recommendations: postIncident.recommendations
};
}
private async containIncident(
incident: SecurityIncident,
analysis: IncidentAnalysis
): Promise<ContainmentResult> {
const actions = [];
// Isolate affected components
if (analysis.affectedComponents.length > 0) {
for (const component of analysis.affectedComponents) {
const isolated = await this.isolateComponent(component);
actions.push({
action: 'isolate_component',
target: component,
success: isolated
});
}
}
// Block malicious IPs
if (analysis.maliciousIPs.length > 0) {
const blocked = await this.blockIPs(analysis.maliciousIPs);
actions.push({
action: 'block_ips',
targets: analysis.maliciousIPs,
success: blocked
});
}
// Revoke compromised credentials
if (analysis.compromisedCredentials.length > 0) {
for (const credential of analysis.compromisedCredentials) {
const revoked = await this.revokeCredential(credential);
actions.push({
action: 'revoke_credential',
target: credential,
success: revoked
});
}
}
return {
success: actions.every(a => a.success),
actions,
timestamp: new Date()
};
}
}
// security/SecurityMonitoring.ts
export class SecurityMonitor {
private detectionRules: DetectionRule[] = [
{
name: 'brute_force_detection',
pattern: /Failed login.*5 times.*60 seconds/,
severity: 'HIGH',
action: 'block_ip'
},
{
name: 'privilege_escalation',
pattern: /Unauthorized access.*admin.*resources/,
severity: 'CRITICAL',
action: 'isolate_account'
},
{
name: 'data_exfiltration',
pattern: /Large data transfer.*external.*destination/,
severity: 'CRITICAL',
action: 'block_transfer'
},
{
name: 'code_injection',
pattern: /Malicious pattern detected.*code execution/,
severity: 'CRITICAL',
action: 'isolate_agent'
}
];
async monitorSecurityEvents(): Promise<void> {
const eventStream = this.getEventStream();
for await (const event of eventStream) {
const threats = await this.detectThreats(event);
if (threats.length > 0) {
for (const threat of threats) {
await this.handleThreat(threat);
}
}
// Update security metrics
await this.updateSecurityMetrics(event);
}
}
private async detectThreats(
event: SecurityEvent
): Promise<Threat[]> {
const threats = [];
// Check against detection rules
for (const rule of this.detectionRules) {
if (rule.pattern.test(event.message)) {
threats.push({
rule: rule.name,
severity: rule.severity,
event: event,
detectedAt: new Date()
});
}
}
// ML-based anomaly detection
const anomaly = await this.detectAnomaly(event);
if (anomaly.score > 0.8) {
threats.push({
rule: 'ml_anomaly_detection',
severity: this.calculateAnomalySeverity(anomaly.score),
event: event,
anomaly: anomaly,
detectedAt: new Date()
});
}
return threats;
}
}
# compliance/framework.yaml
compliance_requirements:
gdpr:
data_protection:
- encryption_at_rest: required
- encryption_in_transit: required
- data_minimization: required
- right_to_erasure: implemented
privacy:
- consent_management: required
- data_portability: required
- breach_notification: 72_hours
soc2:
security:
- access_control: implemented
- encryption: aes_256
- monitoring: continuous
- incident_response: documented
availability:
- uptime_sla: 99.9%
- disaster_recovery: tested_quarterly
- backup_retention: 30_days
pci_dss:
cardholder_data:
- storage: not_applicable
- transmission: encrypted
- access_control: role_based
iso_27001:
information_security:
- risk_assessment: annual
- security_policy: documented
- access_control: implemented
- cryptography: strong
// security/AuditLogger.ts
export class AuditLogger {
private requiredFields = [
'timestamp',
'userId',
'action',
'resource',
'result',
'ipAddress',
'userAgent'
];
async logAuditEvent(event: AuditEvent): Promise<void> {
// Validate required fields
this.validateAuditEvent(event);
// Add metadata
const enrichedEvent = {
...event,
id: uuid(),
timestamp: new Date().toISOString(),
environment: process.env.NODE_ENV,
version: process.env.APP_VERSION
};
// Sign event for integrity
const signature = await this.signEvent(enrichedEvent);
enrichedEvent.signature = signature;
// Store in immutable log
await this.storeAuditLog(enrichedEvent);
// Forward to SIEM
await this.forwardToSIEM(enrichedEvent);
// Check for compliance violations
await this.checkCompliance(enrichedEvent);
}
private async signEvent(event: any): Promise<string> {
const canonical = this.canonicalizeEvent(event);
const signature = crypto
.createHmac('sha256', this.auditKey)
.update(canonical)
.digest('hex');
return signature;
}
async queryAuditLogs(
query: AuditQuery
): Promise<AuditLogResult> {
// Verify query authorization
const authorized = await this.authorizeQuery(query);
if (!authorized) {
throw new Error('Unauthorized audit query');
}
// Execute query with filters
const logs = await this.auditDb.query({
startTime: query.startTime,
endTime: query.endTime,
userId: query.userId,
action: query.action,
resource: query.resource
});
// Verify log integrity
const verified = await this.verifyLogIntegrity(logs);
return {
logs: verified.logs,
totalCount: verified.count,
integrityCheck: verified.integrity
};
}
}
# .github/security.yml
security:
code_review:
required_reviewers: 2
security_team_review: true
automated_checks:
- static_analysis
- dependency_scan
- secret_scan
branch_protection:
main:
required_checks:
- security_scan
- code_quality
- tests_pass
dismiss_stale_reviews: true
require_code_owner_reviews: true
secrets_management:
scanning:
- pre_commit_hooks
- ci_pipeline_scan
- periodic_repository_scan
rotation:
api_keys: 90_days
passwords: 60_days
certificates: 365_days
# Agent Security Guidelines
## 1. Authentication & Authorization
- Always verify agent identity before processing requests
- Use mutual TLS for agent-to-agent communication
- Implement least privilege access control
- Rotate agent credentials regularly
## 2. Code Execution
- Never execute untrusted code directly
- Use sandboxing for all code execution
- Validate all inputs and outputs
- Monitor resource usage
## 3. Data Handling
- Encrypt sensitive data at rest and in transit
- Implement data classification
- Follow data minimization principles
- Ensure secure data deletion
## 4. Communication Security
- Use encrypted channels for all communication
- Implement message integrity checks
- Prevent replay attacks with timestamps
- Monitor for anomalous communication patterns
## 5. Logging & Monitoring
- Log all security-relevant events
- Never log sensitive data
- Implement centralized logging
- Set up real-time alerts
## 6. Incident Response
- Have a clear incident response plan
- Practice incident response procedures
- Maintain incident documentation
- Learn from security incidents
#!/bin/bash
# security/deployment-checklist.sh
echo "=== AutoSDLC Security Deployment Checklist ==="
# 1. Secrets Management
echo -n "✓ All secrets in secure storage (not in code)... "
grep -r "password\|secret\|key" --include="*.yaml" --include="*.yml" . | grep -v "secretKeyRef" && echo "FAIL" || echo "PASS"
# 2. Network Policies
echo -n "✓ Network policies applied... "
kubectl get networkpolicies -A | grep -q "deny-all" && echo "PASS" || echo "FAIL"
# 3. RBAC Configuration
echo -n "✓ RBAC policies configured... "
kubectl get clusterroles | grep -q "autosdlc" && echo "PASS" || echo "FAIL"
# 4. TLS Certificates
echo -n "✓ TLS certificates valid... "
openssl s_client -connect api.autosdlc.com:443 -servername api.autosdlc.com < /dev/null 2>/dev/null | openssl x509 -noout -dates
# 5. Security Scanning
echo -n "✓ Container images scanned... "
trivy image autosdlc/agent:latest --severity HIGH,CRITICAL --quiet && echo "PASS" || echo "FAIL"
# 6. Audit Logging
echo -n "✓ Audit logging enabled... "
kubectl logs -n autosdlc-prod deployment/api-server | grep -q "audit" && echo "PASS" || echo "FAIL"
# 7. Monitoring
echo -n "✓ Security monitoring active... "
curl -s http://prometheus:9090/api/v1/query?query=up{job="security-monitor"} | jq -r '.data.result[0].value[1]' | grep -q "1" && echo "PASS" || echo "FAIL"
echo "=== Checklist Complete ==="
Tags: #AutoSDLC #Security #Guidelines #BestPractices #Compliance Last Updated: 2025-06-09 Next: Development Workflow →