We strive for excellence to pursue the best interests of our audience and our colleagues
We are accountable to our audience and work to live up to the trust they place in us
These quotes are taken from the Guardian's values and behaviours. As an organisation we have a low information-security risk appetite. We strive for excellence when protecting the privacy of our reader's data and the integrity of our systems. The security of our applications, infrastructure and data is the highest priority.
You should perform due diligence on your platforms to minimise common vulnerabilities in infrastructure and applications. Some of these vulnerabilities are not possible to fix automatically, so your team should plan to spend time on addressing them on a regular basis.
More detailed guidance is provided in Security HQ's documentation (our central tool for security information.)
We are each responsible for the security of the code we write and staying informed of best practices secure application development. To achieve this you should engage with the security training and recommendations provided internally and be aware of the latest industry guidance. There are lots of good resources online, for example:
- OWASP Security by Design Principles
- The OWASP Top 10
- The Basics of Web Application Security
- Top 10 Secure Coding Practices
Before building an application think about what (if any) sensitive data is involved. Be particularly aware of any personal user data (including email addresses).
Have a plan for storing sensitive data safely. Make sure the ways that data can be accessed are well understood. How will you ensure the data remains safe?
Limit access to sensitive data. Only people and services that directly depend on the data should be able to access it.
Keep sensitive data to yourself. Keep your team's sensitive data within the team and under your control. Don't share it with other teams, don't store it in cookies and don't let it sit in caches.
Keep data only for as long as it is needed Ensure retention policies are implemented aligned with the requirements set for the type of data you are storing. Use AWS object life-cycle management whenever possible.
Ensure you set the right Cache-Control
for CDN to not cache your
response Using Cache-Control: no-cache
is NOT sufficient, use
Cache-Control: private
for this purpose. See
Cache-control semantics
and
Fastly config
Keep secrets out of repositories. Application secrets must not be stored in version control, even if the repo is "private". To prevent accidental leakage, files containing secrets should be stored away from the project, completely outside the source tree.
Secrets should be rotated regularly. Automate the rotation if possible.
Some non-secrets should still be kept out of the public domain. "Private" information that does not constitute a secret but may make an exploit easier to achieve should be kept in private repositories.
Also see the guidance on github repository contents
Centralised Reporting from AWS services and guidance is available in Security HQ.
Infrastructure should be provisioned via cloudformation using the Guardian CDK library. Many of the following recommendations are encoded as defaults in the library, making their adoption simple.
See the patching guidance below
Do not use permanent AWS credentials. Applications running in AWS
should use assumeRole
to gain access to other AWS resources. For
local development you should use AWS profiles to manage credentials
and these should be temporary credentials (e.g. provided by Janus).
Permanent credentials should be rotated every 365 days. (When they cannot be replaced by temporary credentials.)
Ensure that at least 2 people have IAM logins for each AWS account.
In the event of a VPN or Janus outage this will ensure that teams can
still access their account. These IAM users should have 2FA enabled and no
active access keys. Note that Infosec can also provide access if necessary
but this is much less convenient.
Direct access to production infrastructure should be a last resort. Prefer automating common actions and shipping telemetry data extrernally, which should reduce the need.
Use SSM-Scala for SSH access. SSM-scala is a tool executing commands on EC2 instances authenticated by IAM credentials. The SSM Agent is baked into many of our AMI images and should be preferentially used to permanent keys.
EC2 instances should be run in the private subnet of a VPC. Only the load balancer of an application should reside in the public subnet. For more information see aws documentation on VPCs.
Be aware instances in private subnets that make calls to the internet will require a NAT gateway, and incur associated costs.
Security Groups egress/ingress rules should be locked down as much as possible. There's no reason to allow open access to any EC2 instances; they should ideally be locked down to the load balancer and nothing else.
Port 22 access should be removed everywhere. This is no longer required for SSH access via SSM-scala (see above.)
It is surprisingly easy to accidentally make public an S3 bucket or object public. There are a number of ways of controlling access, all of which must be correctly configured to keep private objects private.
Prefer single logical purpose buckets, either public or private. Mixing concerns makes it more complicated to configure access and easier to get it wrong.
Prefer bucket-level policies to control access. Object-level access control is generally not recommended due to the extra risk its complexity brings.
Avoid deleting buckets. Prefer emptying the bucket and creating a single file indicating its archived status e.g. a README. This helps to prevent issues such as subdomain takeover when buckets are used as static websites and the subdomain routing is leftover. (S3 bucket names are global to all customers)
For non-public buckets block all public access.
Enable encryption by default and encrypt private data.
Consider setting object lifecycle rules to remove old data. Bucket versioning is also a useful setting to enable for some use cases.
All running EC2 instance AMIs should be less than 30 days old. The refreshing of AMIs can and should be automated with a combination of Amigo, scheduled deploys and the AMI cloudformation parameter deploy type.
Use current LTS versions for image/container OS. E.g. Avoid Amigo base images that are end of life.
Integrate a vulnerability scanning tool and patch vulnerabilities as fixes become available. More guidance can be found on Security HQ.
All endpoints should be served over HTTPS. Use HSTS to enforce it. More broadly, no plain text protocol services should be exposed externally (not just HTTP, but also FTP etc.)
Disk encryption. All machines that you do work on must have disk encryption enabled.
2FA. Whenever a service offers 2FA, you should enable it.
Use a password manager. Don't reuse simple passwords across
services. A password manager is a good way to help use strong
passwords. The pwgen
command can be used to generate good passwords,
especially with the -s
and -y
flags (pwgen -sy <length>
).