# Website threat model

## Assets and actors

Assets are claim accuracy, historical source integrity, reviewed public evidence, the dependency lockfile, generated website output, and publication authority. Readers must distinguish historical observations from present cloud status. Contributors can propose prose, JSON, MDX, dependencies, scripts, or workflow changes; maintainers can approve and publish; a compromised dependency or action can alter a build. Attackers may aim to leak operational information, inject malicious content, falsify evidence, or misuse deployment credentials.

The website is published as public static output through native Cloudflare Pages Free at `https://security.devsatym.xyz`, with `https://gcp-security-handbook.pages.dev` as its assigned Pages address. It has no authentication backend, cloud API integration, or demo-cluster access. The GCP system's Cosign, Kyverno, and Falco controls do not apply to the website build. Publication authority comes from the separately authorized Cloudflare account and selected-repository GitHub App integration; the historical GitHub Pages OIDC publication workflow is not the active deployment path.

Source lives in the separate private repository `devSatym/gcp-security-handbook`. Its access controls protect repository contents, while production and native preview output are public. Do not treat a private source repository as permission to include sensitive data in the publishable artifact. Preview `noindex` headers, metadata and robots rules control indexing rather than access. The owner authorized Cloudflare publication with the existing approved assets; actual project, domain and hosted-check observations are recorded separately in the deployment runbook and excluded audit receipts.

## Trust boundaries

| Boundary | Threat | Implemented treatment | Residual risk |
| --- | --- | --- | --- |
| Contribution → build | MDX import/code or package script execution | Treat MDX as code; review diffs and native build inputs; GitHub validation has read-only repository permissions | Native branch previews also execute build inputs; build runner/network remain exposed to dependency behavior |
| Baseline source → claims | Revision blending, copied inaccurate comments | Full-SHA manifest/source URLs, source hashes, source review | Human interpretation can still overclaim |
| Original evidence → public asset | Secret/personal metadata disclosure or misleading cropping | Visually reviewed, owner-approved fourteen unchanged originals; hashes, provenance and retained-metadata notes; separate approval for later derivatives | Approved originals retain disclosed terminal/account metadata; automated checks cannot prove absence of all sensitive information |
| Internal engineering → public output | Raw logs/state/ledger accidentally copied | Explicit report/assets allowlist; publication audit | A sanitized report can still contain an overlooked disclosure |
| Build → deployment | Artifact substitution or unnecessary privilege | Native Pages uses selected private repository, `main` production branch, root `website`, checked build wrapper and `dist` output; compare actual hosted output separately | Cloudflare account, GitHub App or maintainer compromise remains authoritative; native publication does not wait for GitHub validation |
| Browser interaction → reader | Script injection or external link confusion | Astro escaped text, controlled trusted content, no third-party analytics | Trusted MDX can deliberately emit unsafe markup if review fails |
| Dependency update → build | Supply-chain compromise or breaking change | Pinned direct versions, committed lockfile, clean install/audits | Locking records a dependency; it does not establish its safety |

## MDX and contributor execution

Markdown text is content, but MDX can import and run JavaScript during rendering. A contributor changing `.mdx`, `astro.config.mjs`, package scripts, or build tooling changes the executable build boundary. There is no sandbox claim for MDX. Native previews execute the matching branch's build inputs, so review executable contributions and avoid storing unnecessary sensitive values in either build environment. Production publication must build an intended reviewed revision; a PR validation result does not itself establish a successful deployment. Do not use `pull_request_target` with checkout/execution of untrusted PR content.

## CI and publication privileges

GitHub validation jobs require contents read, install locked dependencies, perform local checks, and receive no cloud credentials. `docs-validate.yml` runs for relevant pull requests and relevant pushes to `main`; an arbitrary branch push alone does not trigger that workflow. Its checks are independent of native Cloudflare builds and are not an automatic publication gate. Review the preview and passing checks before merging into `main`. Avoid adding repository-write or security-workflow tokens merely for documentation generation.

The Cloudflare Workers & Pages GitHub App has selected-repository access to the private handbook. Native Pages builds relevant `main` changes for production and qualifying non-main branches for previews, using root `website`, `npm run build:cloudflare` and output `dist`. The wrapper checks content, code and output before upload; it does not run Playwright or wait for GitHub CI. Production uses the verified custom origin; native previews use `CF_PAGES_URL`. This provider-managed Git integration does not require a Google/Azure service account or a stored deployment token in the handbook workflow.

