Secure software development and delivery guideline
On this page
Purpose
Developing and delivering secure digital solutions is critical to provide safe and reliable government services to the public, and to protect sensitive information. This guideline is intended to assist Queensland Government entities understand key concepts, processes, and techniques that enable the production of digital solutions that are resistant to malicious interference and therefore reduce Queensland Government cyber risk.
Overview
Secure software development and delivery is necessary to enable the Queensland Government to protect its sensitive data, including the data that it stores on the behalf of its employees, suppliers, and the citizens of Queensland. It is also necessary to ensure that the Queensland Government can deliver cost-effective and reliable public services, and to maintain the overall trust and confidence of the public.
Cyber adversaries are constantly attempting to find and exploit software vulnerabilities to compromise these systems for their benefit. These adversaries use automation technology, including artificial intelligence, to accelerate their malicious activity. Secure software development and delivery assist the Queensland Government defend against this threat and reduces the likelihood of major financial loss, service failure, and reputation damage.
Secure software development and delivery is not merely a technical requirement for information technology (IT) and operational technology (OT) solution development and operations. Executives, leaders, and other IT professionals at every level in the Queensland Government play a role in achieving positive cyber security outcomes. Adopting the guidance provided in this document, will help Queensland Government entities achieve the following benefits:
- Satisfaction of increasing customer expectations: Queenslanders expect that their sensitive information will be handled securely. A security breach can erode public trust of the entity, and the Queensland Government overall. When the public loses trust in the use of digital service channels, they resort to visiting physical customer service centres in person to conduct transactions, which is more costly to the Queensland Government and inconvenient for its citizens.
- Avoidance of costly incidents: Security failures can lead to high recovery costs, legal liability, extended service downtime, and reputational damage. Taking preventive measures upfront to avoid a major incident is much less costly than dealing with the fallout of a serious security incident.
- Enablement of innovation: The use of secure development and delivery practices enables an entity to innovate with IT to achieve business objectives without fear of introducing software vulnerabilities that lead to losses and service failure. The use of these practices typically results in higher quality digital solutions with a lower total cost of ownership.
- Satisfaction of contractual and regulatory compliance requirements: Security is often part of organisational, contractual, and regulatory obligations. Proactively addressing cyber security will ensure that your entity will continue to meet compliance stakeholder expectations and legal requirements at the lowest cost.
Content summary
Modern software delivery pipelines are attractive targets for attackers. Compromise of source code, build systems, or deployment infrastructure can lead to supply-chain breaches, intellectual-property theft, and regulatory exposure. This short summary of the enclosed guidance outlines controls and best practices to safeguard every stage of the software development environment – from coding and build automation to testing and deployment.
Secure software development must align with approved organisational policies, standards, and regulatory obligations to ensure consistent and compliant security practices.
- Map security controls that protect the software development environment to a relevant industry standard, e.g. ISO 27001, National Institute of Standards and Technology (NIST) Secure Software Development Framework (SSDF), Open Worldwide Application Security Project (OWASP) Software Assurance Maturity Model (SAMM).
- Ensure compliance with Requirement 3 of the Information and cyber security policy (IS18), which are relevant to the development of secure software.
- Maintain a complete software asset inventory, ideally as outlined in the Australian Signal Directorate’s guidance on software bill of materials.
Systems should be designed using secure architecture principles and deployed in hardened environments that reduce exposure to cyber threats.
- Perform and document threat modelling to identify how malicious activity could exploit vulnerabilities inherent to the proposed solution architecture and design, or to related business or technical processes.
- Separate development, test, and production networks.
- Use firewalls and micro-segmentation to limit lateral movement across development, test, and production environments.
- Enforce operating system hardening baselines, timely patching, and block the use of deprecated packages.
- Require full-disk encryption and endpoint detection and response (EDR) agents on developer endpoints, along with conditional access, and with browser isolation (for standard user or admin separation).
- Use dedicated, access-controlled cloud accounts, or Kubernetes “namespaces” (or equivalent) per environment to establish blast radiuses and enforce least privilege access.
- Scan containers and infrastructure-as-code (IaC), such as Docker, Kubernetes, Terraform, Amazon Web Services CloudFormation, to ensure safe images and to identify IaC misconfigurations early.
Access to systems, code, and environments should be tightly controlled, with identities, privileges, and secrets managed to prevent unauthorised use or disclosure.
- Enforce multi-factor authentication (MFA) for as many privileged accounts as practical.
- Apply least privilege and just-in-time access using role-based access control.
- Centralise secrets in a vault and never store credentials in source code.
- Configure audit access logs to be generated and assign responsibility to review the logs, or ideally, be integrated into a security incident and event management system (SIEM), for anomaly detection.
- Do not paste secrets, tokens, customer data, proprietary algorithms into artificial intelligence (AI) prompts.
Source code and third-party dependencies should be protected, reviewed, and maintained to reduce the risk of tampering, vulnerabilities, and supply chain compromise.
- Use a centralised version control platform, for example GitHub Enterprise, GitLab, Bitbucket, with branch protections and the requirement for mandatory code review.
- Require repo pull request reviews before merge; disable direct pushes to the main branch.
- Sign all commits, for example using GNU Privacy Guard or OpenSSF Sigstore, to verify provenance.
- Enforce software composition analysis to detect vulnerable third-party packages.
- Generate and publish software bill of materials (SBOM) for each release, and collect and manage SBOMs for dependencies, to achieve software supply chain transparency and security.
- Protect secrets with a 'vault' to avoid storing secrets in the code repository, for example GitHub.
Build and deployment pipelines should be secured to preserve the integrity of software artefacts and prevent unauthorised changes throughout the build, test and release process.
- Wherever possible, use service accounts, (for example, Microsoft Entra service principals), over user accounts for automation such as running tests, builds and deployment. Ensure credentials are stored securely and their lifecycle managed.
- Isolate build servers and ensure there is no direct internet access for production builds.
- Use ephemeral build agents to reduce the ability of malware to remain persistent.
- Require signed, reproducible builds and store build artifacts in tamper-evident repositories.
- Integrate static application security testing, dynamic application security testing, and dependency scanning into CI/CD pipelines.
- Protect CI/CD pipeline configuration files with strict access controls and code review.
- Deploy tools — such as GitHub Dependabot — that automatically detect vulnerable and deprecated packages and ideally replace them.
- Require code to meet dependency vulnerability scanning requirements as a prerequisite for deployment.
- Enable advanced or audit logging in the code repository and forward to your SIEM if possible.
- Adopt ephemeral, isolated CI/CD 'runners' to impede build poisoning and credential theft.
- The CI/CD processes should include Application Programming Interface (API) security tests, container vulnerability scans, misconfiguration checks, secrets detection, and software bill of materials generation and signing.
Security testing should be performed before production release to identify and address vulnerabilities, misconfigurations, and other security weaknesses early.
- Maintain dedicated staging environments that mirror production for realistic testing.
- Mask or tokenise sensitive production data used in testing.
- Conduct regular penetration tests and red-team exercises focused on the development environment.
Effective monitoring, logging, and incident response processes should be in place to detect, investigate, and respond to security events in a timely manner.
- Centralise logs from code repositories, CI/CD tools, build servers, and developer endpoints to support correlation and anomaly detection.
- Monitor for unusual commit activity, privilege escalations, or suspicious pipeline changes.
- Define an incident response playbook tailored to software development environment compromises, including rapid key rotation and artifact revocation.
Teams should be trained and secure coding skills maintained as part of a strong security culture so that secure development practices are understood and consistently applied.
- Provide secure coding training regularly, and in short intervals to avoid adversely affecting developer productivity. Cover topics such as the OWASP Top 10, language-specific pitfalls, code repository (Github) security model and controls, CI/CD security, threat modelling, and the developer’s own application security policies.
- Conduct simulated phishing and social-engineering awareness for developers and development and operations (DevOps) teams. Encourage a 'security-by-design' culture with regular knowledge-sharing sessions.
Artificial intelligence tools should be used responsibly and securely, with appropriate controls to protect sensitive information, maintain quality, and manage risk.
- Ensure that AI-enabled software development tools have inherent protections to safeguard against the extraction of an entity’s sensitive information or can be manually configured to prevent this.
- Do not paste secrets, tokens, customer data, or sensitive algorithms, into AI prompts.
- Consider the use of masking scripts or safe prompt wrappers that automatically redact sensitive or dangerous content.
- Implement non-deterministic methods that validate AI output (guard rails) where practical to increase reliability and ensure continuous monitoring to help mitigate the risks.
- Configure AI tools to not train themselves with an entity’s code base, nor store an entity’s software artefacts in clear text. This is especially within logs that can be accessed without entity authorisation.
- Only use AI-enabled tools that have been security assessed and approved by your entity. Then, adhere to any restrictions on use.
- The use of an AI-enabled software development tool by an entity should be conditional upon
- the risks being identified using the Foundational artificial intelligence risk assessment framework
- these risks being mitigated as acceptable by entity management.
Secure software development practices should be regularly reviewed and improved to respond to emerging threats, lessons learned, and changes in technology or business needs.
- Establish metrics such as mean time to patch (MTTP) and percentage of critical vulnerabilities remediated within the entity’s established service level agreements (SLA).
- Perform periodic maturity assessments, for example OWASP SAMM. Adjust policies as the entity evolves.
- Review and update the entity’s secure software development and delivery guidance annually, or after major incidents.
- Apply new vulnerability discovery tools and methods to snapshots of older code to confirm that (now) known vulnerabilities are detected.
Enablers of secure software development and delivery
This section highlights the interdependence between organisational culture, people, processes, and technology. Interdependence is required to achieve secure software development and delivery, and more cyber resilient Queensland Government entities. By addressing these four dimensions holistically, entities can:
- reduce risk and losses
- improve business efficiency
- even foster innovation.
They can also maintain compliance with legal and regulatory obligations, and continue to maintain the public’s trust.
Cyber security is not just the responsibility of IT or cyber security teams – everyone has a role to perform. A strong cyber security culture begins with leadership. Executives and project managers set the direction by ensuring security is considered in planning, budgeting, decision-making and scheduling. By fostering a culture of accountability and collaboration, entities can ensure that security becomes an integral part of their values, delivery capabilities, and operations.
Technical teams write secure code and securely configure solutions. However, business leaders, project owners, project managers, and those working in service operations, need to ensure that cyber security is adequately prioritised. By speaking out about the importance of cyber security, championing security initiatives, allocating sufficient resources, holding teams accountable for cyber outcomes, and treating cyber security as a solution quality metric, a leader at any organisational level can help develop a culture where cyber security is understood, valued, and appropriately prioritised.
The skills and awareness of an entity’s IT workforce are critical to secure software development and delivery. From software developers, testers, and operators, through to designers, architects, and service operations staff, every IT team member plays a specific role in ensuring secure software development and delivery. Investment in cyber training tuned to the right audience, and fostering cross-functional collaboration, empowers people and teams to embed security into their daily work. A skilled and security-aware workforce is the foundation of a cyber resilient organisation.
Deploying secure software requires well-defined, repeatable, and verifiable processes that integrate security into every stage of the software development and delivery lifecycle. This includes:
- defining security requirements early
- protecting and assuring the components that comprise the software
- conducting reliable security testing throughout the development and delivery lifecycle
- maintaining the information to track source of software components, their dependencies, and any known vulnerabilities.
In addition, incorporating cyber security into processes such as asset management, external IT service provider assessment, change management, solution testing, disaster recovery, business continuity management, and security debt registration and management, enables teams to deliver secure, high-quality digital solutions efficiently, and within an entity’s cyber security risk thresholds.
Technology is an enabler to achieve an entity’s business objectives, but it is also a safeguard for secure software development and delivery. Secure development environments, automated testing tools, and defendable software development and deployment pipelines, help:
- reduce vulnerabilities
- streamline software delivery.
Technology also enforces access control policies and supports incident detection and response.
In the context of these four enablers, this document provides guidance about how to uplift an entity’s secure software development and delivery maturity. By addressing culture, people, processes, and technology together, you can create an environment where security is embedded in software development by design, not retrofitted as an afterthought when the costs to remediate defects is much higher, or worse - after a significant entity loss event has occurred. This holistic approach not only reduces cyber security risk, but it also enables your organisation to deliver reliable, trusted software to support services to Queenslanders and foster public trust in Queensland Government’s lower-cost digital service channels.
Consider security from the start
By making cyber security a fundamental consideration early during project planning, an entity:
- improves solution quality
- reduces cyber risk
- avoids costly rework to remediate security defects.
When considering the delivery and maintenance of technology solutions, it’s much cheaper and easier to address cyber security during the requirements, design, and development, phases of solution development, rather than to reactively address problems that are detected later in the delivery process, and especially after the solution has been deployed into production.
Consider:
- explicitly defining security requirements into the overall set of solution requirements
- confirming these requirements are being met throughout the development and delivery process (certainly before production release).
Developing a standardised set of security requirements, patterns and architectures, that are applicable to your entity’s specific technical environment and are reusable across initiatives, will also help reduce the overall cost of secure development and delivery.
According to OWASP, a threat model is a structured representation of all the information that affects the security of an application. In essence, it is a view of the application and its environment through the lens of security. Threat modelling can be applied to a wide range of things, including software, applications, systems, networks, distributed systems, Internet of Things (IoT) devices, and business processes.
A threat model typically includes:
- description of the subject to be modelled
- assumptions that can be checked or challenged in the future as the threat landscape changes
- potential threats to the system
- actions that can be taken to mitigate each threat
- a way of validating the model and threats, and verification of success of actions taken.
Different frameworks and approaches to threat modelling can be used, such as:
- MITRE ATT&CK and D3FEND frameworks
- NIST SP 800-154 (Special publication 800-154: Guide to data-centric system threat modelling)
- PASTA (Process for attack simulation and threat analysis)
- OCTAVE (Operationally critical threat, asset and vulnerability evaluation)
- OWASP Threat Dragon
- Microsoft threat modelling tool and the STRIDE model.
Applied to software, it enables informed decision-making about application security risks. In addition to producing a model, typical threat modelling efforts also produce a prioritised list of security improvements to the concept, requirements, design, or implementation of an application. Threat modelling includes:
- identifying how various potential malicious activity could exploit vulnerabilities inherent to the proposed solution architecture and design, or to related business or technical processes
- viewing the proposed solution with a malicious actor’s mindset
- assessing trust boundaries and consider if they have appropriate security controls applied to stop, disrupt or minimise attack pathways
- assessing the application’s entire attack surface – especially APIs
- considering if the solution will store or access sensitive information, or, if not, could it serve as part of an attack vector to other solutions that do.
Encourage collaboration between delivery management, designers, developers, security specialists, and service operations teams to identify security risks early and respond promptly. Adopting multidisciplinary approaches like Agile Delivery and DevSecOps, where security is integrated into both development and operations, can significantly increase this collaboration. Integrate security checks into existing process workflows, such as project planning, code reviews, and automated testing, to identify security concerns early in the software development and delivery process.
Empowering developers to take responsibility for the security of their code is essential to foster a culture of solution ownership and accountability. Security specialists can provide support by working closely with development teams to identify areas of elevated security concern and security-critical solution components, such as digital payment gateways, and other boundaries identified through data flow analysis or threat modelling. This collaboration ensures developers understand where to focus their efforts and when to seek additional support.
Such support can be further enhanced by encouraging development teams to use well-tested security-sensitive software, such as those found in component catalogues, or reusable microservices. By leveraging these existing resources, developers can avoid wasting effort on redevelopment and the possibility of introducing new vulnerabilities.
Given the increasing complexity of software technology and its development and delivery environments, security issues can arise from knowledge gaps and human error. Providing your teams with the right training – whether they’re technical or non-technical – empowers them to recognise and address risks. For example:
- business analysts and designers can learn basic concepts of threat modelling
- architects and designers can learn to integrate security features into solution designs
- developers can learn secure configuration and coding practices and how to deploy automated security tools in build processes
- testers can learn security testing techniques to catch defects that introduce security concerns earlier in the delivery lifecycle.
Security knowledge must be treated as a core competency, with developers and testers regularly trained and supported to stay ahead of evolving threats. Secure development training that is programming language agnostic, and training that is platform specific, is necessary to build awareness of both existing and newly emerging security threats. There are multiple ways that this training can be obtained ranging from freely available online videos, self-paced online courses, through to the highest quality advanced in-person classroom instruction augmented with lab activities.
Regardless of the type of educational delivery, it is essential that developers learn how to avoid introducing vulnerabilities into the solutions that they are building. Threat modelling further enhances this capability by instructing architects, designers, developers, and testers, to anticipate potential attack vectors and design and implement systems to mitigate them. These efforts should also include training on the entity’s architectural and security standards, and detailed design practices, to ensure that developers can write code with a defensive mindset. This applies particularly when producing security-critical software components where malicious activity has the potential to cause significant loss events.
Consider implementing the following actions:
- Learning from real-world experiences is a powerful way to reinforce security skills. Run retrospective sessions that analyse actual issues that have adversely impacted their own solutions, thereby providing developers with practical insights into improving future code.
- Maintain a curated list of trusted security training resources, tailored to the entity’s products and technology stack, that can provide developers with quick access to relevant and reliable security information.
- Incorporate the requirement for cyber security training into every developer’s role to demonstrates an entity’s commitment to security outcomes and to promote an internal entity culture of continuous improvement.
- Provide secure coding training regularly, but in short intervals to avoid adversely affecting developer productivity. This can cover topics such as OWASP Top 10, language-specific pitfalls, repository, for example Github, security model and controls, CI/CD security, and threat modelling the developer’s own applications.
Produce consistent and comprehendible code
Code that is poorly written, inconsistent, or undocumented, increases the overall complexity of a system, which makes it more difficult to ensure that security issues have been properly addressed. Complexity can obscure defects that introduce vulnerabilities. It then makes it difficult for the defects to be detected and corrected during the development process. Naturally, this task becomes more difficult as the codebase increases in size and complexity. Promote the value of clearly written and well-structured code to understanding of the code base. This reduces the risk of obscured security defects and can expedite routine software maintenance, reducing cost.
Create or adopt secure design patterns and a consistent coding style. These can help ensure that the codebase is readable, maintainable, and even self-documenting. Supplementary materials, such as security specifications and standards, the creation of associated test cases for integration into development pipelines, and performing regression testing, should evolve alongside solution development to provide additional assurance.
Key sources of complexity include poorly structured software architectures, classes or variables with confusing or ambiguous names, inconsistent file organisation, and the introduction of different coding styles among individual team members. Other issues include insufficient software documentation, such as inline comments or system design artefacts, and coding without consideration for subsequent testing or validation.
Addressing these issues through a requirement for well-defined coding standards, and a strong culture of adherence, ensures a logical and readable codebase as the solution evolves and is maintained over time. Where available, language and industry-based coding standards should be considered and ideally used during the software testing process to ensure compliance.
Responsible use of AI in software development
The use of AI-enabled software development solutions may increase productivity by generating code automatically. These solutions may be delivered as stand-alone products or web sites/services. They may also be integrated into new or existing software development environments (SDEs) or be accessible by other means. The use of these tools introduces security risks into the software development and delivery process that must be managed for the tools to be used safely.
AI-enabled software development tools in the hands of competent and experienced developers may increase productivity and result in code with less security defects. However, AI-enabled tools are not yet capable of always producing code that is totally free of security defects or may produce code that is inappropriate for the solution architecture. When these tools are used by inexperienced or incompetent developers, and the code that is generated is not actually understood by the developer, security defects and other problems can arise.
Consequently, the code that is produced must be reviewed, and formally approved, by experienced, security-knowledgeable, software engineers before inclusion into any entity digital solution under development. This requirement is even more important when producing software that will form part of:
- multiple software solutions, for example libraries and other software dependencies
- solutions where exploited security defects can result in catastrophic outcomes.
Another risk of the use of AI-enabled software development tools is the potential loss of an entity’s sensitive information. An inexperienced or careless software developer may include intellectual property, access control tokens or passwords, encryption artefacts, or other sensitive information within their code that later becomes accessible by the AI-enabled tool, potentially to unauthorised parties. As with any information submitted to an external service, a copy of the information both may be stored within the service’s repository in some form, which may later be extracted by cyber adversaries using innovative techniques.
- Some AI-enabled tools have inherent protections to safeguard against the extraction of an entity’s sensitive information or can be configured to prevent this. Unfortunately, many do not. Consequently, the use of AI-enabled software development tools by an entity should be conditional upon the risks being investigated, documented, then effectively mitigated, with the residual risk level being formally accepted by entity management.
- Do not paste secrets, tokens, customer data, proprietary algorithms into AI prompts.
- The use of masking scripts or safe prompt wrappers that automatically redact dangerous content may be helpful albeit not always reliable. Implementing other guard rails, such as non-deterministic methods to ensure expected outcome and implementing mechanisms for continuous monitoring can help mitigate the risks.
- Configure enterprise-grade AI features to prevent an AI system from training itself with an entity’s code base or storing an entity’s software artefacts in clear text, especially within logs that can be accessed without entity authorisation.
- Only use AI-enabled tools that have been security assessed and approved by your entity.
Address the risks of using externally sourced code
The productivity of most software developers is dramatically increased via their acquisition of externally sourced code, which is often referred to as a 'library', 'package', or 'dependency'. By utilising externally sourced code to implement a component of a solution, a developer avoids having to write their own code to produce the same component. Unfortunately, cyber adversaries are aware of this practice and can exploit it for their malicious purposes. The software supply chain is now under continual threat.
For example, cyber adversaries can covertly introduce malicious code into an external repository. This then becomes a part of the entity’s solution once the entity incorporates the external repository into the entity solution under development. Whenever externally supplied software is under consideration for entity use, a record should be kept describing:
- why the software is believed to be trusted
- what actions are required to mitigate the risk
- what impacts will occur should a security issue arise
- what actions will be required if this trust is breached
- who compiled the record
- who approved the decision to proceed.
Entities can restrict the use of externally sourced code to those sources deemed trustworthy, or low risk. This is an external source that:
- has a long history of responsible software management
- provides code that is widely used globally
- promotes their own secure software development practices
- has a demonstrated rapid response to reported security defects will introduce a lower risk than an external source that is
- new or unproven
- only used by a small number of other organisations
- does not implement secure development practices, and
- is non-responsive to reports of security defects.
An entity can accurately track its use of externally sourced code. Tracking information, which is often represented in a machine-readable format called a software bill of materials (SBOM), is highly useful when security defects become known to the software developer community. When an entity’s software developers become aware of the defect, they can use the SBOMs to rapidly determine if they have produced, or operate, software that includes the defective code, and what action to take. This activity can dramatically increase the speed that an entity can remediate the defect, which reduces the time that an adversary can exploit the defect.
Entities should ensure that all externally sourced code receives a security review by a security-knowledgeable developer, and is analysed by security testing tools, before being allowed to be incorporated into an entity’s IT solutions. The mitigation activities should be considered essential in situations where exploited security defects can result in significant adverse outcomes.
Ensure secure failure modes
A secure failure mode (or fail closed mode) is a design principle where systems default to a secure state when an error or unexpected condition occurs. Instead of maintaining availability at the expense of security, the system denies access or halts operation until the fault can be safely resolved. This approach prioritises confidentiality and integrity over convenience or uptime and is appropriate in many scenarios. For example, if an authentication service fails to connect to its identity provider, a fail-closed system will reject all login attempts rather than allowing unauthenticated access. The goal is to prevent accidental or malicious exploitation during periods of degraded operation.
Failing securely ensures that a system’s security boundaries remain intact even when dependencies break, or inputs behave unexpectedly. Adversaries often look for failure paths such as timeouts, exceptions, or dependency failures, that cause systems to revert to permissive behaviour. By explicitly defining how components respond to failure, developers eliminate ambiguity that might result in unvalidated data being accepted or unauthorised users gaining access. This mindset treats failure as a potential attack vector, ensuring that no data is exposed, modified, or processed insecurely when components malfunction.
Some examples include:
- when writing access-control mechanisms, always initialise authorisation states to false or denied. This ensures that if the validation logic crashes midway, the user is locked out rather than granted access
- when handling application errors like a dropped database connection or an API timeout, catch blocks should terminate the current process or transaction and throw an exception rather than silently bypassing the failure
- fail-secure software protects information boundaries when a crash occurs. A system failure should never leak operational context to the end-user. Log highly detailed contextual information, for example, stack traces, database query errors, memory dumps, and so on internally to a secured logging server. Present the public user with a generic, sanitised error identifier, for example 'An unexpected system error occurred. Reference code: ER3465'
- when secondary systems or microservices experience a severe outage, implement 'circuit breaker' patterns that fall back to static, safe functionality rather than leaving endpoints exposed. If an external authorisation provider or database goes offline, the software should automatically downgrade into a restricted, read-only mode, rejecting all data manipulation requests until the service safely recovers
- ensure the CI/CD pipeline runs negative test cases. Test passing invalid inputs, mock database drops, or malformed authentication tokens to verify that the software responds by rejecting the interaction rather than breaking open.
While failing securely protects against unauthorised access and data corruption, it can impact availability, especially in distributed systems or high-availability environments. Therefore, architects must design systems that are both resilient and secure under failure. This often involves redundancy, health checks, and circuit breakers to ensure that security enforcement points like authentication, encryption, and access control, are reliable and can fail independently without compromising protection. Ultimately, designing for secure failure means recognising that availability can be restored, but a loss of confidentiality or integrity cannot be undone, and then building systems accordingly.
The entity’s software development and delivery methodology should capture the concept of solution 'survivability', which recognises that the operating context for most software must be considered hostile. Entities should ensure that their software development practices assume the omnipresence of adversaries. This includes practices that confirms the integrity of builds, for example by digitally signing legitimate artefacts, and by 'failing secure' if the software is malfunctioning.
Secure the development environment
Malicious software can cause significant financial and reputational damage to a Queensland Government entity and can even cause risks to human safety. An entity’s employees who use IT systems can be tricked into assisting cyber adversaries by inadvertently introducing malicious software into an entity’s IT environment. In response, modern enterprise IT environments include controls that prevent standard users from writing and executing their own code, and from executing code obtained from external sources, either deliberately or accidently. As standard IT system users have no work requirement to write and deploy code, these restrictions typically pose little to no inconvenience to the entity.
However, these same restrictions are impractical for an entity’s software developers. Writing code, and obtaining code from external sources, and then executing code, for example as part of testing and deploying new services, is an inherent part of their role. Cyber adversaries are fully aware of the extra system access, and powerful capabilities, provided to entity’s software developer. So, they consider these developers as attractive targets. Compromising the account of a software developer is often a first step of a malicious process that can result in significant losses to an entity. The following sections describe steps that entities can take to address this threat.
Address flexibility and security trade offs
Firstly, the performance of a software developer is often evaluated by the developer’s productivity in writing code to build or extend IT solutions. Consequently, it is important to ensure that those security controls and processes put in place to protect the developer’s digital work environment interfere as little as possible with their software development and delivery practices.
Securing a development environment requires:
- understanding the risk context
- applying appropriate technical controls
- ensuring trust and verification of legitimate usage.
The line between development and operations is becoming increasingly blurred. This overlap means that a compromised development device could have significant and direct downstream impacts on services. Implementing risk-appropriate controls to limit this exposure is important.
A compromised development environment can lead to several risks, including theft of sensitive information such as encryption keys, passwords, and intellectual property. Compromise can also result in the insertion of malicious code into the source code base for IT solutions under development or maintenance. Compromised devices can be used by an adversary to:
- attack the build and deployment pipeline
- gain a foothold into the wider entity IT environment
- gain insight into sensitive applications as a precursor to further attacks via other means.
Users of standard business services like email, document storage, and routine business applications, are targets of cyber adversaries. Software developers are often users of these same standard business services. For these software developers, logical separation of their development environments from their access to standard business services impedes adversaries who are successful at compromising the standard business services from then moving laterally to then gain additional unauthorised access the development environment.
To further address these risks, an entity can apply the following additional practices.
This separation can be achieved with virtual machines, authenticated privilege escalation, and other logical means, without requiring separate physical devices, albeit separate devices can certainly achieve the same outcome. Deploy endpoint detection and response (EDR) agents on developer endpoints, along with conditional access, to impede malicious activity being performed by an adversary that gains unauthorised access to the developer’s device. Use browser isolation to separate standard user versus developer usage so high-risk activity associated with standard web browsing is less likely to impact the development environment.
A development environment is an attractive target to an adversary. If an attacker compromises a developer’s environment, they may inherit the same system permissions and privileged access as the developer. Controls like MFA, automated security testing under control of a different user, and multi-person code reviews, can help mitigate the impact of successful initial adversary intrusion. Require full-disk encryption on developer endpoints to mitigate against a lost or stolen device.
The principle of least privilege dictates that each user, system, or process should be granted only the essential permissions necessary to perform its legitimate task and nothing more. A primary technique to reduce the attack surface and implement least privilege access in a software development and delivery environment is to apply fine-grained role-based access controls.
Disallow software in the environment that is not necessary for development, restrict activities within the environment to those individuals and actions specifically necessary to progress software development within the environmental boundary. Each developer, build server, and automation tool, should have only the minimum permissions necessary to perform their defined functions. Those permissions should be regularly reviewed and revoked when no longer needed. For example:
- a front-end developer should not have database administrative privileges
- a build automation account should not be able to modify production secrets.
The gradual accumulation of access within the development environment should not be perceived as a sign of trust, status, or competency. Rather, it is a personal responsibility only to be accepted when necessary for the individual to perform their allocated software development or delivery task or role, and, even then, for the least amount of time. By ensuring that even trusted users or services cannot access systems or data they do not require, you significantly reduce the number of potential entry points that an adversary could exploit.
Monitoring the development environment
In mature IT organisations, certain system access provided to, and tasks performed by, system administrators are monitored, which allows for:
- user access and activity reviews
- incident response processes to be initiated.
Consider similar tracking of select developer actions that might indicate compromise and malicious activity.
Tools can be used to control, monitor, and report, on each time that a developer performs a task that requires administrative access. The benefit of these tools is that they can track these high-risk tasks and ensure that developers only receive the permissions necessary. Examples include:
- token creation – generating authentication tokens that grant access to systems or code
- repository visibility changes – switching a code repository from private to public (or vice versa)
- force pushes – overwriting commit histories in a shared repository, which can destroy or alter code
- GitHub App installations – adding third-party integrations that may require extensive permissions and impact the CI/CD process
- GitHub Actions workflow edits – modifying automated CI/CD build pipelines, which could introduce malicious deployment steps if compromised.
When a developer changes projects or role, or ceases to be employed by an entity, the tool ensures that all unnecessary permissions are immediately revoked. By providing the right tools and environments, entities can empower developers to work productively while ensuring a secure posture.
Advanced tools that perform user and entity behaviour analytics (UEBA) can help identify unusual or risky behaviours, such as accessing sensitive systems at odd hours or attempting to upload or download large volumes of data. These tools use machine learning to establish a baseline of normal activity and flag deviations for further investigation. By combining trust with robust verification mechanisms, entities can strike the right balance between security and productivity. If your entity operates a SIEM solution, consider requesting that logs of important developer and administrator actions be ingested into the SIEM to assist with anomalous event detection.
Even with robust security measures, compromises will occur. Preparing for this eventuality involves proactive threat modelling to identify potential attack vectors and to assess the impact of a compromised development environment. This should be complemented by an incident response plan that addresses:
- the most likely types of compromises anticipated
- what action to take
- whom to inform.
Reduce the attack surface of the developer environment
Minimising the attack surface of development environments can reduce the likelihood of exploitation. Segregating development, testing, and production, environments are important to minimise lateral movement and prevent malicious software active in one environment from reaching the others. Other techniques include running development workloads inside isolated virtual networks, using hardened base images for build servers, and disabling unused services or open ports. Effective data management practices, such as ensuring that sensitive data is anonymised or desensitised where possible, can limit the value of stolen data to attackers.
Containerisation and ephemeral build agents can help ensure that each build starts from a known-clean state and is discarded when finished. This leaves no persistent environment for an attacker to exploit. Regular patching and configuration management automation using dedicated software tools such as Ansible, Chef, or Terraform can help ensure systems are configured consistently and securely every time they’re built. One cannot steal what no longer exists.
Infrastructure as code (IaC) refers to defining infrastructure setup, for example servers, networks, build agents, and so on, using code, so one can automatically rebuild environments with the same secure baseline every time. This consistency helps prevent “configuration drift” where systems slowly diverge from secure standards due to manual modifications. An adversary’s processes to maintain a foothold in a target environment can be frustrated by regularly generating “greenfield” virtual infrastructure as part of software builds. Logically segmenting the development environment can increase overall security by requiring an adversary to have to breach many controls to move laterally to access the entire environment.
Automating and codifying infrastructure setup keeps every build environment securely patched and consistent across the entity. By addressing these issues, entities can create a more resilient development environment with fewer opportunities for attackers to exploit. Ensure that CI/CD and other build processes remove all temporary artefacts promptly after use.
Protect access credentials and secret keys
Privileged Identity Management (PIM) refers to managing and controlling privileged identities, namely those accounts with elevated permissions that can access sensitive systems and data. PIM solutions provide a way to grant just-in-time, time-bound, or approval-based, access to critical resources. Privileged rights are granted only when needed and for a limited duration. Requests for privileged access often require managerial or security-team approval. All privileged activities are logged for compliance and security monitoring.
Privileged Access Management (PAM) is a broader discipline for securing, controlling, and monitoring privileged access to critical systems. While PIM deals with identities, PAM focuses on the access and sessions themselves. PAM solutions store and rotate credentials for privileged accounts such as root or admin accounts. PAM solutions also record administrator sessions for forensic analysis. PAM allows access without revealing actual passwords to users.
PIM and PAM tools should be considered for use in an entity’s software development and delivery environment. Naturally, multi-factor authentication (MFA) adds an additional layer of protection, ensuring that stolen credentials alone are insufficient for access.
Entities should also adopt practices such as encrypting secrets, storing them in dedicated secrets management tools, and avoiding hardcoding them into source code. Source-code scanning tools should be applied to scan for exposed secrets at every stage in the development lifecycle. Protect secrets with a vault or secrets manager. Examples solutions include Github Actions Secrets, AWS Secret Manager, and GCP Secret Manager. Do not allow secrets to be stored in the code repository. By implementing the measures described in this section, entities can significantly reduce the risk of credential theft and misuse.
Avoid operating production systems from a development environment
Operating live production systems from development environments introduces significant risks. You should avoid this wherever possible. When access to production systems is necessary, it should be governed by request and approval-based processes that enforce separation of duties. Developers should only be granted temporary access through PAM tools. All actions should be logged and subject to session recording for accountability. By limiting access and enforcing strict controls, entities can reduce the risk of accidental or malicious changes to production systems.
Protect your code and configuration repositories
A common practice of software development teams is for all team members to store software in a code and configuration repository, such as GitHub, GitLab, Bitbucket, and Azure DevOps. The purpose of the repository is to serve as the central location for:
- software that the team writes
- software obtained from external sources, that is intended to comprise the entity’s IT solution under development.
The repositories also provide features to automate software artefact management, change and version control, automated testing processes, and many other functions. These features increase development efficiency and reduce complexity. The result is:
- faster and less expensive software development and delivery costs
- effective software asset management
- less errors in software composition
- decreased risk of a security defect.
Cyber adversaries understand the immense opportunity that unauthorised access to a repository provides. They can steal code and other intellectual property, covertly insert malicious code to compromise systems that rely on the repository, and steal authentication credentials from the repository. This opens the doors to a broad range of malicious activity. Consequently, an entity’s code and configuration repository must be comprehensively protected. This section guides entities on how to protect entities' code and configuration repositories.
Evaluate and monitor entity repositories
The repository chosen serves as the foundation for part, or all, of the entity’s entire codebase including configuration files. Protecting the repository from unauthorised access is clearly important. An entity may choose to host a repository product within its own IT infrastructure. Alternatively, they may utilise a cloud-based repository service. In either case, it is important to evaluate the operational management of the service, including its:
- underlying infrastructure
- APIs
- access control mechanisms
- support
- proactive monitoring processes.
Entities should select a reputable provider of code and configuration repositories. Preferably choose one with a long history of effective management. Both Git and Github are well-established but other offerings with similar reputations may be suitable. Regardless of the repository selected, it is important that the software development and delivery teams are trained in how to configure and use the repository to avoid situations resulting in serious security implications.
Software development and delivery that relies on public or open-source repositories introduce unique risks. Public repositories often display contributor profiles. These profiles can be exploited for social engineering attacks like spear-phishing. Ensure you:
- limit the amount of personal information shared in your profile
- educate contributors on the importance of protecting their online identities.
With public repositories, an entity’s code may be visible and accessible to anyone. Highly sensitive code, such as fraud detection algorithms and payment gateway access, should always be stored in private repositories to limit external exposure.
The primary objective of repository security is strict control over who can access what content. Consistent with the principle of least privilege, every user, service account, and automation tool, should receive only the minimum permissions necessary to perform the specified task or function. Use role-based access control to grant granular permissions, such as:
- read-only for auditors
- limited write access for developers who need to push code.
Require multi-factor authentication (MFA) for all accounts to reduce the risk of unauthorised logins if credentials are compromised. Integrate your repository platform with a centralised identity and access management (IAM) solution to unify authentication across systems. This allows rapid repository access de-provisioning when employees leave the entity or change roles.
Naturally, it is important to review access rights regularly. Automated audits can help identify dormant accounts or excessive permissions that accumulate over time. Where feasible, prefer short-lived access tokens or fine-grained personal access tokens over long-lived credentials. These can be narrowly scoped to specific actions, reducing the impact if a token is compromised.
Just like for managing development environment access, consider the use of PAM and PIM systems to limit access to sensitive areas of the repository. Ensure that any other software tools that integrate with the repository via an API employ effective authentication and authorisation methods. Automate the processes that implement access key rotation policies.
Adopt a least privilege model by restricting repository access based on role and necessity. For example, developers may only need read access to certain repositories, while specific roles like team leader or release manager may require write or merge permissions. Enable user activity logging to create an audit trail of actions performed within the repository. Consider ingesting these logs into your entity’s SIEM.
Ensure a mechanism is in place to swiftly and comprehensively revoke access to the repository to anyone in case of suspected compromise. Implement incident response procedures to isolate affected accounts and investigate the root cause. These measures mitigate the risk of unauthorised access, or excessive damage should unauthorised access occur. Combine this with regular user activity reviews to identify anomalies, for example unauthorised access attempts or suspicious repository changes.
In summary, repository access should be carefully managed to prevent unauthorised use. As teams evolve, periodically review access permissions and revoke access that is no longer needed. Automate this process using identity governance systems and access management tools to ensure prompt action. When an employee leaves the entity or changes roles, their repository access should be immediately disabled and scheduled for deprovisioning.
Gaining unauthorised access to repositories that contain the code of popular packages is now a top priority of adversaries due to the:
- potential to compromise the package
- different software products that are then built using the compromised package.
Default repository platform settings may not provide sufficient protection. So, a review of the initial configuration should be performed. Consider the following actions:
- enforce branch protection rules so changes to critical branches, (main, master or release) cannot be modified directly
- require pull requests, which can enforce peer code review, initiate automated testing, and enable approval workflows
- disallow force pushes to protect the integrity of the commit history
- enable signed commits and tags to verify the authenticity of contributors, and to record the contributor initiating each change. Using GPG or secure shell (SSH) signing ensures that commits come from trusted developers, and not unauthorised individuals who may be impersonating legitimate repository users
- regularly update and patch self-hosted repository servers to eliminate known vulnerabilities
- apply hardening templates and disable features not required by your organisation such as public wikis, issue trackers, or anonymous access, which can leak sensitive data
- monitor administrative settings and maintain a change log for traceability
- configure notifications for high-impact actions like the creation of new administrator accounts, disabling of MFA, or modification of repository visibility. Such alerts may provide entities with early detection of insider threats or compromise attempts.
For externally hosted and managed repositories, consider imposing a requirement of entity use to be performing independent third-party security assessments that demonstrates effective security controls. Consider:
- ongoing vendor management, including reviewing the provider’s security certifications (such as system and organisation controls [SOC] 2 or ISO 27001)
- any breach history
- incident response practices.
Also consider using repository scanning tools to identify vulnerabilities. Periodically review the security posture of externally managed vendor repositories. Consider changes in their policies, infrastructure, compliance, security incidents and events. Review available independent assessment on the security of the repository in use, to ensure continued alignment with the entity’s internal standards. Finally, implement guidance that describes how to harden the code repository that your team adopts.
The use of authentication and authorisation protocols such as OAuth 2.0, OpenID Connect, and security assertion markup language (SAML) is essential to ensure that software systems that are designed to communicate with each other can do so effectively and safely. Inherent to the operation of these protocols is the use of 'secret credentials' such as API keys, OAuth tokens, and database connection strings, to verify identity and authorise access. Developers may store these credentials within code in the:
- repository
- configuration files
- API definitions
- infrastructure templates.
These credentials must be protected to prevent unauthorised access and exposure.
Some software developers will insert the secret credentials directly into source code. This practice, which is termed hard coding the credentials, is a highly risky practice. You should avoid this. Instead, consider using a separate secrets management tool (sometimes termed a vault) to securely store and manage credentials. Some of these tools inject secret credentials into an application only during runtime rather than being hard-coded and stored in your repository. These tools often offer features such as automatic credential rotation, audit trails, and role-based access control. As described above, use of PAM systems can further restrict access to sensitive credentials.
Regularly scan your repositories using code repository scanning tools, for example GitHub Secret Protection, to:
- detect exposed secrets
- enable internal repository secrets scanning and blocking utilities.
Configuring automated tooling will reduce the likelihood of credential leaks and help to eliminate manual checking effort.
A security objective should be to minimise the impact if a secret is compromised. Provide pipelines and services with dynamic, short-lived tokens instead of static keys. This minimises the duration of exposure if a secret credential is compromised. When an accidental credential exposure occurs:
- rotate the exposed credential immediately
- then revoke the credentials that are believed to have been compromised.
Developers should be trained, and authorised, to respond to compromise quickly. Incorporate this response process into the entity’s incident-handling plan.
Repository monitoring and auditing is important to achieve early detection of suspicious activity. Enable detailed audit logging on your repository platform to track actions such as logins, permission changes, and direct pushes to protected branches. If your entity operates a security operations centre, these logs could be forwarded to the entity’s SIEM for centralised analysis and real-time alerts.
After the logs are being collected and stored into a secure repository:
- monitor for indicators of compromise such as a sudden spike in clone operations or a high number of failed login attempts
- configure alerts for high-impact events, including the creation of new administrator accounts or disabling of security controls
- monitor other events such as token creation, repository visibility changes, force pushes, and edits to important automation scripts like Github Actions
- periodically review logs to identify trends and detect intrusions
- combine automated detection with scheduled manual audits for a thorough approach.
Correlation and analysis of logs, plus quick notification of discovered suspicious events, enables your security team to investigate and respond quickly. Pair these alerts with a well-defined incident response plan so your team can react quickly to suspicious events like unauthorised commits or large-scale cloning of repositories.
Repositories contain an entity’s intellectual property and represent significant investment. So, protect repositories against both cyberattacks and accidental loss. The following activities should be performed by the entity, or by the repository service and then verified by the entity:
- maintain regular, encrypted backups of all repositories, including configuration data and access control lists - this ensures that an entity can quickly recover from incidents and maintain business continuity
- implement versioned backups so it is possible to roll back to a clean state if a compromise or accidental deletion occurs
- use immutable or write-once storage to protect backups from ransomware attacks
- ensure that backup processes themselves are secured with strong access controls and encryption in transit and at rest to prevent unauthorised access to entity source code
- ideally, entities should store backups in geographically redundant locations and test restoration procedures to ensure they work during an emergency.
Protect your repository and build process from vulnerabilities and supply-chain risks introduced through third-party code. Modern software often relies heavily on open-source libraries and external dependencies. These could contain known vulnerabilities or malicious modifications.
Consider the following actions:
- apply dependency scanning and software composition analysis (SCA) tools to identify vulnerable third-party libraries within the repository
- enforce signed or verified packages to ensure source authenticity and protect against software supply-chain attacks
- configure automated static application security testing and dynamic application security testing (DAST) as mandatory steps in the software CI/CD development and delivery pipeline to detect vulnerabilities before code is merged
- develop processes for peer review and code scanning for pull requests
- combine automated checks with human oversight, so no developer can introduce code to protected branches without scrutiny
- integrate automated policy enforcement tools to enforce these requirements consistently.
Secure the pipeline
Modern software development teams often leverage continuous integration (CI), and continuous delivery and deployment (CD), practices to streamline their software build, test, and release processes. These CI/CD approaches allow small, frequent, code submissions from team members. The submissions can automatically trigger the:
- software build process
- continuous testing,
- automated deployments, to either development, staging, or production environments.
The intent is to achieve an automated software development and delivery process that minimises manual intervention and promotes rapid fully tested production releases.
The security of the CI/CD 'pipeline' is critical to protect the:
- integrity of the developed code
- applications and systems that are then built and delivered.
Technical weaknesses in this pipeline can be used by a cyber adversary to steal code, and introduce malicious code, via the:
- unauthorised modification of the code
- configuration passing through the pipeline.
This may result in security vulnerabilities being covertly introduced into the delivered product. Consequently, it is important that Queensland Government entities secure their software build and development pipelines. This section contains guidance for securing both the CI/CD platforms. But, it can also be helpful for other means of software development and delivery.
The security of the build and deployment pipeline begins with the devices where code is created and traverses. If these devices are compromised, malicious code and other vulnerabilities can be introduced into the pipeline. Developers should be provided with separate dedicated developer workstations. Ideally, they should be physical, or at least virtual. These developer workstations should only:
- contain the tools and resources required for the purposes of software development and delivery
- be connected to a separate segmented development environment.
They should not have access to the entity’s wider IT network or systems, including standard user services such as email and the entity’s enterprise resource planning (ERP) system.
Developer devices and environments should be able to be easily rebuilt. Should abnormal activity be suspected, or malware be identified, the workstations can then be quickly wiped and redeployed. Naturally, this practice assumes that all produced code is being stored in another repository (not on the workstation) so that wiping the workstation will not result in lost development effort.
A compromised pipeline undermines the entire software lifecycle, as attackers can:
- tamper with code
- bypass security measures
- inject vulnerabilities.
To establish trust and ensure integrity, verify the pipeline and its underlying infrastructure is built, configured, and administered securely. Ensure that only authorised users and services can modify or trigger pipeline workflows.
Ensure that every piece of code, and other build artifact, is authentic and correctly sourced. Consider using cryptographic signing and verification of code and builds. This provides an additional layer of assurance that code has not been tampered with during transit. For example, signing artefacts, preferably using automated processes, at every stage of the pipeline ensures that only authentic, untampered, code progresses to production.
Adopt ephemeral, isolated CI/CD 'runners' to execute the steps in your CI/CD workflows, such as:
- building and deploying software (including IaC)
- performing security testing.
Self-hosted ephemeral runners are created on demand, destroy themselves after the specified task(s) are finished. So, they remove persistence. This impedes adversaries from introducing malicious software that remain hidden between jobs.
The integrity of the pipeline depends on its controls being followed in the correct order. If stages like testing, approvals, or security checks, can be skipped or reordered, the pipeline’s effectiveness may be compromised. To enforce this, consider architecting the pipeline process to ensure immutability. Each stage must be completed before progressing. Cryptographic signing at each stage can also be used to verify that processes like testing or peer reviews have occurred as intended. This prevents developers or attackers from bypassing critical controls. Therefore, it maintains the integrity and reliability of the pipeline.
Peer reviews serve as a critical quality control mechanism for catching:
- vulnerabilities
- errors
- misconfigurations.
This applies not only to application code but also to IaC and configuration files. They might inadvertently expose sensitive data or open attack vectors. Terraform configuration files and Kubernetes manifests should undergo review to ensure they specify secure defaults, such as:
- using encrypted storage
- restricting network access.
Consider requiring peer reviews by multiple team members, including logging the activity and its results. This ensures that all changes are scrutinised, and reviewer identity is also logged. In addition, no pipeline should have broad cloud or GitHub administrator rights built in. These activities provide accountability and reduce the likelihood that vulnerabilities will reach production.
Third-party libraries are a common source of vulnerabilities as they may contain outdated or insecure code. Consider the following activities to manage risk:
- Be aware of typo-squatting or URL hijacking risks when importing libraries to ensure that the intended library is indeed imported rather than an attacker-controlled 'twin'.
- Ensure that libraries are sourced from legitimate repositories and continuously monitored for vulnerabilities.
- Maintain a repository of software bill of materials (SBOM) and vulnerability exploitability eXchange (VEX) artefacts to allow tracking of all dependencies and their versions, and to enable quick identification of vulnerabilities when updates are released.
- Consider automating SBOM generation as part of your entity’s pipeline to ensure that your application’s components are always current, and their source is known.
These activities:
- promote supply chain transparency
- reduce the risk of introducing vulnerabilities through third-party code.
Prevent unauthorised access to pipeline credentials and environment secrets. Secrets such as API keys, passwords, and cryptographic keys, are critical to operating the pipeline. But, they represent significant risks if mishandled. Exposing these secrets, accidentally or otherwise, can allow attackers to gain access to sensitive systems. To mitigate this, an entity can employ secrets management tools to:
- securely store and inject secrets into the pipeline only where and when required
- automate their rotation.
Limit access to pipeline secrets and sensitive data using role-based access controls. This ensures that only authorised processes or users can access them.
Fully automated pipelines, while efficient, can be risky if critical security controls are insufficient. Introducing manual approval steps before production release provides an additional layer of oversight. For instance, deployments could require sign-off from a security lead after passing automated tests. These approval processes function as security checkpoints. This ensures that human judgment complements automation.
Apply continuous security testing
Security testing is fundamental to ensure that software and systems function as intended while defending against weaknesses and vulnerabilities. This requires a continuous, software lifecycle testing approach that:
- starts early during development
- evolves as the software matures.
By integrating security testing into every stage of the software development lifecycle, you can:
- catch vulnerabilities early
- reduce risks
- maintain your entity’s confidence in your solution’s security.
Security testing is most effective when it aligns with the cadence of the complete software development lifecycle through the entire life of the solution (from solution design to decommission). This alignment ensures that security is a natural part of the workflow rather than an afterthought.
Incorporating unit tests, system tests, and end-to-end security tests, throughout development ensures vulnerabilities are addressed early and iteratively. Continuous integration pipelines provide an ideal framework for embedding and automating these tests. These tests could be run 'in-line', which block deployment until tests pass. Alternatively, the tests could be run in parallel with development activity, with the goal to avoid slowing down the pipeline while still identifying security defects.
Your entity may consider adopting practices from test-driven development (TDD). TDD requires that key security tests are considered before the code is written. This approach aims to ensure that the code meets security requirements. Security testing can also be aligned with the Australian Government's Secure by design practice. The practice requires cyber threats to be considered from the outset to enable mitigations through:
- thoughtful design
- architecture
- security measures.
The scope of security testing can then be assessed to ensure coverage of the potential threats.
Maintaining awareness of your testing coverage helps to ensure that no part of a solution is overlooked. Not all code may be equally tested, particularly in large or complex systems. For instance, legacy modules or low-traffic components might lack adequate security tests. By tracking which areas of your codebase are covered, and which are not, you can prioritise resources and systematically close gaps in your security posture. The use of automated regression testing ensures that previously fixed vulnerabilities do not reappear in subsequent releases.
Tailoring security tests to your specific application is a best practice that ensures your testing efforts are both effective and efficient. Off-the-shelf testing tools can be useful. However, they often do not account for the unique architecture, functionality, and risk profile of your entity’s solutions. For instance, an application with complex data flows may need custom tests to validate how sensitive information is managed. By leveraging your existing build and release processes to include targeted tests, you can systematically address the most critical vulnerabilities in your application. Over time, these tailored tests can be refined and expanded as your team gains experience. This ensures that they remain relevant as your entity’s solution evolves.
Automated security testing provides repeatable, scalable, and efficient mechanisms for identifying vulnerabilities and security defects. This allows for vulnerabilities to be identified and resolved earlier in the development lifecycle when remediation is the least expensive.
Techniques like static application security testing can analyse source code on every commit to catch hygiene issues such as:
- unvalidated inputs
- misconfigured settings.
Dynamic application security testing (DAST) can be used in integration and staging environments to detect vulnerabilities in running applications. DAST can simulate real-world attacks on running systems, such as fuzz-testing software inputs, in real time to identify unexpected behaviours.
Automated tools are excellent for:
- detecting known vulnerabilities
- reducing the burden of mundane tasks.
However, traditionally, these tools often struggle with complex, system-specific issues, like architecture flaws, or the most sophisticated attack vectors, that may require human intuition and creativity. Consequently, manual security testing by security-knowledgeable professionals is typically still required. For example, penetration testers can explore unexpected interactions between system components that automated scanners might overlook. Focus on high-risk areas and avoid duplicating work already covered by automated tests to make the best use of specialist expertise.
An entity should consider the following actions:
- employ automated testing that forces compliance with leading standards, for example the OWASP application security verification standard (ASVS), to ensure that tests are comprehensive and aligned with industry best practices
- include the scanning of containers and IaC, platforms such as Docker, Kubernetes, Terraform, AWS CloudFormation, to ensure safe images and to identify IaC misconfigurations early
- regularly re-evaluate and refine the test suite to identify gaps or ineffective tests
- use a baseline mode when applying automated testing to existing code to avoid overwhelming developers with historical findings
- assess emerging AI-based vulnerability detection and defect remediation solutions.
At time of writing, recent industry reports suggest that emerging AI or large language model (LLM)-enabled software vulnerability analysis solutions can be very effective at discovering and rectifying cyber vulnerabilities. Some of these solutions are comprised of specialised agents with dedicated capability in either discovering, validating, prioritising and remediating software defects. If your entity chooses to experiment with these solutions, please consider assessing the AI-related risks using the Foundational artificial intelligence risk assessment framework (FAIRA) framework or contact the Cyber Security Unit’s Architecture Team for guidance at cybersecurityunit@cyber.qld.gov.au.
Validating tests is important to maintain an effective security posture. In a controlled environment, deliberately introduce carefully selected vulnerabilities to verify that the tests can detect them. For example, one could introduce an input validation error to ensure that your static application security testing tool properly identifies it. This process helps:
- identify false negatives and where vulnerabilities go undetected
- ensures that tests provide accurate and reliable feedback.
When a security vulnerability is identified, it is important to create a new test to identify the defect should it reoccur. For example, if your team discovers that a particular API endpoint is susceptible to injection attacks, creating a test ensures that any future changes will be automatically checked for the same vulnerability. This practice not only prevents regression but also serves as documentation of the issue for future reference. The test should also be incorporated to apply to other APIs as well.
As system development progresses, testing processes must by modified to adapt. Tests that frequently fail or produce false positives:
- undermine trust in the testing process
- can lead to critical issues being ignored.
For example, if a test repeatedly flags a harmless configuration as a vulnerability, developers may begin dismissing all test results without proper review. It is important to correct such tests or remove them entirely if they are no longer relevant. Naturally, you must first confirm that a failed test is not highlighting a legitimate issue before correcting or removing it. Regularly reviewing and updating your tests ensures they remain aligned with your system’s current state and security requirements.
Building internal security skills is an investment that pays dividends. It:
- reduces reliance on external specialists
- fosters an internal culture of security awareness.
Developers and testers can be trained to identify vulnerabilities and write security-focused unit tests, much like traditional functional unit tests. For example, a developer who understands common attack vectors like SQL injection can proactively write code to avoid this problem and build the tests to confirm detection. Empowering development and testing teams with these skills:
- shows that the entity supports their career growth
- ensures that security becomes an integral part of the development process rather than a specialised, siloed activity.
Transparency in security testing is vital to foster a culture of collaboration and accountability. Developers need to see and understand the results of security tests to respond effectively to the detection of defects and to learn from them. For instance, integrating test results into team dashboards or collaboration tools enable developers to quickly assess, and act on, findings. Producing visual displays, such as graphs showing trends in vulnerabilities over time, can also:
- reinforce the importance of security testing
- motivate teams to maintain high standards.
Reporting the results in an appropriate form for entity management to consume can also show the return gained from the investment in security testing and training.
Plan for security defects
Some computer software is designed for use in highly critical environments where there is little or no tolerance for defects. This includes those defects with significant security implications. Some examples would include surgically implanted pacemakers, nuclear powerplant operation, and avionics applications. In these scenarios, an enormous quantity of resources is invested to extensively test the software to attempt to ensure that the software is defect free. However, in typical business applications, the cost to perform the same level of testing is typically considered to be economically infeasible due to perceived lower consequences resulting from a defect. Consequently, it is nearly inevitable that defects, including those with security implications, will exist in an entity’s business applications. They may only be discovered well after deployment.
Acknowledging the inevitability of security defects being identified, even if well after deployment, encourages an entity to adopt an approach intended to track, and remediate, vulnerabilities whenever required. By implementing vulnerability management practices and maintaining a record of design decisions that adversely impact security posture, entities can minimise cyber security risks while maintaining agility and cost efficiency in their software development and delivery. This section describes how an entity can effectively plan for inevitable security defects.
Effective vulnerability management is an important practice in the secure software development and delivery lifecycle. Vulnerability management involves continuously identifying, assessing, prioritising, and remediating, vulnerabilities across the entire software stack. This includes third-party components like libraries and other vendor-provided software components. Therefore, vulnerability management practices should cover both in-house applications and externally sourced software. For widely used software and hardware, patching and remediation should leverage, and be integrated into, your entity’s routing software maintenance strategy to address known issues, such as weak configurations or unpatched vulnerabilities, as a matter of general IT operations.
A current and complete software bill of materials (SBOM) repository can play a key role in vulnerability management by maintaining a detailed inventory of all the components, libraries, and dependencies, that comprise your entity’s software. A SBOM management system can compare the entity’s inventory to new vulnerability reports to quickly identify impacted systems. For example, if a critical vulnerability is discovered in a widely used library like OpenSSL, a SBOM repository can enable teams to:
- rapidly pinpoint which of the entity’s solutions are affected
- prioritise remediation efforts based on risk levels.
Security debt arises when an entity makes the decision to subordinate cyber security concerns to address more pressing entity business priorities, such as:
- meeting business objectives or delivery deadlines
- addressing risks perceived as more serious.
For example, during the development of a minimum viable product (MVP), developers might grant overly broad permissions or skip input validation to save time. While these decisions may expedite delivery, this introduce risks that need to be documented and addressed later.
Maintaining a register of security debt enables teams to systematically:
- track these risks
- prioritise their resolution.
The security debt register provides context for why the decision was made and how it should be resolved. This register should document:
- the nature of each decision
- its rationale
- its potential impact on the solution, and therefore the entity’s security profile.
Project management tools, enterprise risk management tools, and even IT service management tools, can be used to track security debt. This ensures that the debt itself, and the remediation actions necessary to discharge the debt, and who is accountable to ensure resolution, remain visible and actionable.
This register should be periodically presented to the appropriate executive for formal approval as part of regular reporting to ensure adequate management attention and oversight. This structured approach ensures that security debt does not accumulate unchecked. This:
- reduces long-term risks
- improves the maintainability of the software.
Addressing individual vulnerabilities is important. However, focusing solely on symptoms can lead to a reactive inconsistent approach to security defect remediation. Using analysis methods like fault tree analysis, failure mode and effects or root cause analysis, and using these after incidents, near-misses, and in testing findings, allows an entity to identify and address the underlying issues that lead to vulnerabilities. This could involve:
- tracing a defect back to the point where it was introduced in the development lifecycle
- identifying systemic weaknesses in coding practices, tools, or processes.
For example, one of these analysis methods might reveal that a recurring vulnerability, such as insecure deserialisation, is caused by the exploitation of one specific library or framework. By addressing the root cause, such as updating the library or implementing stricter input validation, an entity can address an entire class of vulnerabilities. These analysis methods should inform vulnerability management and development processes to enable teams to adapt their tools and practices to prevent similar issues in the future. This iterative approach strengthens the entity’s security posture over time.
External users, researchers, and ethical hackers can provide valuable security insights by identifying vulnerabilities that internal teams may overlook. Establishing a responsible disclosure process for your entity allows these helpful individuals to report security concerns to your entity in a structured and secure manner. For example, entities should publish a `security.txt` file on their entity’s external website with contact details and guidelines for reporting vulnerabilities to the entity. The presence of this file ensures that external security researchers can find out:
- how to engage the entity
- what to expect during the disclosure process.
Entities can also implement 'bug bounty' programs to incentivise responsible reporting of security defects. Once a vulnerability is disclosed, it should be integrated into the entity’s vulnerability management and requirements management processes to prioritise and remediate. By encouraging responsible disclosure, an entity can address security defects before they are exploited by malicious actors. This transforms potential risks into opportunities for improvement.
Some bug bounty programs provide those individuals who identify, then properly report, security defects with financial renumeration. However, programs can also be successful that acknowledge the contribution made by the individual in ways other than financial reward. For example, the acknowledgement can be made:
- by recognition posted on a public website
- via the provision of an entity-issued certificate that acknowledges an individual’s contribution to improving cyber security.
The individual can then use this certificate to demonstrate cyber competency and professional ethics, for example as part of an employment application.
References and further reading
This guidance is structured to generally align with the major topics appearing in the software development and deployment guidance available from the UK National Cyber Security Centre (see Secure development and deployment guidance). However, the guidance has also been updated and augmented using many other sources, including some of the references below. These references provide additional perspectives on how to implement secure software development and delivery within your Queensland Government entity.
- ASD Guidelines for software development
- NCSC Software security code of practice – implementation guidance
- Business Software Alliance (BSA) framework for secure software 1.1
- ISO/IEC 27002 Information security, cybersecurity and privacy protection — Information security controls, sections 8.25 – 8.33
- NIST SP800-218 secure software development framework (SSDF) version 1.1: recommendations for mitigating the risk of software vulnerabilities
- NIST SP800-204 security strategies for microservices-based application systems
- OWASP Application security verification standard (ASVS) 5.0
- OWASP Software assurance maturity model (SAMM) 2.0
- OWASP Software component verification standard (OCVS) 1.0
- Choosing secure and verifiable technologies
- ASD Safe software deployment: how software manufacturers can ensure reliability for customers
- NIST SP 800-218 Secure software development framework (SSDF) Version 1.1: recommendations for mitigating the risk of software vulnerabilities
- Software Engineering Institute Computer Emergency Response Team (SEI CERT) coding standards
- OWASP development guide
- ASD Updated guidance on the 2026 minimum elements for a software bill of materials