docs(security): add SECURITY.md and discoverable disclosure links #192

Open
opened 2026-09-12 13:42:42 +00:00 by PlasticDigits · 1 comment

Summary

The bridge monorepo has no root SECURITY.md and no easy-to-find user disclosure path. CL8Y DEX already ships that surface: root policy, README / docs-index pointers, a structured security-report issue template, and a dApp footer link. Mirror that pattern here so a user who sees a stuck or unexpected transfer, a wrong amount or recipient, a misleading UI state, or a suspected vulnerability can find how to report it without digging through the watchtower threat-model doc.

Bundle (do not split):

  1. Root SECURITY.md — contact, responsible disclosure, response window, in-scope / out-of-scope.
  2. Discoverability — README, docs/README.md, and docs/security-model.md must link it (same job as DEX README.md “Security reports” and docs/security-model.md § User security contact).
  3. Structured report channel — a Forgejo issue template (this repo has no .gitlab/ and no .forgejo/ issue templates today).
  4. dApp footer — a “Report suspicious activity” (or equivalent) link on packages/frontend so retail users do not have to find the git tree.

Pattern to follow (different repo, already shipped): cl8y-dex-terraclassic#392 and that repo’s SECURITY.md. Do not copy GitLab-only URLs. This repo’s tracker is Forgejo (git.cl8y.com/code/cl8y-bridge-monorepo).

Current state

