Software Development Security Practices
We follow secure development practices aligned with ISO/IEC 27001/27002 across our backend services and HubSpot CMS deployments. All changes go through controlled GitHub workflows with SSO, code reviews, CI checks, and vulnerability scanning. Customer data is processed transiently and never stored. Secrets are managed through GCP Secret Manager and MyGlue and are not committed to source control. We use Sentry, GCP logging, and IAM-based access control for monitoring and governance. Identified risks, such as static service account keys and limited CMS automation, are acknowledged, with clear improvement plans in place.
Current Security Practices
Purpose
This document describes our software development security practices, aligned to relevant ISO/IEC 27001 and 27002 controls. It covers our Python `FastAPI` services deployed to GCP `Cloud Run` and our CMS team’s web assets deployed to HubSpot. It reflects the current state and identified improvements. Intended for auditor review and due diligence.
Organisational and Technical Scope
- Applications
- Backend services: Python `FastAPI` microservices - - CMS/web: HTML/CSS/JavaScript assets and templates for HubSpot
- Source control: GitHub (SSO enforced)
- CI/CD
- Backend: GitHub Actions deploying to GCP - - CMS: GitHub-based workflow deploying to HubSpot
- Runtime/Hosting
- Backend: GCP `Cloud Run`, images in `Artifact Registry` - - CMS: HubSpot CMS (SaaS)
- Secrets: `GCP Secret Manager` (deploy-time) and `MyGlue Secret Config` (runtime)
- Observability: Sentry (alerts to Slack and email)
- Environments: Separate GCP projects for `staging` and `prod` aligned to `staging`/`main` branches
- Cryptography: Google-managed keys for encryption at rest (CMEK not required)
- Data handling: No persistent storage of customer data; processing is transient in memory
Roles and Responsibilities
|
Role |
Responsibility |
|
Developers |
Implement secure code, write tests, participate in code reviews, remediate vulnerabilities |
|
CMS Developers |
Implement secure HTML/CSS/JS, follow content security practices, reviews prior to publish |
|
Tech Lead/Reviewer |
Enforce coding/security standards, review PRs, approve changes |
|
DevOps/Platform |
CI/CD security, GitHub↔GCP integration, IAM, secrets management, runtime configuration |
|
Security/ISO function |
Maintain policies and risk register, advise on control selection, coordinate incident handling |
Secure SDLC
- Requirements and Design
- Security requirements considered during planning (authentication/authorisation, external exposure, data handling)
- Lightweight threat assessment performed for material changes (e.g., new third‑party integrations or network exposures) - Implementation
- Backend: Python/FastAPI coding standards
- CMS: Front-end security guidelines (see CMS Secure Practices)
- Secrets are not embedded in code or config; retrieved from managed secret systems - Verification
- All changes proceed via pull requests with required code
- Backend CI: linting/testing/coverage; `pip-audit` fails on High/Critical vulnerabilities
- CMS CI: currently no automated linting/testing (see Improvement Plan) - Release
- Backend: Build container images in CI and deploy to `Cloud Run`
- CMS: Deploy web assets/templates to HubSpot via pipeline
- Backend CI auth uses static GCP service account keys stored in the repository (see Risk and Improvements) - Operations and Monitoring
- Sentry alerts are delivered to Slack and email; payloads are redacted and retained for 90 days
- GCP logging/monitoring are available as needed for platform observability
Source Control and Branch Protection
- All changes are made via pull requests; direct pushes to protected branches are restricted
- Branch protection is enforced on `staging` and `main` with required code reviews and passing linting/testing/coverage checks
- SSO is enforced for GitHub organisation access
Dependency, SAST, and Supply Chain Security
- Dependencies are pinned in `requirements.txt`
- `pip-audit` runs in CI and fails on High/Critical vulnerabilities
- Static application security testing: `bandit` is not currently in use (see Improvements)
- Build provenance and SBOM generation are not yet implemented (see Improvements)
Secure Coding Standards – Backend (Python/FastAPI)
- Input validation/serialisation: `pydantic` models; avoid unsafe deserialisation (e.g., `pickle`) for untrusted data
- Authentication/Authorisation: Implemented at application endpoints; least privilege and route-level checks where applicable
- Error handling: User responses avoid leaking stack traces; detailed errors are logged server-side
- Logging: Structured logs without sensitive data (tokens, secrets, PII). Use request correlation IDs where feasible
- Secrets handling: Retrieved from `Secret Manager` (deploy) and `MyGlue Secret Config` (runtime); never committed to source; not logged
- Cryptography: Standard libraries (e.g., `cryptography`) with modern algorithms; encryption at rest relies on Google-managed keys
- HTTP security: HTTPS enforced by platform; security headers and rate-limiting/WAF can be layered as needed
CMS Secure Development Practices (HubSpot)
- Technologies: HTML, CSS, JavaScript; deployed to HubSpot CMS
- Authentication/authorisation: Managed by application endpoints or HubSpot when applicable
- Front-end security controls
- Avoid inline event handlers where possible; prefer unobtrusive JS
- Sanitise and escape dynamic content to prevent XSS
- Use `rel="noopener noreferrer"` for external links when targeting new windows
- Prefer `https:` for all external assets; Subresource Integrity (SRI) for third‑party scripts when supported
- Set security headers via HubSpot or edge/CDN where configurable (CSP, X-Content-Type-Options, etc.) - Testing and validation
- Due to CMS deployment constraints, automated unit tests are not currently feasible
- Manual review is required prior to publish
- Automated linters/validators are not yet in the pipeline (see Improvements)
CI/CD Security (GitHub Actions to GCP and HubSpot)
- Backend
- GitHub Actions builds and deploys to `Cloud Run`
- Authentication uses static GCP service account keys stored in the Git repository; keys not currently rotated - CMS
- GitHub-based workflow deploys to HubSpot
- No automated linting or tests; deploy relies on peer review and manual verification - Risk Statement (backend)
- Long‑lived credentials in a repository pose elevated risk of unauthorised access and are difficult to fully eradicate from history - Compensating Controls
- Branch protection and review gates reduce the chance of unauthorised changes
- SSO enforced for repository access
Container and Runtime Security (Cloud Run)
- Services are public; authentication/authorisation is managed by the application endpoints
- TLS in transit is enforced by Cloud Run; encryption at rest uses Google‑managed keys
- Image signing (`cosign`) and Binary Authorisation are not currently in use (see Improvements)
- Secrets are consumed from `GCP Secret Manager` and `MyGlue Secret Config`; environment variables are minimised
HubSpot Platform Security Considerations (CMS)
- Hosting and runtime provided by HubSpot (SaaS); customer code executes client-side
- Access to HubSpot is restricted via enterprise identity and platform permissions
- API keys/tokens for HubSpot integrations managed via HubSpot’s secret mechanisms; not stored in source
Secrets Management
- `GCP Secret Manager` provides deploy‑time secrets; access is controlled by IAM in each environment/project
- `MyGlue Secret Config` provides runtime secrets; it supports update‑only semantics and no read for customer‑managed secrets, reducing exfiltration risk
- Secrets are never stored in source control or logs
Data Handling and Privacy
- Customer data is processed transiently in memory only; no customer data is persisted or backed up by services
- As a result, traditional data retention and customer‑data backup controls are not applicable
- Operational and security logs are retained per platform policy; Sentry retains redacted payloads for 90 days
Logging, Monitoring, and Alerting
- Sentry captures application errors and performance events; alerts route to Slack and email
- Sensitive fields in Sentry payloads are redacted; retention is 90 days
- GCP `Cloud Logging`/`Monitoring` are available for platform signals; Security Command Center can be enabled depending on scope
Access Control
- GitHub and GCP access require SSO
- Separate GCP projects for `staging` and `prod`; IAM follows least‑privilege principles for service accounts and roles per environment
Change and Release Management
- Backend: Changes are tracked via PRs; merges to `main`/`prod` trigger deployments to matching GCP projects
- CMS: Merges to protected branches trigger deploys to HubSpot; manual verification precedes publish
- Emergency fixes can be expedited with follow‑up review
- Releases are tagged; CI retains build and deployment logs
Incident Management
- Alerts originate from Sentry to Slack and email
- No formal on‑call rotation is currently established; incidents are handled by responsible team members on a best‑effort basis
- Post‑incident actions can be tracked in tickets; a formalised incident response plan is identified as an improvement area
Business Continuity and Availability
- Customer data backups/restores are not applicable (no persistent customer data)
- Service availability targets (RTO/RPO) are not currently formalised and may be defined based on business needs
Third‑Party and Open‑Source Management
- Backend: Dependencies tracked via `requirements.txt`; `pip-audit` enforces fail on High/Critical
- CMS: Third‑party front-end libraries (if used) are inventoried; no automated audit currently (see Improvements)
- Third‑party services (Sentry, MyGlue, HubSpot) used with least‑privilege access and redaction controls
Evidence Available on Request
- GitHub branch protection configurations and list of required CI checks (linting/testing/coverage)
- CI logs demonstrating `pip-audit` enforcement and build/test results
- Cloud Run service configuration summaries for `staging` and `prod`
- Secret Manager IAM policies; documentation of `MyGlue Secret Config` update‑only access model
- Sentry alert policies, redaction configuration, and sample (sanitised) notifications
Statement of Applicability (Selected Exclusions/Constraints)
- Customer data retention and backup controls: Not applicable (no persistent customer data)
- Customer data restoration testing: Not applicable (no persistent customer data)
- Customer‑managed encryption keys (CMEK): Not required; Google‑managed keys accepted per risk profile
- CMS automated unit/integration testing: Not currently feasible due to deployment model; reliance on review and automated static checks (see Improvements)
Future Plans
Identified Improvements (Not Yet Scheduled)
- CI/CD authentication and secrets
- Migrate from static GCP service account keys in the repository to GitHub OIDC Workload Identity Federation; remove and invalidate legacy keys - Static application security testing
- Add `bandit` to PR checks - Supply chain integrity
- Generate SBOMs (e.g., `syft`) and attach to releases; consider container image signing with `cosign` and, for production, Binary Authorisation - Runtime hardening for public services
- Evaluate Cloud Armor (WAF/rate limiting) and ensure non‑root, minimal/distroless images, read‑only filesystem, and minimal environment variables - CMS pipeline hardening
- Introduce non-disruptive static checks: `eslint` (JS), `stylelint` (CSS), `htmlhint`/`html-validate` (HTML), link checker (e.g., `lychee`), basic accessibility scan (e.g., `pa11y`)
- Add security linters (e.g., ESLint `eslint-plugin-security`) and dependency checks (`npm audit`/`yarn audit` where applicable)
- Optional pre-deploy preview/review steps using HubSpot staging or private content when feasible
- Document CSP guidance and approved third‑party script list with SRI requirements - Incident response and availability
- Establish a lightweight incident response plan (severities, escalation) and define pragmatic service availability targets as required
Acknowledgements
Risk Acknowledgements
- Static GCP service account keys are currently stored in the repository and not rotated, which increases credential exposure risk. Branch protections, SSO, and CI gates provide partial mitigation; migration to OIDC is identified as a priority improvement.
- Public `Cloud Run` endpoints rely on application‑level authentication/authorisation; additional L7 protections (e.g., WAF) may further reduce risk and are under consideration.
- CMS pipeline lacks automated linting/testing; manual review is in place. Non‑disruptive static checks are identified as a feasible improvement given deployment constraints.