Quick Takeaways
What you'll learn in this article
- 1
SQL injection that bypasses WAF rules by exploiting application-specific query patterns
- 2
Deserialization attacks where malicious objects are injected through service-to-service calls
- 3
Path traversal attempts that exploit file-handling logic
- 4
Server-side request forgery (SSRF) where the application is tricked into making requests to internal services
- 5
A container spawning an unexpected shell process
Keep reading for detailed implementation, code examples, and real-world results
Advanced Microservices Security in 2026: Zero Trust, API Protection, Supply Chain Integrity, and Runtime Defense
Microservices architecture has fundamentally reshaped how organizations build and deploy software. The decomposition of monolithic applications into dozens or hundreds of independently deployable services delivers remarkable agility, but it also creates an attack surface that traditional perimeter-based security was never designed to protect. Every service boundary is a potential entry point. Every API call is a trust decision. Every container image is a link in a supply chain that attackers are increasingly targeting.
By 2026, the security landscape for microservices has matured significantly. The industry has moved beyond the early debates about whether microservices introduce more risk than they eliminate. The answer is clear: microservices demand a fundamentally different security model, one built on cryptographic identity, continuous verification, automated compliance, and defense in depth at every layer of the stack.
This guide covers the advanced security techniques that engineering teams need to protect microservices in production today. We will go deep on workload identity, API security, supply chain integrity, runtime defense, secrets management, network microsegmentation, data protection, security testing, incident response, compliance automation, and DevSecOps integration. Each section provides actionable patterns and configurations you can apply to your own systems.
Microservices Security Incidents
68%
of organizations experienced at least one microservices-related security incident in 2025
Understanding the Microservices Attack Surface
Before diving into specific techniques, it is essential to understand why microservices present such a unique security challenge. A typical enterprise microservices deployment might have 200 to 500 services, each with its own API surface, dependencies, and data access patterns. The combinatorial complexity of securing all these interactions is staggering.
The core challenges break down into several categories:
Distributed trust boundaries. In a monolith, trust decisions happen at the application boundary. In microservices, every service-to-service call crosses a trust boundary that must be validated. A single payment service might receive requests from the order service, the refund service, the admin dashboard, and a batch processing job, each requiring different authorization levels.
Ephemeral infrastructure. Containers spin up and down constantly. IP addresses are meaningless as identity anchors. Services scale horizontally, creating new instances that need immediate access to secrets, certificates, and authorization policies. Traditional security models that rely on static IP-based allow lists simply cannot keep up.
Polyglot complexity. Microservices teams often use different languages, frameworks, and runtime environments. A security solution that works for Java Spring Boot services might not apply to Go services or Python FastAPI applications. Security must be enforced at a layer that transcends individual technology choices.
Supply chain depth. Each microservice brings its own dependency tree. A 200-service deployment might collectively depend on thousands of open-source packages, any one of which could be compromised. The attack surface extends far beyond your own code.
Data sprawl. Microservices encourage each service to own its own data store. Sensitive data may be replicated across multiple databases, caches, and message queues, each requiring its own encryption and access controls.
Zero Trust Architecture for Microservices
Zero trust has become the foundational security model for microservices, but implementing it effectively requires going far beyond simply enabling mTLS. True zero trust for microservices means establishing cryptographic workload identity, enforcing continuous verification at every interaction, and eliminating implicit trust from every layer of the architecture.
SPIFFE and SPIRE: Workload Identity at Scale
The Secure Production Identity Framework for Everyone (SPIFFE) has emerged as the standard for workload identity in microservices environments. SPIFFE defines a universal identity format, the SPIFFE ID, that looks like spiffe://trust-domain/workload-identifier. Unlike certificates tied to hostnames or IP addresses, SPIFFE IDs are tied to the workload itself, regardless of where it runs.
SPIRE (the SPIFFE Runtime Environment) is the production implementation that manages the lifecycle of these identities. In a typical deployment, a SPIRE server acts as the certificate authority, while SPIRE agents run on each node and attest workload identity through multiple signals: the Kubernetes service account, the container image hash, the namespace, and node-level attestation.
Here is a practical SPIRE registration entry that binds a SPIFFE ID to a specific Kubernetes workload:
# SPIRE registration entry for the payment service
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
name: payment-service
spec:
spiffeIDTemplate:
'spiffe://production.example.com/ns/{{ .PodMeta.Namespace }}/sa/{{
.PodSpec.ServiceAccountName }}'
podSelector:
matchLabels:
app: payment-service
namespaceSelector:
matchLabels:
environment: production
ttl: '1h'
dnsNameTemplates:
- 'payment-service.{{ .PodMeta.Namespace }}.svc.cluster.local'
The key advantage of SPIFFE/SPIRE over simpler certificate-based approaches is multi-signal attestation. SPIRE does not simply trust a Kubernetes service account. It combines multiple attestation signals, such as the node the pod is running on, the container image digest, and the Kubernetes namespace, to build a high-confidence identity assertion. An attacker who compromises a service account token but is running on an unattested node will be rejected.
Continuous Verification Beyond Authentication
Authentication answers the question "who are you?" but zero trust demands continuous verification that goes much further. Every request between microservices should be evaluated against the current security context, not just the initial identity.
Implementing continuous verification requires:
Request-level authorization. Every API call between services should include not just the caller's identity but the specific action being requested. The order service should be able to read payment status but not initiate refunds. These fine-grained permissions must be enforced at the receiving service, not just at a gateway.
Context-aware policies. Authorization decisions should incorporate runtime context: the time of day, the request rate, the geographic origin, and the current threat level. During an active incident, you might restrict cross-service calls to read-only operations.
Short-lived credentials. SPIRE issues SVIDs (SPIFFE Verifiable Identity Documents) with short TTLs, typically one hour or less. This limits the window of exploitation if credentials are compromised. The rotation happens automatically through the SPIRE agent, with zero downtime for the workload.
Behavioral verification. Beyond cryptographic identity, zero trust systems should monitor service behavior. A payment service that suddenly starts making calls to the user directory service at 100 times its normal rate should trigger an anomaly alert, even if its SPIFFE identity is valid.
Zero Trust Policy Enforcement Architecture
A production zero trust architecture for microservices typically involves several policy enforcement points:
External Traffic
|
[API Gateway]
(AuthN + Rate Limiting)
|
[Authorization Service]
(OPA / Cedar / Zanzibar)
|
+----------+----------+
| | |
[Service A] [Service B] [Service C]
(SPIRE Agent) (SPIRE Agent) (SPIRE Agent)
| | |
[Sidecar] [Sidecar] [Sidecar]
(mTLS + (mTLS + (mTLS +
AuthZ) AuthZ) AuthZ)
Each layer enforces different aspects of the zero trust model. The API gateway handles external authentication and coarse-grained rate limiting. The authorization service makes fine-grained access decisions based on policies. The SPIRE agents provide cryptographic workload identity. And the sidecars (or eBPF-based enforcement) handle mTLS termination and per-request authorization at the network level.
API Security for Microservices
APIs are the nervous system of microservices. Every service exposes an API, and every interaction between services flows through API calls. Securing these APIs requires a layered approach that addresses authentication, authorization, input validation, rate limiting, and protocol-level protections.
OWASP API Security Top 10: 2023 Edition in Practice
The OWASP API Security Top 10 (2023 update) provides a framework for understanding the most critical API vulnerabilities. In a microservices context, several of these risks are amplified.
Comparison
Top External API Risks
Top Internal API Risks
Broken Object Level Authorization (BOLA) is the number one API vulnerability for a reason. In microservices, BOLA manifests when Service A requests data from Service B for a specific resource ID, and Service B does not verify that Service A (or the original user) has permission to access that specific resource. Simply authenticating the calling service is not enough. The authorization check must verify access to the specific object being requested.
A common anti-pattern is a user service that exposes a GET /users/{id} endpoint. If the calling service passes any user ID and the user service returns data without verifying that the original request context has permission to access that specific user, you have a BOLA vulnerability. The fix requires propagating the original user's authorization context through the entire call chain, not just the service identity.
Unrestricted Resource Consumption becomes particularly dangerous in microservices because a single abusive request can cascade through multiple downstream services. A request to the search service might trigger calls to the catalog service, the pricing service, the inventory service, and the recommendation service. Without proper rate limiting at each hop, a single malicious request can consume resources across the entire system.
API Gateway Security Patterns
The API gateway serves as the first line of defense for microservices APIs. Modern gateway deployments implement several security layers:
Request validation. The gateway should validate all incoming requests against an OpenAPI specification before forwarding them to backend services. This catches malformed requests, unexpected parameters, and oversized payloads before they reach application code. Tools like the OpenAPI-based validation middleware in Kong, Envoy, or AWS API Gateway can automate this.
JWT validation and transformation. External requests typically carry OAuth 2.0 access tokens (JWTs). The gateway validates the token signature, checks expiration and audience claims, and can transform the token into an internal representation that downstream services consume. This prevents each microservice from needing to implement its own JWT validation logic.
Request signing for internal traffic. For service-to-service calls that bypass the gateway, implement request signing using HMAC or asymmetric signatures. Each request includes a signature computed from the request body, timestamp, and a shared or service-specific key. The receiving service verifies the signature before processing the request.
# Example: Kong API Gateway security plugin configuration
plugins:
- name: jwt
config:
uri_param_names:
- jwt
claims_to_verify:
- exp
- nbf
maximum_expiration: 3600
header_names:
- Authorization
- name: request-validator
config:
body_schema: auto # Validates against the OpenAPI spec
allowed_content_types:
- application/json
verbose_response: false # Don't leak schema details
- name: rate-limiting
config:
second: 50
minute: 1000
policy: redis
fault_tolerant: true
redis_host: redis.internal
hide_client_headers: true
- name: bot-detection
config:
deny:
- Scrapy
- curl
- HttpClient
OAuth 2.0 and OIDC for Service-to-Service Communication
For service-to-service authentication beyond mTLS, the OAuth 2.0 Client Credentials flow provides a well-understood pattern. Each microservice is registered as an OAuth client with its own client ID and secret. When Service A needs to call Service B, it first obtains an access token from the authorization server, then includes that token in the request to Service B.
The token should include scoped permissions that limit what the calling service can do. The payment service might receive a token with scopes orders:read payments:write, while the reporting service gets orders:read payments:read with no write access.
In 2026, the best practice is to combine mTLS (for transport-level identity) with OAuth tokens (for application-level authorization). mTLS ensures you are talking to the right service. The OAuth token ensures that service has permission to perform the specific action it is requesting.
Token exchange (RFC 8693) is another pattern that has gained traction. When an external user request flows through multiple microservices, each service can exchange the incoming token for a new token with reduced permissions appropriate to the downstream call. This implements the principle of least privilege across the call chain.
Supply Chain Security
The software supply chain has become one of the most targeted attack vectors for microservices. The SolarWinds breach, the Log4Shell vulnerability, and the xz-utils backdoor demonstrated that attackers are increasingly targeting the build pipeline and dependencies rather than the running application.
SBOM Generation and Management
A Software Bill of Materials (SBOM) provides a complete inventory of every component in your microservice images. In 2026, SBOM generation is no longer optional. Executive Order 14028 mandates SBOM for software sold to the US government, and major enterprises require SBOM from their vendors.
For microservices, SBOM generation must be automated as part of the CI/CD pipeline. Each container image should have an associated SBOM that lists every package, library, and binary included in the image, along with version numbers and known vulnerabilities.
# Generate SBOM using Syft for a container image syft packages registry.example.com/payment-service:v2.4.1 \ --output spdx-json=payment-service-sbom.spdx.json \ --output cyclonedx-json=payment-service-sbom.cdx.json # Attach SBOM to the container image using cosign cosign attach sbom \ --sbom payment-service-sbom.spdx.json \ --type spdx \ registry.example.com/payment-service:v2.4.1 # Scan the SBOM for known vulnerabilities grype sbom:payment-service-sbom.spdx.json \ --fail-on critical \ --output json > vulnerability-report.json
The critical insight for microservices is that SBOM management must be centralized. With hundreds of services, each with its own dependency tree, you need a central SBOM repository (such as Dependency-Track or GUAC) that aggregates SBOMs across all services. When a new CVE is published, you need to know within minutes which services are affected.
Sigstore and Cosign for Image Signing
Container image signing with Sigstore/cosign ensures that only images built by your trusted CI/CD pipeline can be deployed to production. Cosign signs container images using keyless signing (backed by OIDC identity from your CI provider) or traditional key-based signing.
# Keyless signing with GitHub Actions OIDC cosign sign \ --yes \ --rekor-url https://rekor.sigstore.dev \ registry.example.com/payment-service@sha256:abc123... # Verify the signature before deployment cosign verify \ --certificate-identity-regexp="https://github.com/myorg/.*" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ registry.example.com/payment-service@sha256:abc123...
In a microservices environment, image signing must be enforced at the admission control layer. A Kubernetes admission webhook (using Kyverno or Sigstore Policy Controller) should reject any pod that references an unsigned or improperly signed image. This prevents both accidental deployment of untested images and malicious injection of compromised images.
The SLSA Framework
Supply chain Levels for Software Artifacts (SLSA, pronounced "salsa") provides a maturity framework for supply chain security. SLSA defines four levels of increasing rigor:
Build Provenance
Automated build process generates provenance metadata documenting how the artifact was built. This is the baseline that most organizations should achieve immediately.
Hosted Build + Signed Provenance
Build runs on a hosted, managed build service. Provenance is signed by the build platform, preventing tampering after the build completes.
Hardened Build Platform
Build platform provides strong isolation between builds. Build definitions come from version control. Provenance is non-falsifiable by build platform administrators.
Two-Person Review + Hermetic Builds
All changes require two-person review. Builds are hermetic with no network access. Dependencies are locked and verified. This is the gold standard for critical infrastructure.
For microservices, achieving SLSA Level 3 across all services is the practical target for 2026. This means every service is built on a hardened CI/CD platform (GitHub Actions with reusable workflows, or Tekton Chains), provenance is automatically generated and signed, and admission controllers verify provenance before allowing deployment.
Dependency Scanning and Pinning
Dependency management is a particularly acute challenge for microservices because each service maintains its own dependency tree. A vulnerability in a widely-used library like a JSON parser or HTTP client can affect dozens of services simultaneously.
Best practices for dependency security in microservices:
Pin all dependencies to exact versions. Do not use version ranges. Every dependency should be locked to a specific version with a verified hash. This prevents supply chain attacks where a malicious version is published within an existing version range.
Use a private registry proxy. Route all dependency downloads through a private registry (Artifactory, Nexus, or GitHub Packages) that caches approved versions. This protects against dependency confusion attacks and provides a single point of audit.
Automate vulnerability scanning. Run dependency scanning on every pull request and on a daily schedule against all deployed services. Tools like Dependabot, Renovate, Snyk, and Trivy can automate this process.
Establish a vulnerability SLA. Define maximum remediation times based on severity: critical vulnerabilities patched within 24 hours, high within 7 days, medium within 30 days. Track compliance across all microservices in a central dashboard.
Runtime Security
Runtime security protects microservices while they are actually executing. Even with perfect supply chain security and network controls, a zero-day vulnerability in application code or a library can be exploited at runtime. Defense in depth requires detecting and preventing attacks as they happen.
Runtime Application Self-Protection (RASP)
RASP embeds security monitoring directly into the application runtime. Unlike network-based security tools that can only see traffic patterns, RASP has visibility into the application's internal state: function calls, data flow, database queries, and file system access.
For microservices running on the JVM, tools like Contrast Security and Sqreen (now part of Datadog) instrument the application bytecode to detect and block attacks in real time. For other runtimes, agent-based RASP solutions provide similar capabilities.
RASP is particularly effective against:
- SQL injection that bypasses WAF rules by exploiting application-specific query patterns
- Deserialization attacks where malicious objects are injected through service-to-service calls
- Path traversal attempts that exploit file-handling logic
- Server-side request forgery (SSRF) where the application is tricked into making requests to internal services
The tradeoff with RASP is performance overhead. Instrumentation adds latency to every protected operation. For latency-sensitive microservices, profile the overhead carefully and consider applying RASP selectively to services that handle sensitive data or external input.
Syscall Filtering with Seccomp
Seccomp (Secure Computing Mode) restricts the system calls that a container can make. Since most exploits ultimately need to execute system calls to achieve their objectives (spawning a shell, reading files, opening network connections), seccomp provides a powerful layer of defense.
The default Docker seccomp profile blocks approximately 44 of 300+ system calls, but a custom profile tailored to your specific microservice can be far more restrictive. A microservice that serves HTTP API requests typically needs fewer than 100 system calls. Blocking everything else eliminates entire classes of exploits.
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 1,
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": [
"read",
"write",
"close",
"fstat",
"mmap",
"mprotect",
"munmap",
"brk",
"rt_sigaction",
"rt_sigprocmask",
"ioctl",
"access",
"pipe",
"select",
"sched_yield",
"mremap",
"msync",
"madvise",
"shmget",
"shmat",
"shmctl",
"dup",
"dup2",
"pause",
"nanosleep",
"getpid",
"socket",
"connect",
"accept",
"sendto",
"recvfrom",
"bind",
"listen",
"getsockname",
"getpeername",
"setsockopt",
"getsockopt",
"clone",
"execve",
"exit",
"wait4",
"kill",
"fcntl",
"flock",
"fsync",
"fdatasync",
"getcwd",
"openat",
"mkdirat",
"newfstatat",
"unlinkat",
"readlinkat",
"fchmodat",
"futex",
"epoll_create1",
"epoll_ctl",
"epoll_wait",
"getrandom",
"membarrier"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
Generating custom seccomp profiles has become much easier with tools like oci-seccomp-bpf-hook and inspektor-gadget, which trace system calls during normal operation and generate a minimal profile. The workflow is: run the service under normal load, record the syscalls it makes, generate a profile allowing only those syscalls, then deploy the profile in audit mode before switching to enforce mode.
Falco for Runtime Threat Detection
Falco is the de facto standard for runtime security monitoring in containerized environments. It uses eBPF probes to monitor system calls and kernel events, comparing observed behavior against a set of rules to detect suspicious activity.
For microservices, Falco is particularly valuable because it can detect attacks that network-level monitoring cannot see:
- A container spawning an unexpected shell process
- A service writing to directories outside its expected paths
- A process opening a network connection to an unexpected external host
- A container reading sensitive files like /etc/shadow or Kubernetes service account tokens
- Privilege escalation attempts through setuid binaries
# Custom Falco rules for microservices
- rule: Unexpected outbound connection from payment service
desc:
Payment service should only connect to payment-gateway.internal and database
condition: >
container.name = "payment-service" and evt.type in (connect) and fd.net !=
"0.0.0.0/0" and not fd.sip in (payment-gateway.internal, postgres.internal)
output: >
Unexpected outbound connection from payment service (command=%proc.cmdline
connection=%fd.name container=%container.id
image=%container.image.repository)
priority: CRITICAL
tags: [network, microservices]
- rule: Sensitive file read in API service
desc: API services should not read SSH keys or cloud credentials
condition: >
container.image.repository contains "api-service" and evt.type in (open,
openat) and fd.name pmatch (/root/.ssh/*, /home/*/.aws/*,
/var/run/secrets/*)
output: >
Sensitive file read in API container (file=%fd.name command=%proc.cmdline
container=%container.id)
priority: WARNING
tags: [filesystem, microservices]
The power of Falco in a microservices context is that you can write service-specific rules. Each microservice has a well-defined purpose and expected behavior. The payment service should connect to the payment gateway and the database, nothing else. The image processing service should read from the upload bucket and write to the processed bucket, nothing else. Any deviation from these expected patterns is a potential security incident.
AppArmor and SELinux Profiles
Mandatory Access Control (MAC) systems like AppArmor and SELinux provide an additional layer of security by restricting what a process can do, regardless of its Unix permissions. For microservices running in containers, MAC profiles can restrict file access, network access, and capability usage.
AppArmor profiles are generally easier to write and deploy than SELinux policies. Here is a minimal AppArmor profile for a Node.js microservice:
#include <tunables/global>
profile microservice-api flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
#include <abstractions/nameservice>
# Allow reading application files
/app/** r,
/app/node_modules/** r,
# Allow writing to logs and tmp
/var/log/app/** w,
/tmp/** rw,
# Network access
network inet stream,
network inet6 stream,
# Deny everything else
deny /etc/shadow r,
deny /root/** rw,
deny /home/** rw,
deny /proc/*/mem r,
}
Secrets Management
Secrets management is one of the most critical aspects of microservices security. Every service needs access to database credentials, API keys, encryption keys, and certificates. How you store, distribute, rotate, and audit these secrets determines the blast radius of a compromise.
HashiCorp Vault for Microservices
HashiCorp Vault has become the standard for secrets management in microservices environments. Vault provides several capabilities that are essential for microservices:
Dynamic secrets. Instead of storing long-lived database credentials, Vault generates short-lived credentials on demand. When the payment service needs database access, it requests credentials from Vault, which creates a new database user with a TTL of one hour. When the TTL expires, Vault automatically revokes the credentials. This eliminates the risk of credential reuse and limits the window of exposure.
Transit encryption. Vault's transit secrets engine provides encryption-as-a-service. Microservices can encrypt sensitive data (credit card numbers, personal information) by sending it to Vault's transit endpoint, which returns ciphertext. The encryption keys never leave Vault, and the microservice never has direct access to them.
PKI management. Vault can serve as a private certificate authority, issuing TLS certificates to microservices with short TTLs. This integrates with SPIRE for workload identity or can be used independently for services that need standard X.509 certificates.
Authentication methods. Vault supports Kubernetes authentication, where a service's Kubernetes service account token is exchanged for a Vault token with specific policy bindings. This eliminates the bootstrapping problem of how to authenticate to the secrets manager.
# Vault policy for the payment service
path "secret/data/payment-service/*" {
capabilities = ["read"]
}
path "database/creds/payment-readonly" {
capabilities = ["read"]
}
path "database/creds/payment-readwrite" {
capabilities = ["read"]
}
path "transit/encrypt/payment-pii" {
capabilities = ["update"]
}
path "transit/decrypt/payment-pii" {
capabilities = ["update"]
}
# Explicitly deny access to other services' secrets
path "secret/data/user-service/*" {
capabilities = ["deny"]
}
path "secret/data/admin-service/*" {
capabilities = ["deny"]
}
External Secrets Operator
The External Secrets Operator (ESO) bridges the gap between external secrets managers (Vault, AWS Secrets Manager, Google Secret Manager, Azure Key Vault) and Kubernetes secrets. ESO watches for ExternalSecret custom resources and synchronizes secrets from the external provider into Kubernetes secrets that pods can consume.
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: payment-service-secrets
namespace: payment
spec:
refreshInterval: 5m
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: payment-service-secrets
creationPolicy: Owner
deletionPolicy: Retain
template:
type: Opaque
data:
DATABASE_URL:
'postgresql://{{ .db_user }}:{{ .db_pass
}}@postgres.internal:5432/payments'
STRIPE_API_KEY: '{{ .stripe_key }}'
data:
- secretKey: db_user
remoteRef:
key: secret/data/payment-service/database
property: username
- secretKey: db_pass
remoteRef:
key: secret/data/payment-service/database
property: password
- secretKey: stripe_key
remoteRef:
key: secret/data/payment-service/stripe
property: api_key
ESO's refreshInterval is critical for microservices. Setting it to 5 minutes means that when a secret is rotated in Vault, the Kubernetes secret is updated within 5 minutes. For dynamic database credentials with short TTLs, you may need an even shorter interval.
Secret Rotation Patterns
Automated secret rotation is non-negotiable for microservices. With dozens or hundreds of services, manual rotation is impossible, and long-lived credentials are a ticking time bomb.
The rotation pattern depends on the type of secret:
Database credentials should use Vault's dynamic secrets engine. No rotation is needed because credentials are generated on demand with short TTLs.
API keys for external services (Stripe, Twilio, SendGrid) require a dual-key rotation pattern. Generate a new key while the old key is still active, deploy the new key to all consuming services, verify the new key is in use, then revoke the old key. ESO handles the distribution, but the rotation logic typically requires a custom controller or scheduled job.
Encryption keys should be rotated using envelope encryption. The data encryption key (DEK) is wrapped by a key encryption key (KEK). Rotating the KEK does not require re-encrypting all data. The old KEK is kept available for decryption, but all new encryptions use the new KEK. Over time, background processes re-encrypt data with the new KEK.
TLS certificates should have short lifetimes (24 hours or less) and be automatically rotated. SPIRE handles this for workload identity. For certificates used by external-facing services, cert-manager with ACME (Let's Encrypt) automates rotation.
Network Security Beyond mTLS
While mTLS provides encryption and mutual authentication for service-to-service traffic, it is only one piece of the network security puzzle. A comprehensive network security strategy for microservices includes network policies, DNS-based security, egress control, and microsegmentation.
Network Policies
Kubernetes network policies provide namespace and pod-level network segmentation. The default Kubernetes network model allows all pods to communicate with all other pods, which is far too permissive for production microservices.
The starting point for network security is a default-deny policy in every namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: payment
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Then, explicitly allow only the communication paths that each service requires:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: payment-service-policy
namespace: payment
spec:
podSelector:
matchLabels:
app: payment-service
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: order
podSelector:
matchLabels:
app: order-service
- namespaceSelector:
matchLabels:
name: refund
podSelector:
matchLabels:
app: refund-service
ports:
- protocol: TCP
port: 8443
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to: # DNS resolution
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
DNS-Based Security
DNS is a frequently overlooked attack vector in microservices. DNS spoofing, DNS tunneling, and DNS-based data exfiltration can bypass network policies and mTLS. Securing DNS in a microservices environment requires:
CoreDNS with response policy zones (RPZ). Configure CoreDNS to block known malicious domains and prevent DNS resolution to unauthorized external services. Services that should only communicate internally should not be able to resolve external domain names.
DNS query logging and anomaly detection. Monitor DNS queries for suspicious patterns: high volumes of NXDOMAIN responses (potential domain generation algorithm), queries to uncommon TLDs, or unusually long subdomains (potential DNS tunneling).
mTLS for DNS. Enable DNS-over-TLS between pods and the CoreDNS service to prevent DNS spoofing within the cluster.
Egress Control
Controlling outbound traffic from microservices is as important as controlling inbound traffic. A compromised service that can reach any external host can exfiltrate data, download additional payloads, or establish command-and-control channels.
Egress gateways route all outbound traffic through a controlled proxy that enforces allow lists. Only approved external destinations (payment processor APIs, email delivery services, cloud provider APIs) are permitted. All other outbound traffic is blocked and logged.
Network policies for egress restrict which services can make external calls at all. Internal-only services (like a caching layer or a data transformation pipeline) should have no egress to external networks.
TLS inspection for egress (where legally and ethically permitted) can detect data exfiltration attempts hidden in encrypted outbound traffic. This is controversial and must be balanced against privacy considerations, but it is common in regulated industries.
Data Security in Microservices
Microservices architectures distribute data across multiple databases, caches, message queues, and event streams. Each data store requires its own security controls, and sensitive data must be protected as it flows between services.
Encryption at Rest and in Transit
In transit: mTLS provides encryption for synchronous service-to-service calls. For asynchronous communication through message queues (Kafka, RabbitMQ, NATS), enable TLS on the broker and authenticate producers and consumers with client certificates or SASL.
At rest: Every database and persistent store must use encryption at rest. For managed databases (RDS, Cloud SQL, Azure SQL), enable the built-in encryption. For self-managed databases, use LUKS or dm-crypt for volume encryption and database-native TDE (Transparent Data Encryption) where available.
Application-level encryption adds a layer beyond infrastructure encryption. Even if an attacker gains access to the database, they cannot read data encrypted with application-managed keys. This is essential for PII, payment data, and healthcare records.
Field-Level Encryption
Not all data within a microservice requires the same level of protection. Field-level encryption allows you to encrypt specific sensitive fields while leaving non-sensitive fields in plaintext for querying and indexing.
For example, a customer record might store the name and email in plaintext for search functionality, but encrypt the Social Security number, date of birth, and payment information at the field level. This approach, sometimes called "tokenization" when implemented with format-preserving encryption, allows the service to function normally while protecting the most sensitive data.
MongoDB supports Client-Side Field Level Encryption (CSFLE) natively, and similar patterns can be implemented in other databases using application-level encryption with Vault's transit engine.
// Example: Field-level encryption with Vault transit
const encryptedSSN = await vault.write('transit/encrypt/customer-pii', {
plaintext: Buffer.from(customer.ssn).toString('base64'),
})
const customerRecord = {
name: customer.name,
email: customer.email,
ssn: encryptedSSN.data.ciphertext, // vault:v1:encrypted...
dateOfBirth: encryptedDOB.data.ciphertext,
address: customer.address, // plaintext for shipping
createdAt: new Date(),
}
Data Classification
Microservices should implement a data classification framework that categorizes all data elements:
| Name | Value |
|---|---|
| Public (non-sensitive) | 35 |
| Internal (business data) | 30 |
| Confidential (PII/financial) | 25 |
| Restricted (regulated/secret) | 10 |
Each classification level maps to specific security controls:
- Public: No special handling required. Can be cached freely and logged without redaction.
- Internal: Standard encryption in transit and at rest. Access logging required. No external exposure without review.
- Confidential: Field-level encryption. Strict access controls with audit trails. Data masking in non-production environments. Retention limits enforced.
- Restricted: Application-level encryption with customer-managed keys. Zero-knowledge storage where feasible. Real-time access alerts. Formal access review processes.
Security Testing for Microservices
Testing security in a microservices architecture requires approaches that account for the distributed nature of the system. Traditional security testing tools designed for monolithic applications may miss vulnerabilities that only manifest in service interactions.
SAST, DAST, and IAST
Static Application Security Testing (SAST) analyzes source code for vulnerabilities without executing it. For microservices, SAST should run on every pull request as part of the CI pipeline. Tools like Semgrep, SonarQube, and CodeQL can identify common vulnerabilities like SQL injection, XSS, and hardcoded secrets.
The challenge with SAST in microservices is false positive management. With hundreds of services, even a 5% false positive rate generates an overwhelming volume of findings. Tuning SAST rules to your specific technology stack and creating custom rules for your internal patterns is essential.
Dynamic Application Security Testing (DAST) tests running services by sending malicious requests and observing responses. For microservices, DAST should target both external-facing APIs and internal service-to-service APIs. Tools like OWASP ZAP, Burp Suite, and Nuclei can automate DAST scans.
Interactive Application Security Testing (IAST) combines SAST and DAST by instrumenting the application at runtime and correlating observed behavior with source code locations. IAST has lower false positive rates than SAST because it verifies vulnerabilities through actual execution.
API Fuzzing
Fuzzing generates randomized, malformed inputs to discover unexpected behavior and crashes. For microservices APIs, fuzzing is particularly effective at finding:
- Input validation bypasses
- Parsing vulnerabilities in JSON, XML, or protobuf handling
- Integer overflow in numeric fields
- Denial-of-service through oversized payloads or deeply nested structures
- Authentication bypass through malformed tokens
API fuzzing tools like RESTler, Schemathesis, and API Fuzzer generate test cases from OpenAPI specifications and systematically explore the API surface. Running fuzzing as part of the CI/CD pipeline catches vulnerabilities before they reach production.
Chaos Security Testing
Chaos engineering principles applied to security, sometimes called "chaos security" or "security chaos engineering," deliberately inject security failures to test the system's resilience. This includes:
- Revoking a service's credentials to verify that the service handles authentication failures gracefully and does not fail open
- Injecting expired certificates to verify that certificate rotation works correctly
- Simulating a compromised service to verify that blast radius containment mechanisms (network policies, circuit breakers) function correctly
- Triggering rate limit violations to verify that rate limiting does not create denial-of-service for legitimate traffic
- Injecting malicious payloads in service-to-service messages to verify input validation at every service boundary
Tools like Gremlin, Chaos Mesh, and Litmus can automate these experiments. The key is to run chaos security tests regularly in staging environments and, when confidence is high enough, in production with appropriate safeguards.
Incident Response in Microservices
When a security incident occurs in a microservices environment, the distributed nature of the system makes incident response both more challenging and more nuanced than in monolithic architectures. Containment, investigation, and recovery all require approaches designed for distributed systems.
Blast Radius Containment
The primary advantage of microservices for incident response is the ability to contain the blast radius of a compromise. If the image processing service is compromised, the attacker should not be able to pivot to the payment service or the user database.
Effective blast radius containment requires:
Network segmentation that is already in place before the incident. Network policies should restrict the compromised service to only its approved communication paths. If you have to create network policies during an incident, you have already lost.
Service isolation mechanisms that can quickly quarantine a compromised service. This includes the ability to:
- Remove a service from the load balancer without shutting it down (preserving forensic evidence)
- Revoke the service's SPIFFE identity to prevent it from authenticating to other services
- Block the service's egress traffic to prevent data exfiltration
- Scale the service to zero replicas as a last resort
Automated containment playbooks that execute these isolation steps within seconds of detection. Manual containment is too slow in a microservices environment where lateral movement can happen in milliseconds.
Circuit Breakers as Security Controls
Circuit breakers, traditionally used for reliability, also serve as security controls in microservices. When a service exhibits suspicious behavior (unusual error rates, unexpected latency patterns, anomalous request volumes), circuit breakers can automatically cut off traffic to and from that service.
Security-aware circuit breakers extend the standard circuit breaker pattern with:
- Anomaly-based tripping: The circuit opens not just on error rates but on security-relevant signals like authentication failures, authorization violations, or unexpected payload sizes
- Cascading isolation: When one circuit breaks for security reasons, upstream services can preemptively reduce their trust in the affected service
- Security observability integration: Circuit breaker state changes trigger alerts in the security monitoring system, creating a correlation between reliability events and security events
Security Observability
Observability in microservices, the combination of logs, metrics, and traces, is the foundation of security monitoring and incident investigation. For security purposes, observability must capture:
Distributed traces with security context. Every trace should include the authenticated identity of the caller, the authorization decision, and any security-relevant metadata. When investigating an incident, you need to follow the complete request path through all services involved.
Structured security logs. Every authentication decision, authorization check, and security-relevant event should be logged in a structured format that can be queried and correlated. Use a common schema across all services, something like:
{
"timestamp": "2026-03-01T14:23:45.123Z",
"service": "payment-service",
"event_type": "authorization_decision",
"caller_identity": "spiffe://prod/ns/orders/sa/order-service",
"action": "CreatePayment",
"resource": "payment:order-12345",
"decision": "ALLOW",
"policy_version": "v2.4.1",
"latency_ms": 2,
"trace_id": "abc123def456"
}
Security metrics. Track authentication failure rates, authorization denial rates, certificate expiration timelines, secret access patterns, and network policy violations as metrics. Set alerts on anomalous changes in these metrics.
Compliance Automation
In regulated industries, demonstrating compliance with standards like [SOC 2](https://glossary.crashbytes.com/soc), PCI DSS, HIPAA, and FedRAMP is as important as actually being secure. For microservices, compliance must be automated because manual audit processes cannot keep up with the pace of change.
Policy-as-Code with OPA and Kyverno
Policy-as-code translates compliance requirements into machine-enforceable policies that are version-controlled, tested, and automatically applied.
Open Policy Agent (OPA) with its Rego policy language is the most widely adopted policy engine for microservices. OPA can enforce policies at the API gateway (authorization decisions), the Kubernetes admission controller (deployment policies), and within individual services (data filtering policies).
Kyverno takes a Kubernetes-native approach, defining policies as Kubernetes custom resources written in YAML rather than a specialized policy language. This makes Kyverno more accessible to Kubernetes operators who may not want to learn Rego.
For compliance automation, policies should map directly to compliance controls:
# Kyverno policy implementing PCI DSS Requirement 2.2.1
# System components should have only necessary services and protocols enabled
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: pci-dss-2-2-1-restrict-capabilities
annotations:
compliance.framework: PCI-DSS-v4.0
compliance.control: '2.2.1'
compliance.description: 'Only necessary services, protocols enabled'
spec:
validationFailureAction: Enforce
background: true
rules:
- name: drop-all-capabilities
match:
any:
- resources:
kinds:
- Pod
namespaces:
- 'payment*'
- 'cardholder*'
validate:
message: >-
PCI DSS 2.2.1: Containers in PCI scope must drop all capabilities and
only add back specific required capabilities.
pattern:
spec:
containers:
- securityContext:
capabilities:
drop:
- ALL
Continuous Compliance
Continuous compliance means that every change is evaluated against compliance policies before it is deployed, and the compliance posture of the running system is continuously monitored.
| approach | auditTime | complianceDrift |
|---|---|---|
| Manual Audits | 120 | 45 |
| Periodic Scanning | 40 | 25 |
| CI/CD Policy Gates | 8 | 10 |
| Continuous Compliance | 2 | 3 |
The continuous compliance architecture for microservices includes:
Pre-deployment gates. Every pull request is checked against compliance policies before merging. Every container image is scanned for vulnerabilities and compliance violations before deployment. Every Kubernetes manifest is validated against admission policies before the pod is scheduled.
Runtime monitoring. The running system is continuously scanned for drift from compliance baselines. If a service's configuration changes in a way that violates compliance (for example, a network policy is accidentally deleted), an alert fires and remediation begins automatically.
Audit trail generation. Every compliance-relevant event (deployment, configuration change, access grant, policy exception) is recorded in an immutable audit log. This log serves as evidence during compliance audits and must be protected against tampering.
Evidence collection. Compliance audits require evidence that controls are operating effectively. Automated evidence collection gathers screenshots, configuration snapshots, scan results, and policy evaluation logs, and organizes them by compliance control. This can reduce audit preparation time from weeks to hours.
Audit Trails for Microservices
In a microservices environment, audit trails must span multiple services and correlate events across the distributed system. A single user action (like processing a payment) might touch five or six services, and the audit trail must capture the complete chain.
Implementing audit trails in microservices:
- Correlation IDs propagated through all service calls allow reconstruction of the complete event chain
- Immutable audit logs stored in append-only storage (like Amazon QLDB or a write-once S3 bucket with Object Lock) prevent tampering
- Structured audit events with consistent schemas across all services enable querying and analysis
- Retention policies automated per compliance framework (PCI DSS requires one year, HIPAA requires six years, SOX requires seven years)
DevSecOps Pipeline Integration
Security must be integrated into the development and deployment pipeline, not bolted on as an afterthought. For microservices, this means embedding security checks at every stage of the pipeline, from code commit to production deployment.
Shift-Left Security
Shifting security left means moving security testing earlier in the development lifecycle, ideally to the developer's local environment. The goal is to catch vulnerabilities before they enter the codebase, not after they are deployed to production.
Practical shift-left techniques for microservices:
Pre-commit hooks that scan for hardcoded secrets (using tools like detect-secrets or gitleaks), check dependency versions against known vulnerabilities, and validate configuration files against security schemas.
IDE integrations that provide real-time security feedback as developers write code. Semgrep, Snyk, and SonarLint all offer IDE plugins that highlight security issues inline.
Local policy evaluation that lets developers test their Kubernetes manifests against admission policies before pushing. kyverno apply and conftest test can run policies locally against manifest files.
Security Gates in CI/CD
The CI/CD pipeline should include explicit security gates that prevent insecure artifacts from progressing:
Code Commit
|
v
[Pre-commit: Secret scanning, linting]
|
v
[Build: SAST scanning, dependency check]
|
v
[Container Build: Image scanning, SBOM generation]
|
v
[Image Signing: Cosign signing, provenance attestation]
|
v
[Staging Deploy: DAST scanning, integration security tests]
|
v
[Production Gate: Policy evaluation, vulnerability threshold check]
|
v
[Production Deploy: Admission control, runtime monitoring activated]
|
v
[Post-Deploy: Continuous scanning, compliance monitoring]
Each gate has defined pass/fail criteria:
- Build gate: No critical or high SAST findings. No critical dependency vulnerabilities. All secrets scanning passes.
- Container gate: No critical image vulnerabilities. SBOM generated and attached. Image signed with valid provenance.
- Staging gate: No critical DAST findings. API fuzzing passes. Integration security tests pass.
- Production gate: All compliance policies pass. Vulnerability count is within threshold. Change has required approvals.
Automated Vulnerability Management
With hundreds of microservices, vulnerability management must be fully automated. The vulnerability management lifecycle for microservices includes:
Discovery: Automated scanning identifies vulnerabilities in source code (SAST), dependencies (SCA), container images (image scanning), running services (DAST), and infrastructure (cloud security posture management).
Triage: Automated triage reduces noise by deduplicating findings, correlating across scanners, and applying context (is the vulnerable code reachable? is the vulnerable library actually used?). Tools like DefectDojo and Nucleus aggregate findings from multiple scanners and apply risk-based prioritization.
Remediation: Automated remediation generates pull requests for dependency updates (Dependabot, Renovate), applies security patches to base images, and updates infrastructure configurations. For vulnerabilities that require code changes, automated triage assigns findings to the responsible team based on service ownership.
Verification: After remediation, automated rescanning verifies that the vulnerability is actually fixed. The vulnerability is not closed until the fix is deployed to production and verified.
Reporting: Dashboards track vulnerability counts by service, severity, age, and SLA compliance. Engineering leadership can see which teams are meeting remediation SLAs and which services carry the most risk.
Real-World Breach Analysis
Studying real-world security incidents provides invaluable lessons for securing microservices. Several high-profile breaches have highlighted specific weaknesses in microservices architectures.
Lessons from Capital One (2019)
The Capital One breach exposed over 100 million customer records through a Server-Side Request Forgery (SSRF) vulnerability in a misconfigured WAF. The attacker exploited the SSRF to access the EC2 instance metadata service, obtained IAM role credentials, and used those credentials to access S3 buckets containing sensitive data.
For microservices, the lessons are:
- Instance metadata lockdown. Require IMDSv2 (which uses session tokens) to prevent SSRF-based metadata access. Better yet, use workload identity (SPIFFE/SPIRE or cloud-native alternatives like EKS Pod Identity) instead of instance-level IAM roles.
- Least-privilege IAM. Each microservice should have its own IAM role with minimal permissions. A WAF processing service should never have access to S3 buckets containing customer data.
- Egress filtering. The compromised service should not have been able to reach the metadata service at all if proper network policies were in place.
Lessons from the Codecov Supply Chain Attack (2021)
The Codecov attack compromised a bash uploader script that thousands of organizations used in their CI/CD pipelines. The attacker modified the script to exfiltrate environment variables, including secrets and tokens, from CI environments.
For microservices, the lessons are:
- Pin all CI/CD dependencies. Do not use latest tags or unversioned scripts from external sources. Pin to specific versions and verify checksums.
- Isolate CI/CD secrets. Use short-lived, scoped credentials in CI/CD pipelines. Implement OIDC-based authentication (like GitHub Actions OIDC with Vault) instead of long-lived tokens.
- Monitor CI/CD pipeline behavior. Alert on unexpected network connections, new environment variable access patterns, or changes to build scripts.
Lessons from the Log4Shell Vulnerability (2021)
Log4Shell (CVE-2021-44228) demonstrated how a single vulnerability in a ubiquitous library could affect virtually every Java-based microservice. The vulnerability allowed remote code execution through crafted log messages, and the dependency chain made it difficult to identify all affected services.
For microservices, the lessons are:
- SBOM is essential. Organizations with comprehensive SBOMs identified affected services within hours. Those without SBOMs spent days or weeks hunting for the vulnerability.
- Defense in depth works. Services with egress filtering, seccomp profiles, and least-privilege IAM roles were not exploitable even when they contained the vulnerable library, because the exploit payload could not reach external LDAP servers or download additional code.
- Automated patching at scale. Organizations that could automatically rebuild and redeploy all affected services recovered fastest. Those relying on manual patching per service took weeks.
Lessons from the xz-utils Backdoor (2024)
The xz-utils supply chain compromise was one of the most sophisticated attacks ever detected. A long-term contributor to the xz compression library inserted a backdoor that would have enabled remote code execution on SSH servers using systemd. The attack was discovered by accident when a developer noticed unusual latency in SSH connections.
For microservices, the lessons are profound:
- Trust but verify contributors. Even trusted, long-term contributors can be compromised or malicious. Code review must focus on understanding what the code does, not just who wrote it.
- Reproducible builds matter. The xz-utils backdoor was injected through the build process, not through the source code visible in the repository. Reproducible, hermetic builds (SLSA Level 4) would have detected the discrepancy.
- Monitor build artifacts, not just source code. Compare binary artifacts against expected outputs. Unexpected changes in binary size, linked libraries, or behavior should trigger investigation.
Bringing It All Together: A Defense-in-Depth Security Architecture
Effective microservices security is not about any single technique. It is about layering multiple controls so that the failure of any one control does not result in a breach. Here is the complete defense-in-depth architecture:
Layer 1: Supply chain. SBOM generation, image signing with Sigstore, dependency scanning, SLSA Level 3 provenance, private registry proxies.
Layer 2: Build pipeline. SAST, secret scanning, container image scanning, policy-as-code gates, automated vulnerability management.
Layer 3: Deployment. Admission control (image signature verification, policy evaluation), least-privilege RBAC, namespace isolation.
Layer 4: Network. mTLS with SPIFFE/SPIRE workload identity, network policies (default deny), egress filtering, DNS security.
Layer 5: Runtime. Seccomp profiles, AppArmor/SELinux, RASP, Falco runtime monitoring, anomaly detection.
Layer 6: Application. API gateway security, OAuth 2.0/OIDC, input validation, field-level encryption, secret management with Vault.
Layer 7: Data. Encryption at rest and in transit, data classification, tokenization, audit trails, retention policies.
Layer 8: Response. Automated containment playbooks, circuit breakers, security observability, incident response procedures.
No single layer is sufficient. An attacker who bypasses supply chain controls (by exploiting a zero-day in a dependency) should be stopped by runtime controls (seccomp blocking unexpected syscalls). An attacker who bypasses network controls (through a compromised service) should be stopped by application controls (authorization policies rejecting unauthorized actions). Each layer reduces the probability of a successful attack, and the combined probability approaches zero.
Looking Forward: Emerging Trends
Several trends are shaping the future of microservices security in 2026 and beyond:
eBPF-native security. eBPF is moving security enforcement from sidecars and agents into the kernel itself. Projects like Tetragon and Cilium are enabling network policies, runtime security, and observability without the performance overhead of userspace proxies. This is particularly important for latency-sensitive microservices.
AI-assisted security operations. Large language models are being applied to security operations: automated analysis of security alerts, natural language policy authoring, and AI-assisted incident investigation. While not a replacement for human judgment, AI is helping security teams manage the volume of signals from large microservices deployments.
Confidential computing. Hardware-based trusted execution environments (Intel SGX, AMD SEV, ARM CCA) are becoming practical for microservices. Confidential computing protects data even from the infrastructure operator, enabling zero-trust computing where the platform itself is untrusted.
WebAssembly (Wasm) sandboxing. Wasm provides a lightweight sandboxing model that is more fine-grained than containers. Each microservice (or even each function within a service) can run in its own Wasm sandbox with precisely defined capabilities. Projects like Wasmtime and WasmCloud are making this practical for production workloads.
Software-defined perimeters. Moving beyond traditional VPNs and network boundaries, software-defined perimeters (SDPs) create on-demand, identity-based network connections between services. Each connection is individually authenticated and authorized, with no exposed ports or discoverable services.
Conclusion
Microservices security in 2026 is a mature discipline with clear best practices and proven tools. The foundations are non-negotiable: cryptographic workload identity with SPIFFE/SPIRE, comprehensive API security, supply chain integrity with SBOM and Sigstore, runtime protection with seccomp and Falco, secrets management with Vault, network microsegmentation, and automated compliance.
The key insight is that microservices security is not a feature you add. It is an architectural property that must be designed in from the beginning. Every service boundary is a security boundary. Every API is an attack surface. Every dependency is a trust decision. Every data store is a potential breach target.
Organizations that treat security as a first-class architectural concern, embedding it into their development pipelines, deployment processes, and operational procedures, will thrive in the microservices era. Those that treat security as an afterthought will find themselves responding to incidents that were entirely preventable.
Start with workload identity and network segmentation. Add supply chain security and secrets management. Layer on runtime protection and compliance automation. Test everything continuously with security chaos experiments. And always, always assume that the next breach is already in progress, because in a microservices world with thousands of dependencies and hundreds of services, the attack surface never sleeps.