Surface Today
Root SECURITY.md Missing (404 on main)
Root README.md Documentation table Architecture, security model, deploy, frontend invariants — no disclosure / contact row
docs/README.md Security section Links security-model.md and Terra gap analysis only
docs/security-model.md Watchtower, hash, delay, reorg, rate limits, Blockaid (INV-BLK1). No user contact section
docs/qa-onboarding.md QA files bugs on Forgejo; “escalate privately” for backend/contracts — not a public user path
Issue templates No .gitlab/, no .forgejo/ templates; .github/ is workflow/reference leftover
dApp chrome Layout.tsx footer is version / git SHA / theme only. Legal clickwrap (INV-FE-CLICKWRAP-1 / #134) is terms signing, not vulnerability reporting
Skills No SECURITY.md / disclosure playbook (DEX has skills/AGENTS_SECURITY_CONTACT.md)

Readers who need this: retail users on bridge.cl8y.com, researchers, and agents verifying pre-launch disclosure. They currently land on operator-facing threat-model prose or QA onboarding, neither of which is a disclosure policy.

Why the new documentation is needed

  1. Discoverability. Forgejo (and clones) surface SECURITY.md at the repo root. Without it, the file browser and any host “Security” tab have nothing to show.
  2. Parity with DEX. DEX already documents email, structured issue template, 48–72 hour acknowledgement, and a footer link. Bridge is a funds-moving product with a public UI and should not be the product that is harder to report against.
  3. Wrong docs today. docs/security-model.md explains how cancelers stop a bad approveWithdraw. It does not tell a user where to send a report or that they must not paste exploit steps into a public issue.
  4. One bundle. Splitting policy file vs README link vs footer vs template produces stale URLs (DEX still says “GitLab” in places). Land the Forgejo URLs and footer href together.

Constraints / guardrails

  • Contact channel. Reuse the already-published DEX address contact@ceramicliberty.com unless product updates it in-repo. Do not invent a second mailbox, Telegram handle, or Discord. Keep email + template URL in sync across SECURITY.md, template, footer constants, and docs.
  • Tracker is Forgejo. Preferred structured path: new issue on code/cl8y-bridge-monorepo with the security label via a template under .forgejo/issue_template/ (or .gitea/issue_template/ if that is what this Forgejo version reads). Do not revive GitLab template URLs. Do not point the footer at DEX’s GitLab security_report template.
  • Responsible disclosure. Policy must say: do not publish exploit details, PoCs, or step-by-step attack instructions in public issues or social posts before triage. Public issues are for how to reach us and what was observed (tx hash, chain, time UTC), not recipes.
  • Response window. Match DEX unless product specifies otherwise: initial acknowledgement 48–72 hours (business days); triage/next steps within 5 business days when reproduction is feasible; same-day priority when funds appear at immediate risk and the report has enough detail.
  • Scope table is bridge-shaped. In scope: EVM / Terra Classic / Solana contracts, operator and canceler services, frontend/wallet UX (wrong network, wrong recipient, misleading quote or status). Out of scope for this file: third-party wallet heuristics (point at docs/METAMASK_BLOCKAID_EVM.md / INV-BLK1), general product bugs (normal issues, no security label), and operator runbooks (docs/runbook-cancelers.md) — those stay internal.
  • Clickwrap is not disclosure. INV-FE-CLICKWRAP-1 stays terms gating on mutative CTAs. Do not put the report link inside TermsGate or send reporters to terms.cl8y.com. Footer / legal strip only.
  • Header / mobile. INV-FE-WC-MOBILE-1: do not cover the Connect Terra Wallet CTA with a full-viewport overlay. Footer link must not steal header z-50 or eat the first tap on Connect.
  • No secrets in the policy. No RPC URLs beyond what README already publishes, no operator tokens, no host/VM inventory, no SQLite/queue internals.
  • Do not rewrite docs/security-model.md threat model. Add a short “User security contact” section + link, same as DEX § User security contact.
  • Do not change contracts, operator, canceler, pause, rate limits, or 2-of-3 admin work (#135). This issue is documentation + discoverability chrome.

Relevant files

Path Why
SECURITY.md (new, repo root) Canonical policy. Forgejo/clones show this first
README.md Documentation table / “Security reports” one-liner like DEX
docs/README.md Security index must list the policy, not only the threat model
docs/security-model.md New § User security contact; do not bury the link in watchtower diagrams
docs/qa-onboarding.md Short “Security escalation” for QA: user reports vs private contract bugs
.forgejo/issue_template/security_report.yaml (or .md) Structured Forgejo template: security label, impact, chain, tx hash, UTC time. Confirm the directory this Forgejo actually renders
packages/frontend/src/components/Layout.tsx Footer currently version/SHA/theme only — add report link
packages/frontend/src/components/ (small legal copy helper if needed) Keep href/email/window in one constant so docs and UI cannot drift
packages/frontend unit test next to the footer Assert label, href, target="_blank", rel="noopener noreferrer"
docs/FRONTEND_BRIDGE_INVARIANTS.md One invariant for the footer report link (do not merge into clickwrap)
skills/agent-security-contact.md (new) Agent playbook: paths, invariants, grep/test commands — mirror DEX AGENTS_SECURITY_CONTACT.md with Forgejo URLs
  1. Author root SECURITY.md with the DEX section set, rewritten for bridge: How to report (Forgejo template first, email second), what to include (tx hash, src/dest chain, token, amount, wallet, screenshots, UTC time, whether funds look stuck or at risk), Responsible disclosure, Response window, Scope table (contracts / operator-canceler / frontend).
  2. Add the Forgejo security-report issue template. Front matter / YAML must apply security. Prompt for reproduction, impact, affected component (EVM, Terra, Solana, frontend, operator). Tell reporters not to paste exploit PoCs.
  3. Cross-link: README.md Documentation (or a one-line “Security reports: see SECURITY.md”), docs/README.md Security list, docs/security-model.md new section with a table of policy / template / footer. docs/qa-onboarding.md one subsection so QA does not file user vulns as ordinary UX bugs.
  4. Footer on Layout.tsx (desktop and any mobile legal strip): “Report suspicious activity” → Forgejo new-issue URL with the security template (or SECURITY.md on main if the template URL is not stable for anonymous users). target="_blank" rel="noopener noreferrer". Do not use window.location.href. Constants in one module.
  5. Skill + invariant so later chrome PRs do not drop the link. Verification script or make target that greps the files and runs the footer unit test.

Acceptance criteria

  • AC1. SECURITY.md exists at the repository root on main after merge. It names the email, the Forgejo structured-report path, responsible disclosure (no public exploit write-ups before contact), and a 48–72 hour acknowledgement window.
  • AC2. A human opening the repo root, README.md, and docs/README.md can reach that file in one click each (relative markdown links, not a hostname buried in prose).
  • AC3. docs/security-model.md has a user-contact section that points at SECURITY.md; the watchtower model is unchanged.
  • AC4. Forgejo shows a security-report issue template for this repo. Creating from it applies security and does not use a generic bug template.
  • AC5. Bridge UI footer (all breakpoints that show the existing version/SHA footer) includes a report control whose href is the canonical template or SECURITY.md URL. New tab, noopener noreferrer. Clickwrap / Connect header behavior unchanged (INV-FE-CLICKWRAP-1, INV-FE-WC-MOBILE-1).
  • AC6. Email and template URL match across policy, template, footer constants, and docs.
  • AC7. Agent skill + a focused test or verify script: test -f SECURITY.md, greps for contact email / response window / “Do not”, footer test green.

Test plan (functional paths)

# Path Expect
T1 Open repo root on Forgejo SECURITY.md listed; file has contact + window + disclosure
T2 README.md Security reports link Resolves to SECURITY.md
T3 docs/README.md Security list Policy listed beside security-model
T4 New issue → security template security label; fields for chain / tx / impact
T5 make dev footer, desktop Report link visible; opens template or policy in new tab
T6 Narrow viewport Same link reachable without covering Connect Terra Wallet
T7 Footer unit test href/target/rel assertions
T8 Clickwrap mutative CTA Still TermsGate; report link is not inside the gate

Verification criteria

  • test -f SECURITY.md from repo root.
  • grep contact email, 48–72 hours (or the agreed window), and a responsible-disclosure “Do not” in SECURITY.md.
  • Markdown links from README.md and docs/README.md are relative and resolve in the Forgejo blob view.
  • Footer unit test in packages/frontend.
  • Manual: clone or Forgejo UI → SECURITY.md; make dev → footer → new tab is this repo’s report path, not DEX GitLab and not terms.cl8y.com.
  • Existing frontend unit tests and clickwrap tests stay green. No operator/canceler/contract test changes required.

Out of scope

  • Changing watchtower delay, canceler registration, pause, rate limits, or admin 2-of-3 (#135).
  • Immunefi program, bug bounty amounts, or a new mailbox.
  • MetaMask/Blockaid false-positive process (already docs/METAMASK_BLOCKAID_EVM.md).
  • Operator incident runbooks and canceler ops docs.
  • Deploy, Coolify, or live host changes. Docs and frontend chrome only.
  • Copying DEX SECURITY.md verbatim (GitLab URLs and DEX scope table would be wrong).

Definition of Ready

Given a public clone of code/cl8y-bridge-monorepo and the live bridge UI footer,
When a user looks for how to report a suspicious transfer, wrong payout, misleading status, or suspected vulnerability,
Then they find root SECURITY.md from the repo and docs index, a Forgejo security-report template, and a footer link to that path, with the same contact email and response window as the published DEX policy, without a clickwrap or wallet-connect regression.

purpose=docs

First-pass model recommendation

Recommendation: grok-high

Rationale: Docs/chrome only and low/medium product risk, but the change is not a single-subsystem three-file edit. It spans root policy, docs index + threat-model cross-links, a new Forgejo issue template (this repo has no GitLab templates), frontend footer constants/tests, and a skill/invariant so URLs stay Forgejo rather than leftover GitLab. Contact and disclosure wording must stay consistent with the already-shipped DEX policy. That fails the Composer “at most three production files / one subsystem” bar. Verification is greps, one footer unit test, and a manual footer click-through — no Kimi, no contract tests.

## Summary The bridge monorepo has no root `SECURITY.md` and no easy-to-find user disclosure path. CL8Y DEX already ships that surface: root policy, README / docs-index pointers, a structured security-report issue template, and a dApp footer link. Mirror that pattern here so a user who sees a stuck or unexpected transfer, a wrong amount or recipient, a misleading UI state, or a suspected vulnerability can find how to report it without digging through the watchtower threat-model doc. Bundle (do not split): 1. Root `SECURITY.md` — contact, responsible disclosure, response window, in-scope / out-of-scope. 2. Discoverability — README, `docs/README.md`, and `docs/security-model.md` must link it (same job as DEX `README.md` “Security reports” and `docs/security-model.md` § User security contact). 3. Structured report channel — a Forgejo issue template (this repo has no `.gitlab/` and no `.forgejo/` issue templates today). 4. dApp footer — a “Report suspicious activity” (or equivalent) link on `packages/frontend` so retail users do not have to find the git tree. Pattern to follow (different repo, already shipped): [cl8y-dex-terraclassic#392](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/392) and that repo’s `SECURITY.md`. Do not copy GitLab-only URLs. This repo’s tracker is Forgejo (`git.cl8y.com/code/cl8y-bridge-monorepo`). ## Current state | Surface | Today | | --- | --- | | Root `SECURITY.md` | Missing (`404` on `main`) | | Root `README.md` Documentation table | Architecture, security *model*, deploy, frontend invariants — no disclosure / contact row | | `docs/README.md` Security section | Links `security-model.md` and Terra gap analysis only | | `docs/security-model.md` | Watchtower, hash, delay, reorg, rate limits, Blockaid (INV-BLK1). No user contact section | | `docs/qa-onboarding.md` | QA files bugs on Forgejo; “escalate privately” for backend/contracts — not a public user path | | Issue templates | No `.gitlab/`, no `.forgejo/` templates; `.github/` is workflow/reference leftover | | dApp chrome | `Layout.tsx` footer is version / git SHA / theme only. Legal clickwrap (INV-FE-CLICKWRAP-1 / #134) is terms signing, not vulnerability reporting | | Skills | No `SECURITY.md` / disclosure playbook (DEX has `skills/AGENTS_SECURITY_CONTACT.md`) | Readers who need this: retail users on `bridge.cl8y.com`, researchers, and agents verifying pre-launch disclosure. They currently land on operator-facing threat-model prose or QA onboarding, neither of which is a disclosure policy. ## Why the new documentation is needed 1. Discoverability. Forgejo (and clones) surface `SECURITY.md` at the repo root. Without it, the file browser and any host “Security” tab have nothing to show. 2. Parity with DEX. DEX already documents email, structured issue template, 48–72 hour acknowledgement, and a footer link. Bridge is a funds-moving product with a public UI and should not be the product that is harder to report against. 3. Wrong docs today. `docs/security-model.md` explains how cancelers stop a bad `approveWithdraw`. It does not tell a user where to send a report or that they must not paste exploit steps into a public issue. 4. One bundle. Splitting policy file vs README link vs footer vs template produces stale URLs (DEX still says “GitLab” in places). Land the Forgejo URLs and footer href together. ## Constraints / guardrails - Contact channel. Reuse the already-published DEX address `contact@ceramicliberty.com` unless product updates it in-repo. Do not invent a second mailbox, Telegram handle, or Discord. Keep email + template URL in sync across `SECURITY.md`, template, footer constants, and docs. - Tracker is Forgejo. Preferred structured path: new issue on `code/cl8y-bridge-monorepo` with the `security` label via a template under `.forgejo/issue_template/` (or `.gitea/issue_template/` if that is what this Forgejo version reads). Do not revive GitLab template URLs. Do not point the footer at DEX’s GitLab `security_report` template. - Responsible disclosure. Policy must say: do not publish exploit details, PoCs, or step-by-step attack instructions in public issues or social posts before triage. Public issues are for *how to reach us* and *what was observed* (tx hash, chain, time UTC), not recipes. - Response window. Match DEX unless product specifies otherwise: initial acknowledgement 48–72 hours (business days); triage/next steps within 5 business days when reproduction is feasible; same-day priority when funds appear at immediate risk and the report has enough detail. - Scope table is bridge-shaped. In scope: EVM / Terra Classic / Solana contracts, operator and canceler services, frontend/wallet UX (wrong network, wrong recipient, misleading quote or status). Out of scope for this *file*: third-party wallet heuristics (point at `docs/METAMASK_BLOCKAID_EVM.md` / INV-BLK1), general product bugs (normal issues, no `security` label), and operator runbooks (`docs/runbook-cancelers.md`) — those stay internal. - Clickwrap is not disclosure. INV-FE-CLICKWRAP-1 stays terms gating on mutative CTAs. Do not put the report link inside `TermsGate` or send reporters to `terms.cl8y.com`. Footer / legal strip only. - Header / mobile. INV-FE-WC-MOBILE-1: do not cover the Connect Terra Wallet CTA with a full-viewport overlay. Footer link must not steal header `z-50` or eat the first tap on Connect. - No secrets in the policy. No RPC URLs beyond what README already publishes, no operator tokens, no host/VM inventory, no SQLite/queue internals. - Do not rewrite `docs/security-model.md` threat model. Add a short “User security contact” section + link, same as DEX § User security contact. - Do not change contracts, operator, canceler, pause, rate limits, or 2-of-3 admin work (#135). This issue is documentation + discoverability chrome. ## Relevant files | Path | Why | | --- | --- | | `SECURITY.md` (new, repo root) | Canonical policy. Forgejo/clones show this first | | `README.md` | Documentation table / “Security reports” one-liner like DEX | | `docs/README.md` | Security index must list the policy, not only the threat model | | `docs/security-model.md` | New § User security contact; do not bury the link in watchtower diagrams | | `docs/qa-onboarding.md` | Short “Security escalation” for QA: user reports vs private contract bugs | | `.forgejo/issue_template/security_report.yaml` (or `.md`) | Structured Forgejo template: `security` label, impact, chain, tx hash, UTC time. Confirm the directory this Forgejo actually renders | | `packages/frontend/src/components/Layout.tsx` | Footer currently version/SHA/theme only — add report link | | `packages/frontend/src/components/` (small legal copy helper if needed) | Keep href/email/window in one constant so docs and UI cannot drift | | `packages/frontend` unit test next to the footer | Assert label, `href`, `target="_blank"`, `rel="noopener noreferrer"` | | `docs/FRONTEND_BRIDGE_INVARIANTS.md` | One invariant for the footer report link (do not merge into clickwrap) | | `skills/agent-security-contact.md` (new) | Agent playbook: paths, invariants, grep/test commands — mirror DEX `AGENTS_SECURITY_CONTACT.md` with Forgejo URLs | ## Recommended direction 1. Author root `SECURITY.md` with the DEX section set, rewritten for bridge: How to report (Forgejo template first, email second), what to include (tx hash, src/dest chain, token, amount, wallet, screenshots, UTC time, whether funds look stuck or at risk), Responsible disclosure, Response window, Scope table (contracts / operator-canceler / frontend). 2. Add the Forgejo security-report issue template. Front matter / YAML must apply `security`. Prompt for reproduction, impact, affected component (EVM, Terra, Solana, frontend, operator). Tell reporters not to paste exploit PoCs. 3. Cross-link: `README.md` Documentation (or a one-line “Security reports: see `SECURITY.md`”), `docs/README.md` Security list, `docs/security-model.md` new section with a table of policy / template / footer. `docs/qa-onboarding.md` one subsection so QA does not file user vulns as ordinary UX bugs. 4. Footer on `Layout.tsx` (desktop and any mobile legal strip): “Report suspicious activity” → Forgejo new-issue URL with the security template (or `SECURITY.md` on `main` if the template URL is not stable for anonymous users). `target="_blank"` `rel="noopener noreferrer"`. Do not use `window.location.href`. Constants in one module. 5. Skill + invariant so later chrome PRs do not drop the link. Verification script or `make` target that greps the files and runs the footer unit test. ## Acceptance criteria - AC1. `SECURITY.md` exists at the repository root on `main` after merge. It names the email, the Forgejo structured-report path, responsible disclosure (no public exploit write-ups before contact), and a 48–72 hour acknowledgement window. - AC2. A human opening the repo root, `README.md`, and `docs/README.md` can reach that file in one click each (relative markdown links, not a hostname buried in prose). - AC3. `docs/security-model.md` has a user-contact section that points at `SECURITY.md`; the watchtower model is unchanged. - AC4. Forgejo shows a security-report issue template for this repo. Creating from it applies `security` and does not use a generic bug template. - AC5. Bridge UI footer (all breakpoints that show the existing version/SHA footer) includes a report control whose `href` is the canonical template or `SECURITY.md` URL. New tab, `noopener noreferrer`. Clickwrap / Connect header behavior unchanged (INV-FE-CLICKWRAP-1, INV-FE-WC-MOBILE-1). - AC6. Email and template URL match across policy, template, footer constants, and docs. - AC7. Agent skill + a focused test or verify script: `test -f SECURITY.md`, greps for contact email / response window / “Do not”, footer test green. ## Test plan (functional paths) | # | Path | Expect | | --- | --- | --- | | T1 | Open repo root on Forgejo | `SECURITY.md` listed; file has contact + window + disclosure | | T2 | `README.md` Security reports link | Resolves to `SECURITY.md` | | T3 | `docs/README.md` Security list | Policy listed beside security-model | | T4 | New issue → security template | `security` label; fields for chain / tx / impact | | T5 | `make dev` footer, desktop | Report link visible; opens template or policy in new tab | | T6 | Narrow viewport | Same link reachable without covering Connect Terra Wallet | | T7 | Footer unit test | href/target/rel assertions | | T8 | Clickwrap mutative CTA | Still `TermsGate`; report link is not inside the gate | ## Verification criteria - `test -f SECURITY.md` from repo root. - `grep` contact email, `48–72 hours` (or the agreed window), and a responsible-disclosure “Do not” in `SECURITY.md`. - Markdown links from `README.md` and `docs/README.md` are relative and resolve in the Forgejo blob view. - Footer unit test in `packages/frontend`. - Manual: clone or Forgejo UI → `SECURITY.md`; `make dev` → footer → new tab is this repo’s report path, not DEX GitLab and not `terms.cl8y.com`. - Existing frontend unit tests and clickwrap tests stay green. No operator/canceler/contract test changes required. ## Out of scope - Changing watchtower delay, canceler registration, pause, rate limits, or admin 2-of-3 (#135). - Immunefi program, bug bounty amounts, or a new mailbox. - MetaMask/Blockaid false-positive process (already `docs/METAMASK_BLOCKAID_EVM.md`). - Operator incident runbooks and canceler ops docs. - Deploy, Coolify, or live host changes. Docs and frontend chrome only. - Copying DEX `SECURITY.md` verbatim (GitLab URLs and DEX scope table would be wrong). ## Definition of Ready Given a public clone of `code/cl8y-bridge-monorepo` and the live bridge UI footer, When a user looks for how to report a suspicious transfer, wrong payout, misleading status, or suspected vulnerability, Then they find root `SECURITY.md` from the repo and docs index, a Forgejo security-report template, and a footer link to that path, with the same contact email and response window as the published DEX policy, without a clickwrap or wallet-connect regression. ### purpose=docs ## First-pass model recommendation Recommendation: grok-high Rationale: Docs/chrome only and low/medium product risk, but the change is not a single-subsystem three-file edit. It spans root policy, docs index + threat-model cross-links, a new Forgejo issue template (this repo has no GitLab templates), frontend footer constants/tests, and a skill/invariant so URLs stay Forgejo rather than leftover GitLab. Contact and disclosure wording must stay consistent with the already-shipped DEX policy. That fails the Composer “at most three production files / one subsystem” bar. Verification is greps, one footer unit test, and a manual footer click-through — no Kimi, no contract tests.
Author
Owner

cl8y-agent-control: queued implement job d5392bb5-34a5-453d-ad05-b2b4c6b7ee01 (not executed; no Hetzner VM).

cl8y-agent-control: queued `implement` job `d5392bb5-34a5-453d-ad05-b2b4c6b7ee01` (not executed; no Hetzner VM).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-bridge-monorepo#192
No description provided.