Skip to content

Commit 1bef9a8

Browse files
authored
docs: reflect security posture — TS 6.0, CodeQL hardening, dependency triage (#28)
Additive docs for this session's security work: AGENTS.md stack TS 5.9->6.0 + Security automation subsection; SECURITY.md least-privilege workflow permissions note + new "Dependency security & vulnerability triage" policy (in-range fixes, execution-path triage, dismiss "not used"). No content removed.
1 parent cb17328 commit 1bef9a8

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

AGENTS.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
**astro-gcp-cloudrun-starter** is a production-ready, open-source GitHub template that deploys an **Astro v6 + Tailwind CSS v4** static site to **Google Cloud Run** with a zero-secrets, keyless, Terraform-managed foundation. The front end is derived from the AstroWind theme; the project adds a complete GCP/IaC/CI layer and a 5-phase web-optimization pass (performance, GEO, styling, components, conversion).
66

7-
**Stack:** Astro v6 | Tailwind CSS v4 | TypeScript 5.9 | MDX | Sharp · Docker (nginx:8080) · Google Cloud Run · Terraform · GitHub Actions (keyless WIF)
7+
**Stack:** Astro v6 | Tailwind CSS v4 | TypeScript 6.0 | MDX | Sharp · Docker (nginx:8080) · Google Cloud Run · Terraform · GitHub Actions (keyless WIF)
88

99
**Public-repo rule:** nothing sensitive ever enters files, history, or CI logs. Identity is keyless (Workload Identity Federation, scoped to this repo); only `.example` placeholders are committed. App runtime secrets → Google Secret Manager.
1010

@@ -112,9 +112,17 @@ Hero images use `loading="eager"` and `fetchpriority="high"` (LCP). Non-hero ima
112112
- `.github/workflows/ci.yml` runs on PRs: `npm run check`, Docker build, `terraform validate` (all envs), and a **Lighthouse CI** Core Web Vitals budget.
113113
- `deploy-dev/staging/prod.yml` are **app-deploy-only** (build image → push to Artifact Registry → deploy Cloud Run revision → smoke test). Terraform is run deliberately, not from CI.
114114

115+
### Security automation
116+
117+
Layered, defense-in-depth scanning — full runbook in `SECURITY.md`:
118+
119+
- **Secret scanning**`.github/workflows/secret-scan.yml` (Gitleaks SARIF + TruffleHog `--only-verified`), a Gitleaks pre-commit hook (`.githooks/pre-commit` / `.pre-commit-config.yaml`), and GitHub push protection.
120+
- **Code scanning (SAST)** — CodeQL on every PR; findings surface under **Security → Code scanning**. Keep it clean: workflows declare least-privilege `permissions:` (e.g. `ci.yml` is `contents: read`), and avoid the patterns CodeQL flags (e.g. complete, case-insensitive URL-scheme checks in `src/utils/permalinks.ts`).
121+
- **Dependencies** — Dependabot **version updates** (`.github/dependabot.yml`, weekly grouped: npm / github-actions / docker) plus security updates. See `SECURITY.md` → "Dependency security & vulnerability triage" for how transitive, dev/build-only advisories are assessed (execution-path exposure) and remediated or dismissed.
122+
115123
## Documentation
116124

117-
All guides live in `docs/` and are indexed in `README.md` (deploy/infra + the 5-phase web-optimization docs).
125+
All guides live in `docs/` and are indexed in `README.md` (deploy/infra + the 5-phase web-optimization docs). Security tooling and the dependency/vulnerability response runbook are in `SECURITY.md`.
118126

119127
## Verification Checklist
120128

SECURITY.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ Security**). Current state:
6868
on enablement). Findings appear under **Security → Code scanning**, alongside
6969
the Gitleaks SARIF from Layer 2.
7070
-**Copilot Autofix** — AI-suggested fixes for CodeQL alerts.
71+
-**Least-privilege workflows** — CI workflows declare an explicit
72+
`permissions:` block (e.g. `ci.yml` is `contents: read`) so `GITHUB_TOKEN`
73+
isn't granted broad default scopes. This clears CodeQL's "Workflow does not
74+
contain permissions" alerts and is the standard for any new workflow.
7175
- Check-runs failure threshold: Security = **High or higher**, Standard = **Only
7276
errors**. To _block merges_ on these alerts, create a branch ruleset
7377
(**Settings → Rules**) that requires the code-scanning check.
@@ -87,6 +91,36 @@ Security**). Current state:
8791

8892
> To review or change any of these: **Settings → Advanced Security**.
8993
94+
## Dependency security & vulnerability triage
95+
96+
Dependabot opens **version-update** PRs (weekly, grouped) and **security-update**
97+
PRs. Routine flow: let CI (`npm run check` + Docker build + Lighthouse + CodeQL)
98+
gate each PR, then merge group/patch/minor bumps when green; review majors
99+
(e.g. TypeScript 6.0) deliberately before merging.
100+
101+
Not every alert has a clean fix — especially **transitive, dev/build-only**
102+
packages pinned by a parent (e.g. `esbuild` via `vite`). Triage by **execution
103+
path**, not severity label alone:
104+
105+
1. **Is a non-breaking fix in range?** Prefer it. A locked transitive version can
106+
lag the allowed range — `npm update <pkg>` bumps it without changing
107+
`package.json` (this is how `vite` was moved 7.3.3 → **7.3.5** to fix
108+
CVE-2026-53571, within the existing `^7` override). **Never** take a fix that
109+
force-downgrades a core dep (e.g. `npm audit fix --force` proposing an ancient
110+
`astro`).
111+
2. **Is the vulnerable code actually reachable here?** This ships as a **static
112+
site** — Astro builds HTML in Linux CI, served by **nginx with no Node
113+
runtime**. Advisories that only affect a dev server, a non-npm runtime
114+
(Deno), or an OS we don't build on are **not in the execution path**. If so,
115+
and no in-range fix exists, **dismiss the alert** in **Security → Dependabot
116+
alerts** with reason **"Vulnerable code is not actually used"** and a one-line
117+
justification. Re-evaluate if the dependency later enters a runtime path.
118+
3. **Stale alerts** (the flagged package is no longer in `package-lock.json`)
119+
auto-close on the next dependency-graph scan; dismiss if they linger.
120+
121+
Record non-obvious decisions in the PR or the dismissal note so the rationale is
122+
auditable.
123+
90124
## Allowlist rationale (why the gate isn't noisy)
91125

92126
`.gitleaks.toml` allowlists values that match secret-shaped patterns but are

0 commit comments

Comments
 (0)