Development, test and production environments are often separated on paper but joined in practice by shared credentials, shared networks, copied production data and developers with standing production access. When that happens, the weakest environment sets the security level of the strongest: an attacker who reaches a lightly protected test system can walk into production. This guide covers how to separate environments properly across accounts, networks and identities, how to handle production data in non-production, what access developers should have, how promotion paths should work and what evidence auditors expect for ISO/IEC 27001:2022 control 8.31. It is for application security, platform and cloud engineers and the people who prepare audit evidence. The policy wording lives in the Secure SDLC Policy Template; this guide is the implementation.
Key takeaways
- Separate by account, not by naming convention. A cloud account, subscription or project per environment gives a hard identity, policy and billing boundary; tags and resource names do not.
- No identity should span environments by default. Shared service accounts, pipeline credentials and admin roles that work in both test and production erase the separation.
- Production data in test inherits production's protection. NIST SP 800-53 SA-3(2) requires approval for live data in preproduction and protection at the same level as the live data, so mask or synthesise instead.
- Promotion is the only path to production. Changes reach production through a pipeline with approvals and protected credentials, not through a developer's laptop or console session.
- Forgotten non-production environments are a known breach route. Legacy test tenants and staging systems with weak controls and a trust path into production have led to major incidents.
What the control requires
ISO/IEC 27001:2022 Annex A control 8.31, Separation of development, test and production environments, expects the environments to be separated and secured. Related Annex A controls are 8.32 Change management, 8.33 Test information and 8.25 Secure development life cycle. NIST SP 800-53 Rev. 5 states the same expectations in more detail.
| Source | Requirement | What it means in practice |
|---|---|---|
| NIST SP 800-53 CM-4(1) Separate Test Environments | Analyse changes in a separate test environment before implementation in an operational environment, looking for security and privacy impacts | Testing in production is not testing; a real non-production environment must exist |
| NIST SP 800-53 SA-3(1) Manage Preproduction Environment | Protect preproduction environments commensurate with risk throughout the life cycle | Non-production is not exempt from security controls |
| NIST SP 800-53 SA-3(2) Use of Live or Operational Data | Approve, document and control live data in preproduction, and protect preproduction at the same level as the live data in use | Copying production data down drags production requirements with it |
| NIST SP 800-53 CM-5 Access Restrictions for Change | Define, document, approve and enforce access restrictions associated with changes | Who can push to production must be controlled and recorded |
| NIST SP 800-53 AC-5 Separation of Duties | Separate duties of individuals | The author of a change should not be its only approver |
| OWASP ASVS 5.0 V13.4.2 and V15.2.3 | Debug modes disabled in production; production includes only required functionality, with no test code or sample snippets | Build artefacts must differ by configuration, not by hand edits |
Separation patterns: account, network and identity
Separation has three layers. All three are needed; a separate network with a shared admin identity is not separated.
Account boundaries
AWS's guidance on organising environments explains that non-production and production often need different security and operational controls, and that separate accounts keep each environment's resources and data isolated by default, containing the impact of a misconfiguration or malicious activity to one account. Google's enterprise foundations blueprint uses folders named development, nonproduction and production, plus a common folder for shared services, with separate secrets and key management projects per environment and folder-level policies inherited by every project inside. Azure landing zones achieve the same with subscriptions under separate management groups.
| Pattern | Isolation strength | When it fits |
|---|---|---|
| Separate cloud organisation or tenant for production | Strongest: separate identity directory and admin plane | Highly regulated workloads, very large estates, or where the identity tenant itself must be isolated |
| Separate account, subscription or project per environment per workload | Strong: hard policy, IAM and billing boundary | Default for most organisations in the cloud |
| Shared account, separate VPCs or virtual networks | Moderate: network boundary but shared IAM plane | Transitional only; IAM policies must be written very carefully |
| Kubernetes namespaces in one cluster | Weak for security: shared control plane, nodes and often cluster-wide roles | Separating teams within one environment, not production from test |
| Same hosts, different folders or ports | Minimal | Not acceptable for production systems holding sensitive data |
Decision guidance: a small organisation can start with three accounts or subscriptions (development, test, production) plus one for logs and security tools. Larger organisations move to an account per workload per environment, which limits blast radius further and lets each team own its own accounts. A separate production tenant is justified when production identities must not be administrable by anyone who administers corporate IT. See the AWS Organizations and SCPs Guide for applying guardrails per environment.
Network boundaries
- Default deny between environments: no routing between non-production and production networks unless a specific flow is documented and approved.
- Shared services carefully: DNS, logging, artefact registries and identity providers are often shared. Make the flows one-way where possible (environments push logs to a log account; production pulls approved images from a registry) and never let a shared service become an admin path between environments.
- Separate egress and ingress: non-production should not be reachable from the internet unless it needs to be, and if it is, it needs authentication in front of it.
Identity boundaries
- Human access: distinct roles per environment, assigned separately, with production roles requiring stronger authentication and time-limited elevation.
- Non-human access: each environment gets its own service accounts, workload identities, API keys and certificates. A pipeline credential that can deploy to both test and production is a single key to both. See the OWASP NHI Top 10 NHI8 Environment Isolation Guide.
- Secrets and keys: separate secret stores or vault paths and separate encryption keys per environment, as the Google blueprint does with per-environment secrets and KMS projects.
SaaS sandboxes and identity provider test tenants
Separation is not only a cloud infrastructure question. Many SaaS platforms offer sandbox or preview instances, and identity teams run test tenants to trial policies. These environments are frequently created by copying production configuration and users, connected to the same identity provider and integrated with the same third-party apps. Treat each one as an environment in the inventory: give it an owner, require the same sign-in controls as production (MFA, blocked legacy authentication), keep its integration credentials and OAuth apps separate from production ones, and never grant an application registered in a test tenant permissions in the production tenant. Where a sandbox is refreshed from production, the data rules in the next section apply to it in full.
Production data in non-production
Copying production databases into test is the most common way environment separation fails. SA-3(2) is clear: if live data is used in preproduction, that environment must be protected to the same level as production, at which point it is no longer a cheaper, more open test environment.
| Approach | Realism | Residual risk | Use when |
|---|---|---|---|
| Synthetic data | Medium; generated to match schemas and distributions | Lowest; no real individuals | Default for development and most testing |
| Masked or tokenised copy | High; real structure with sensitive fields replaced | Re-identification if masking is weak or inconsistent | Integration and performance testing needing realistic volumes |
| Pseudonymised copy | High | Still personal data under UK and EU GDPR; full data protection rules apply | Only with a documented legal basis and production-level controls |
| Full production copy | Exact | Same as production | Rare, approved, time-limited cases such as diagnosing a data-dependent defect, in an environment secured as production |
- Make masking part of the pipeline: the job that refreshes test data should mask during extraction, so unmasked data never lands in the lower environment.
- Record approvals: every use of live data in non-production needs a named approver, a purpose and an end date, which is exactly the evidence SA-3(2) and ISO 27001 control 8.33 auditors look for.
- Remember secrets are data too: a production database restore can carry application secrets, OAuth tokens and API keys stored in tables.
See the Pseudonymisation Techniques Guide and the Anonymisation and Re-identification Risk Guide.
Developer access to production
Developers need to diagnose production problems; they rarely need standing write access to do it.
- Read paths first: give developers logs, metrics and traces from production through the observability platform, scrubbed of sensitive data, so most diagnosis needs no production login.
- Just-in-time elevation: when production access is needed, grant it through an approval workflow for a limited time, with session recording for privileged work. See the JIT Access Guide.
- Break-glass for emergencies: a documented emergency path that is monitored and reviewed after every use.
- Separation of duties: the person who writes a change should not be the only one who approves its deployment (AC-5). Small teams that cannot staff separate roles can compensate with mandatory peer review and post-deployment review of production changes. See the Segregation of Duties Guide.
Promotion paths between environments
The safest design is that nothing reaches production except through the pipeline, and the pipeline's production credential is protected more tightly than any other.
- Build once, promote the artefact: build an immutable artefact (container image or package) once, sign it, and promote the same artefact through test to production. Rebuilding per environment means production runs something that was never tested.
- Externalise configuration: environment differences live in configuration and secrets injected at deploy time, never in code branches, so debug settings cannot leak into production builds (ASVS V13.4.2).
- Protect the production deployment step: in GitHub Actions, environments support required reviewers (up to six users or teams), an option to prevent self-review, wait timers, deployment branch and tag restrictions, and environment secrets that jobs cannot read until a required reviewer approves. Administrators can bypass protection rules by default; turn that off for production. Plan limits apply: on Free, Pro and Team plans several of these rules apply only to public repositories. Other CI platforms have equivalents.
- Use separate deploy identities: federate each pipeline environment to its own cloud role, scoped to its own account, using short-lived tokens rather than stored keys. See the GitHub Actions OIDC Federation Hardening Guide.
- Infrastructure follows the same path: infrastructure as code changes go through the same promotion and approval as application code. See the CI/CD Security Guide.
Rolling out separation in an existing estate
- Inventory: list every environment, including forgotten staging, demo, training and test tenants, with an owner and its trust paths to production.
- Find shared identities: report service accounts, pipeline credentials and admin roles that work in more than one environment.
- Stand up the target structure: create per-environment accounts or subscriptions with guardrails, starting with production.
- Move production first, in waves: migrate production workloads into the protected structure, issuing new production-only credentials and rotating the shared ones.
- Close cross-environment paths: remove network routes and trust relationships one by one, monitoring for breakage, with the old rule ready to restore for a defined rollback window.
- Clean the data: replace production copies in non-production with masked or synthetic data and delete the copies.
- Retire what is unowned: decommission environments no one claims.
Audit evidence
| Evidence | Shows |
|---|---|
| Account or subscription structure diagram and export | Environments are separate at the account level |
| Guardrail policies per environment (for example service control or organisation policies) | Controls are enforced, not documented only |
| Role assignment reports per environment | Who can access production, and that it differs from non-production |
| Pipeline configuration and deployment approval logs | Changes reach production only through approved promotion |
| Live data approval records and masking job logs | Production data in test is controlled (SA-3(2), ISO 27001 8.33) |
| JIT and break-glass access logs with review sign-off | Production access is temporary and reviewed |
Detection and measurement
Alert on: sign-ins to production by identities that normally work only in non-production; deployments to production not originating from the pipeline; new trust relationships or network peerings between environments; bulk data exports from production to non-production accounts; and console changes in production outside break-glass. These map to ATT&CK techniques such as T1078.004 Cloud Accounts and T1199 Trusted Relationship.
- Identities valid in more than one environment: target zero outside documented shared services.
- Production changes made outside the pipeline: count per month, target zero apart from reviewed break-glass use.
- Standing human write access to production: number of people, trending down.
- Non-production datasets containing unmasked personal data: target zero without an approval record.
- Environments without a named owner: target zero.
Framework mapping
| Area | ISO/IEC 27001:2022 Annex A | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 |
|---|---|---|---|
| Environment separation | 8.31 | CM-4(1), SA-3(1), SC-7 | PR.IR-01 |
| Test data | 8.33 | SA-3(2) | PR.DS-01 |
| Change and promotion | 8.32 | CM-5 | PR.PS-06 |
| Access and duties | 5.3 Segregation of duties; 8.2 Privileged access rights | AC-5, AC-6 | PR.AA-05 |
| Secure development | 8.25 | SA-11 | PR.PS-06 |
CIS Controls v8.1 safeguard 16.8, Separate Production and Non-Production Systems, covers the same ground.
Common failure patterns
- Legacy test tenants with a path to production: in the Microsoft Midnight Blizzard Breach 2024, a password spray against a legacy non-production test tenant account without MFA led to a legacy test OAuth application with elevated access to the corporate environment.
- Shared pipeline credentials: one deploy key works in every environment, so compromising a test job compromises production.
- Production restores in test: full database copies refreshed weekly into a test environment with broad developer access and no masking.
- Namespaces mistaken for environments: test and production share a Kubernetes cluster and a cluster-admin role.
- Production secrets in development tooling: developers copy production API keys into local .env files or test configuration "temporarily", so a leaked laptop or test repository exposes production. See the Environment Variables and .env Files.
- Admin bypass left on: deployment protection rules exist but administrators can skip them, so emergency changes become routine.
Practitioner checklist
- Give each environment its own cloud account, subscription or project, with production guardrails applied at the organisation level.
- Deny network routing between environments except documented, approved flows.
- Issue separate service accounts, pipeline identities, secrets and encryption keys per environment.
- Replace production copies in non-production with synthetic or masked data; approve and time-limit any exception.
- Remove standing developer write access to production; use JIT elevation and monitored break-glass.
- Build once and promote signed artefacts; keep environment differences in injected configuration.
- Protect production deployments with required reviewers, no self-review and no admin bypass.
- Inventory and assign owners to every environment, including legacy test and demo tenants.
- Keep the audit evidence pack current: structure exports, role reports, approval logs and masking records.
Standards and references
- ISO: ISO/IEC 27001:2022 Information security management systems
- NIST: SP 800-53 Rev. 5
- OWASP: Application Security Verification Standard 5.0
- AWS: Organizing Your AWS Environment, Benefits of using multiple AWS accounts
- Google Cloud: Enterprise foundations blueprint, Organization structure
- GitHub Docs: Deployments and environments
- NIST: Cybersecurity Framework 2.0
Related NHI Mgmt Group resources: Secure SDLC Policy Template · Secure Software Development Lifecycle (SSDLC) Guide · OWASP NHI Top 10 NHI8 Environment Isolation Guide · CI/CD Pipeline Identity Security Guide