The unused manual `docs-pages.yml` remains a historical GitHub hosting option with a separate read-only build and a publication job using `pages: write` and `id-token: write` bound to the GitHub Pages environment. Its private-repository visibility guard and manual main-only dispatch do not describe current Cloudflare publication. The GitHub and legacy site profiles are independently built compatibility targets.

The initial implementation phase shared the original source worktree, so its existing application workflow triggers were inspected. The owner then requested a separate private documentation repository, initialized with new history and only documentation workflows. Handbook pushes therefore do not execute the original repository's application workflows. Confirm the push destination and private visibility before the authorized documentation push; never push handbook changes into the source project.

## Evidence and secret handling

Never copy Terraform state, kubeconfig, OIDC JWTs, cloud JSON keys, webhooks, credentials, unapproved screenshots, browser storage, or raw environment dumps into `public/`. Publication approval is per evidence asset and per report filename. A source link may reveal a historical project name already public, but that does not authorize publication of account tokens or unrelated personal metadata. The fourteen approved original captures retain explicitly disclosed terminal/account metadata; this does not authorize publishing other private material. Unknown dates/revisions remain null and visibly unknown.

The final report must avoid local filesystem paths and raw diagnostic content in its public derivative. Internal audit artifacts can be retained under `engineering/` without becoming website assets. Directory exclusion and content inspection both matter: a secret can be pasted into an allowed file.

## Availability, accuracy, and remaining risk

Static hosting reduces operational components but depends on Pages/CDN availability and browser search downloads. External pinned source links depend on repository availability. A hash validates a recorded snapshot, not remote settings or live behavior. Search and routing bugs can hide useful evidence without changing its source. Stale content is a security communication risk; review date/baseline plus explicit maintenance reduce ambiguity.

No threat-model step establishes a secure live cloud environment. Residual risks include maintainer compromise, dependency compromise, erroneous reviewed claims, outdated evidence, incomplete redaction, and untested browser combinations. Final audit results document their tested coverage and limitations, rather than declaring the site immune to these threats.


Official action major-version tags remain mutable dependencies; review any resolved action changes before publication. The lockfile fixes npm resolution, not the honesty of dependencies or content. Validation restricts source URLs to HTTPS and the chosen baseline repository, while schema consistency remains separate from source interpretation.

## Domain, identity and complete-gallery update

All fourteen visually reviewed original screenshots are published at the owner’s request and under the later Cloudflare publication authorization. SHA-256 and dimensions bind their exact source bytes; no proposed privacy mask was applied because no optional pixel-redaction choice was selected. Several retain incidental terminal/account metadata, disclosed in their gallery provenance and evidence limitations. Any later display derivative needs separate explicit owner direction and truthful provenance; optional redaction is not an outstanding prerequisite for this authorized publication. Publication checks reject missing display hashes, source mismatches, altered supposedly unchanged bytes, unrelated/orphan assets and unsafe image URLs. They do not inspect every pixel for a secret.

The typed author/project modules hide absent credentials/contact details and avoid live buttons for unverified destinations. Initials avoid a fabricated portrait. Original editorial/social imagery remains distinguishable from execution evidence. Each profile generates its own canonical/social/sitemap/asset paths; no one-artifact/arbitrary-base claim is made. Private source access and public output remain distinct. Native Cloudflare production and previews use their respective origins, and generated private audit paths are excluded from build watches and public output.

The owner added the external-provider CNAME; no agent DNS, nameserver, billing or original-source mutation was made. Domain association, active certificate validation and real HTTPS were observed separately from artifact checks. The saved custom-domain checkpoint records successful native production `9ee2cc16` and preview `652eedba` for source commit `9074b7178158d80e3d321279641a3c967cfbc162`: 170 HTTP checks passed on each origin, with fourteen original PNGs, and production passed 31 hosted browser cases plus ten separate supplemental assertions. Those dated receipts establish that checkpoint, not future deployment health. Subsequent content changes require a fresh matching build and hosted verification.
