From c754535a0d3150aa3f79666cc75b9d574935cdd9 Mon Sep 17 00:00:00 2001 From: aljo242 Date: Wed, 30 Sep 2026 16:44:20 -0400 Subject: [PATCH 1/6] docs: replace the silent patch model with the monthly private patch cycle Brings SECURITY.md in line with the agreed patching policy change. Every severity is patched privately in that month's private repository, shared with KYC'd downstream teams, and published with a full GHSA at the start of the next month. Drops the severity-based disclosure table, since severity no longer decides how or when a fix is published. Active exploitation still leaves the cycle and is handled as an incident. --- SECURITY.md | 136 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 54 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 3d69721..fd1866c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,6 +11,9 @@ This document defines the process for reporting vulnerabilities, describes the bug bounty program, and outlines Cosmos Labs’ approach to patching and public disclosure. +Security patches are made privately at every severity and published on a +monthly cycle. See [Security Patch Process](#security-patch-process). + ------------------------------------------------------------------------ ## Reporting a Vulnerability @@ -62,7 +65,8 @@ Policy** and **Safe Harbor terms**. ## Vulnerability Severity Levels Reported vulnerabilities are assigned a severity classification that -determines handling priority and disclosure timing. +determines handling priority and reward. It does not determine how or when a +fix is published: every severity follows the same patch process below. The definitions that define severity classification and the reward ranges that follow are maintained on our Immunefi page and not duplicated here. See the @@ -74,57 +78,90 @@ classification methodology. ------------------------------------------------------------------------ -## Silent Patch and Disclosure Process +## Security Patch Process + +All security patches are made privately, at every severity. There is no separate +public path for lower severity issues, and no severity-based decision about +where a fix lands. + +### Monthly private repositories + +Cosmos Labs maintains a set of private repositories each month, one for each +repository in bug bounty scope. Coverage targets the repositories downstream +chains depend on most, including the Cosmos SDK, CometBFT, IBC-Go, Cosmos EVM, +and the CosmWasm repositories. They are named for the repository and the month, +for example `cosmos-sdk-priv-july-2026`. + +Access is granted to downstream teams that have passed KYC and run the +repository in production. Each month's repositories are created fresh and +collaborators are reinvited, which keeps the access list current. They are +rebased periodically against `main` and the maintained release branches, so they +stay current with their public counterparts. + +### Patch detail + +Patches merged into a private repository are not obfuscated. A patch PR carries +the description of the vulnerability, its root cause, severity, potential +impact, and any tests that reproduce it. + +Downstream teams therefore hold the same information we do, and decide for +themselves how their chain responds. Cosmos Labs does not make that call on +their behalf. -Cosmos Labs follows a **silent patch** model for most security -vulnerabilities. Issues are addressed privately and remediated prior to -public disclosure. +### Private distribution -This approach aligns with practices -used by other major protocols, such as **Ethereum's Geth** (see -https://geth.ethereum.org/docs/developers/geth-developer/disclosures), -**Bitcoin Core** (see https://bitcoincore.org/en/security-advisories/), -and **Zcash** (see https://z.cash/technology/security-advisories/). +Patch source code must not be redistributed: not into a downstream codebase, and +not to validators. Distributing a built binary that contains the patch is +allowed, through whatever mechanism the chain already uses, including GitHub +release artifacts, provided no patch source is included. -Premature disclosure can place unpatched networks at risk. Silent -remediation allows operators time to upgrade before vulnerability -details become public. +After each PR merges into a maintained release line, we tag a `-hotfix` version +on that line, so teams that want to remediate ahead of the public release can +build against the fix. -Vulnerabilities classified as **Critical** are handled on a case-by-case -basis. When an issue presents an immediate or network-wide risk, Cosmos -Labs will initiate emergency mitigations, private fix distribution, or -coordinated upgrades before any public disclosure occurs. +Where a fix spans repositories that depend on each other, downstream teams point +at the private repositories with `replace` directives in `go.mod`. -If Cosmos Labs determines that a vulnerability with **network-wide -impact** (such as a chain halt or consensus failure) is already being -actively exploited, or that attacker awareness is confirmed prior to a -scheduled release, the issue is escalated and handled as **Critical** for -response and disclosure purposes, regardless of its original -classification. +### Code freeze and public release -### Fix Distribution +The private repositories are frozen for the last week of each month. During the +freeze no further patches are merged into that month's repositories. They are +merged into the next month's instead, which is why each month's set is created +seven days early. -- Fixes are delivered through patch or minor releases. -- Release notes may omit explicit references to security implications. -- Validators and node operators may be notified privately to upgrade. -- For critical vulnerabilities, fixes may be distributed privately to - key operators or require emergency network upgrades. +At the start of the following month, every patch in the frozen repositories is +merged into the corresponding public repository, new patch releases are tagged, +and a GHSA is published for each vulnerability with full details. That +publication is the disclosure date. -### Disclosure Timeline +The frozen repositories are then deleted. -| **Severity** | **Disclosure Timing** | **Details** | -|------------------|----------------------------------------------------------------------------|-----------------------------------------------------------------------| -| **Low / Medium** | Approximately four weeks after public release of the fix | Full advisory published with impact and remediation details. | -| **High** | After the affected version reaches **End-of-Life (EOL)** (~1 year typical) | Disclosure delayed to reduce exploitation risk. | -| **Critical** | Case-by-case (At minimum after EOL) | Disclosure only when deemed safe; details may be limited or withheld. | +A vulnerability reported on August 12 and patched on August 15 therefore reaches +the private repositories the same week, is frozen on August 25, and is public on +September 1. + +### Critical vulnerabilities + +Criticals follow the same process, with two additions. We notify affected chains +through the security mailing list for that repository that the month's private +repository contains a critical patch. And a critical merged fewer than three +days before the freeze begins moves to the next month's repository, so chains +have at least ten days to mitigate privately before the fix is public. + +### Active exploitation + +A vulnerability that is being actively exploited, or where we confirm attacker +awareness ahead of the scheduled release, leaves the monthly cycle and is +handled as an incident. That means emergency mitigations, private fix +distribution, or a coordinated upgrade, ahead of any public disclosure. This +applies regardless of the original severity classification. ------------------------------------------------------------------------ -## Transparency and Post-Disclosure +## Advisories -After expiration of the disclosure embargo, Cosmos Labs publishes a -**Security Advisory** (via GitHub advisories or official blog posts) -containing: +A GitHub Security Advisory is published for every patched vulnerability at the +monthly public release, containing: - Vulnerability description - Affected versions @@ -132,8 +169,7 @@ containing: - Remediation guidance - Reporter attribution (unless anonymity is requested) -All advisories remain publicly available. This delayed disclosure model -balances ecosystem safety with long-term transparency. +All advisories remain publicly available. ------------------------------------------------------------------------ @@ -143,23 +179,15 @@ ecosystem. ------------------------------------------------------------------------ -### References - -- [Bitcoin Core Security Advisories](https://bitcoincore.org/en/security-advisories/) -- [Go Ethereum Vulnerability Disclosure](https://ethereumpow.github.io/go-ethereum/docs/vulnerabilities/vulnerabilities) -- [Bitcoin Core Security Disclosure Policy Announcement](https://bitexes.com/blog/124272) - ------------------------------------------------------------------------- - ## Consequences of Improper Disclosure -Publishing vulnerability details before their disclosure date puts users at risk -whatever the intent. For High and Critical issues that date falls well after the -fix ships. +Publishing vulnerability details before their disclosure date puts users at +risk whatever the intent. A fix reaches downstream chains privately before it is +public, so early disclosure exposes chains that have not yet upgraded. We give the reporter a disclosure date. That date is the one that counts, and -where we have not given one, the timeline above applies. Disclosure we have -authorized is never a violation, whenever it happens. +where we have not given one, it is the monthly public release that carries the +fix. Disclosure we have authorized is never a violation, whenever it happens. The consequences below apply to anyone who publishes early, whether or not they submitted through the bug bounty program. From deab07f5e2d9780a6c5ce70ffc3fcd0f50e123cf Mon Sep 17 00:00:00 2001 From: aljo242 Date: Thu, 1 Oct 2026 10:04:24 -0400 Subject: [PATCH 2/6] docs: say how teams learn a patch is available Criticals go out on the repository's security mailing list; everything else is found by watching the private repo's -hotfix tags. This is what we already told Cronos when they asked on 2026-09-17, but the policy did not say it. --- SECURITY.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/SECURITY.md b/SECURITY.md index fd1866c..e6e827d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -122,6 +122,14 @@ build against the fix. Where a fix spans repositories that depend on each other, downstream teams point at the private repositories with `replace` directives in `go.mod`. +### How teams learn a patch is available + +For a critical, we send an email to the security mailing list for that +repository. For every other severity, teams watch the `-hotfix` tags on the +private repository and decide from the patch details whether to pull a fix in. +We do not email on each lower severity patch, because at the volume we patch it +would be noise. + ### Code freeze and public release The private repositories are frozen for the last week of each month. During the From b0cef6491aadbcfecd267d4c354113ee252e0cd3 Mon Sep 17 00:00:00 2001 From: aljo242 Date: Thu, 1 Oct 2026 10:09:03 -0400 Subject: [PATCH 3/6] docs: tighten the notification section to policy register Drops the aside explaining why lower severities are not emailed, and the colloquial phrasing, to match the rest of the document. --- SECURITY.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index e6e827d..daf9d9f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -122,13 +122,13 @@ build against the fix. Where a fix spans repositories that depend on each other, downstream teams point at the private repositories with `replace` directives in `go.mod`. -### How teams learn a patch is available +### Notification -For a critical, we send an email to the security mailing list for that -repository. For every other severity, teams watch the `-hotfix` tags on the -private repository and decide from the patch details whether to pull a fix in. -We do not email on each lower severity patch, because at the volume we patch it -would be noise. +Critical patches are announced by email to the security mailing list for the +affected repository. Patches at all other severities are not announced +individually. Teams track the `-hotfix` tags on the private repository and use +the patch details to determine whether to adopt a fix ahead of the public +release. ### Code freeze and public release From 8c89beb7907ddafa4485820ca6ef52f1f502287c Mon Sep 17 00:00:00 2001 From: aljo242 Date: Thu, 1 Oct 2026 10:17:31 -0400 Subject: [PATCH 4/6] docs: fix the ten-day claim and state that intake source does not matter The old wording attributed the ten days to moving a late critical into the next month's repository. Moving it actually pushes the public release out by a month; the ten days is the floor the three-day rule plus the freeze guarantees for any critical. Reworded so a chain planning around it gets the right number. Also states what the RFC is explicit about and the policy was not: the cycle is the same whether a vulnerability arrives by bug bounty, internal audit, or direct disclosure. --- SECURITY.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index daf9d9f..ace8cb7 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -84,6 +84,10 @@ All security patches are made privately, at every severity. There is no separate public path for lower severity issues, and no severity-based decision about where a fix lands. +The process does not depend on how we learned of the vulnerability. A report +through the bug bounty, a finding from an internal audit, and a direct +disclosure all follow the same path. + ### Monthly private repositories Cosmos Labs maintains a set of private repositories each month, one for each @@ -152,9 +156,11 @@ September 1. Criticals follow the same process, with two additions. We notify affected chains through the security mailing list for that repository that the month's private -repository contains a critical patch. And a critical merged fewer than three -days before the freeze begins moves to the next month's repository, so chains -have at least ten days to mitigate privately before the fix is public. +repository contains a critical patch. And a critical is not merged into a +month's repository within three days of its freeze; one that would be goes into +the next month's repository instead, which pushes its public release out by a +month. Together with the week-long freeze, that leaves at least ten days between +a critical landing in a private repository and its public release. ### Active exploitation From 2a3d5a785c8aadfe4038f026e231352e16010846 Mon Sep 17 00:00:00 2001 From: aljo242 Date: Thu, 1 Oct 2026 11:29:49 -0400 Subject: [PATCH 5/6] fix: restrict passing the patch on, not holding it The rule read "not into a downstream codebase", which bans possession and collides with the replace-directive guidance two paragraphs down: a team that vendors would copy patch source into its own tree by following the policy. The rule is about distribution. A team with access can build however it needs to, vendoring included, and must not pass the source on to anyone else before the patch is public. Also says what happens to a replace directive after the private repository is deleted, which the policy described but never followed through on. --- SECURITY.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index ace8cb7..198ec20 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -114,17 +114,24 @@ their behalf. ### Private distribution -Patch source code must not be redistributed: not into a downstream codebase, and -not to validators. Distributing a built binary that contains the patch is -allowed, through whatever mechanism the chain already uses, including GitHub -release artifacts, provided no patch source is included. +A team with access may use the patch however it needs to in order to build, +vendoring included. The restriction is on passing the source on: until the patch +is public, do not publish it in a public repository, do not commit it to one +inside a vendored dependency tree, and do not make it available to validators or +node operators. + +Distributing a built binary that contains the patch is allowed, through whatever +mechanism the chain already uses, including GitHub release artifacts, provided no +patch source is included. After each PR merges into a maintained release line, we tag a `-hotfix` version on that line, so teams that want to remediate ahead of the public release can build against the fix. Where a fix spans repositories that depend on each other, downstream teams point -at the private repositories with `replace` directives in `go.mod`. +at the private repositories with `replace` directives in `go.mod`. Move those +back to the public tags at the monthly release: a private repository is deleted +once its patches are public, and references to it stop resolving. ### Notification From 01e5f7e80a73ef873ae4bff0f340ef9e72673c40 Mon Sep 17 00:00:00 2001 From: aljo242 Date: Thu, 1 Oct 2026 11:32:17 -0400 Subject: [PATCH 6/6] feat: keep a frozen private repository up for two weeks after its release Deleting it the moment its patches went public broke any later rebuild of the binary a team shipped from it: a validator building from source, CI on a release branch, a reproducible-build check. A two-week window gives teams time to move their replace directives to the public tags. The window holds nothing back, since every patch in a frozen repository is public before it starts. Re-invitation for the next month's repositories runs on its own schedule, so the liveness check on the collaborator list is unaffected. --- SECURITY.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 198ec20..14be176 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -130,8 +130,8 @@ build against the fix. Where a fix spans repositories that depend on each other, downstream teams point at the private repositories with `replace` directives in `go.mod`. Move those -back to the public tags at the monthly release: a private repository is deleted -once its patches are public, and references to it stop resolving. +back to the public tags at the monthly release. The private repository comes down +two weeks after that, and references to it stop resolving. ### Notification @@ -153,11 +153,15 @@ merged into the corresponding public repository, new patch releases are tagged, and a GHSA is published for each vulnerability with full details. That publication is the disclosure date. -The frozen repositories are then deleted. +The frozen repositories stay up for two weeks after that release so teams can +move their builds across, and are deleted at the end of that window. Everything +in them is public by then, so the window holds nothing back. Access to the next +month's repositories is granted by fresh invitation on its own schedule, so the +retention does not extend anyone's access. A vulnerability reported on August 12 and patched on August 15 therefore reaches -the private repositories the same week, is frozen on August 25, and is public on -September 1. +the private repositories the same week, is frozen on August 25, is public on +September 1, and the August repositories come down on September 15. ### Critical vulnerabilities