Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ body:
value: |
Thanks for taking the time to fill out this bug report!

**If this is a security vulnerability, do NOT file a public issue.** Report it privately via [GitHub private vulnerability reporting](https://github.com/container-registry/harbor-next/security/advisories/new). See [SECURITY.md](https://github.com/container-registry/harbor-next/blob/main/SECURITY.md) for the full disclosure policy.

**Before submitting**, please search [existing issues](https://github.com/container-registry/harbor-next/issues) to avoid duplicates.

- type: textarea
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# CodeQL static analysis for the Go backend and the Angular/TypeScript portal.
# Results appear under Security -> Code scanning.
# Go requires a build for analysis (autobuild); JS/TS is scanned without one.

name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '25 3 * * 2'

permissions: read-all

concurrency:
group: codeql-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

strategy:
fail-fast: false
matrix:
include:
- language: go
build-mode: autobuild
- language: javascript-typescript
build-mode: none

steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
queries: security-extended

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
category: "/language:${{ matrix.language }}"
2 changes: 2 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ intoto = "intoto"
# Common Go abbreviations referenced in docs
cfg = "cfg"
ctx = "ctx"
# Security terminology (CVE Numbering Authority)
CNA = "CNA"

[files]
extend-exclude = [
Expand Down
47 changes: 37 additions & 10 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@ Harbor Next is maintained independently from the upstream `goharbor/harbor` proj

## Supported Versions

Security fixes are provided for actively maintained Harbor Next releases. If you are unsure whether a version is supported, report the issue anyway and include the affected version, commit, image tag, and deployment details. Maintainers will determine affected versions and whether backports are feasible based on severity and release status.
| Version | Supported |
| ------- | --------- |
| Latest stable release line (currently `2.15.x`) | Yes — security fixes and patch releases |
| `main` (next release) | Yes — fixes land here first |
| Older release lines | No — best effort only, for Critical issues |

If you are unsure whether a version is supported, report the issue anyway and include the affected version, commit, image tag, and deployment details. Maintainers will determine affected versions and whether backports are feasible based on severity and release status.

## Reporting a Vulnerability

**Do not open a public GitHub issue for security vulnerabilities.**

Report vulnerabilities privately through either of these GitHub flows:
Report vulnerabilities privately through GitHub private vulnerability reporting:

- Open a private vulnerability report directly at [Report a vulnerability](https://github.com/container-registry/harbor-next/security/advisories/new).
- Or go to the repository **Security** tab and click **Report a vulnerability**.
- Or go to [New Issue](https://github.com/container-registry/harbor-next/issues/new/choose) and select **Security Vulnerability**, which routes to the same private form.

Reporting requires a GitHub account. If you cannot use GitHub, contact a maintainer listed in [OWNERS.md](OWNERS.md) through any private channel and ask them to open the report on your behalf.

- Open a private vulnerability report directly at [New GitHub Security Advisory](https://github.com/container-registry/harbor-next/security/advisories/new).
- Go to [New Issue](https://github.com/container-registry/harbor-next/issues/new/choose) and select **Security Vulnerability**. The option is labeled **Report Security Vulnerabilities privately** and routes to the private GitHub Security Advisory flow.
Private vulnerability reports are visible only to project maintainers, who will coordinate with the reporter during investigation and remediation. The maintainer-side handling process is documented in [docs/security-process.md](docs/security-process.md).

Private vulnerability reports are visible to project maintainers, who will coordinate with the reporter during investigation and remediation.
**If the vulnerability already has a public CVE or is already publicly disclosed** (for example, a scanner finding in one of our dependencies), open a normal [public issue](https://github.com/container-registry/harbor-next/issues/new/choose) instead — there is nothing left to keep private.

## What to Include

Expand All @@ -40,17 +51,33 @@ Report privately when:

- You believe Harbor Next has a potential security vulnerability.
- You suspect a vulnerability but are unsure whether it impacts Harbor Next.
- You know of a publicly disclosed vulnerability that may affect Harbor Next or one of its dependencies.
- You know of a not-yet-public vulnerability in a dependency that may affect Harbor Next.

For non-security bugs, feature requests, and proposals, use the public [GitHub issue templates](https://github.com/container-registry/harbor-next/issues/new/choose).

## Response and Disclosure
## Response Targets

| Step | Target |
| ---- | ------ |
| Acknowledge your report | Within **3 business days** |
| Triage decision (accepted / declined) and initial severity | Within **7 calendar days** |
| Status updates while a fix is in progress | At least every **14 days** |
| Fix and advisory for **Critical** issues | Within **14 business days** of triage |
| Coordinated public disclosure | Within **90 days** of the report, or earlier once a fix is released |

These are targets, not guarantees. Complex issues can take longer; if a vulnerability is already public or actively exploited, maintainers may disclose and ship a fix faster.

## What Reporters Can Expect

Maintainers aim to acknowledge private vulnerability reports within 3 business days. The project will investigate the report, determine impact and severity, identify mitigations or workarounds when available, and coordinate a fix.
- Your report is handled through a private GitHub security advisory. You are added as a collaborator on the advisory and can follow and participate in the discussion and the fix.
- Maintainers score severity with CVSS (using the advisory's built-in calculator) and share the assessment with you.
- For confirmed vulnerabilities, maintainers request a **CVE** through GitHub inside the advisory.
- You receive **credit** in the published advisory unless you prefer to stay anonymous.
- If the report is declined, maintainers will explain the reason and may ask that it be re-filed as a public issue if appropriate.

If the issue is confirmed, maintainers will coordinate public disclosure with the reporter after a mitigation or patch is available, unless the vulnerability is already public or active exploitation requires faster disclosure. Public disclosure is normally published through [GitHub Security Advisories](https://github.com/container-registry/harbor-next/security/advisories).
## Disclosure Policy

If the report is not considered a security vulnerability, maintainers will explain the reason and may ask that it be re-filed as a public issue if appropriate.
Maintainers coordinate public disclosure with the reporter after a mitigation or patch is available. Public disclosure happens through [GitHub Security Advisories](https://github.com/container-registry/harbor-next/security/advisories), the release notes of the fixed release, and the CVE record. Fixes for embargoed issues are developed in a temporary private fork and are not visible in the public repository until the advisory is published.

## Security Priorities

Expand Down
122 changes: 122 additions & 0 deletions docs/security-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Security Response Process (Maintainer Runbook)

This document describes how Harbor Next maintainers handle private vulnerability reports, from intake to public disclosure. The reporter-facing policy is [SECURITY.md](../SECURITY.md).

The whole process happens inside **one GitHub artifact**: the private report becomes the draft security advisory, the fix is developed in the advisory's temporary private fork, the CVE is requested inside the advisory, and publishing the advisory is the disclosure. Nothing is re-transcribed between systems.

This process follows the workflow proposed for upstream Harbor in [goharbor/community#292](https://github.com/goharbor/community/pull/292). Harbor Next acts as the reference implementation.

## Roles

- **Security responders**: maintainers with admin access to the repository, or members of a GitHub team with the **security manager** role on the org. They see incoming private reports and receive notifications for them.
- **Advisory lead**: the responder who accepts a report. They own the advisory through publication: triage, severity, fix coordination, CVE request, and disclosure.

Every incoming report needs exactly one advisory lead. If you accept a report, you are the lead until you explicitly hand it over.

## 1. Receiving a report

Reports arrive at **Security → Advisories** as `Proposed` advisories: <https://github.com/container-registry/harbor-next/security/advisories?state=triage>

Notifications for new private reports go to repo admins and org security managers only. **Check the queue at least weekly** even if you saw no notification.

Within **3 business days** of a report arriving:

1. Reply in the advisory thread to acknowledge receipt. The reporter can see comments on the advisory; nothing else is needed to keep them informed.
2. Do a first sanity check:
- **Spam or clearly invalid** → close the report with a short explanation. Anyone with a GitHub account can file, so expect noise; closing politely and quickly is part of the job.
- **Already public** (existing CVE, public scanner finding, already-disclosed dependency issue) → ask the reporter to re-file as a public issue and close the report.
- **Dependency vulnerability, not exploitable in Harbor Next** → treat as a normal dependency update (Dependabot / `zero-cve` workflow), not a Harbor Next advisory. Explain and close.
- **Wrong repo** (e.g. an upstream `goharbor/harbor` issue that does not affect Harbor Next code) → point the reporter to the right project's security policy and close.
- **Plausible product vulnerability** → continue to triage.

## 2. Triage

Within **7 calendar days** of the report:

1. Reproduce the issue, or establish why reproduction isn't needed (e.g. obvious by code inspection). Ask the reporter for missing details in the advisory thread.
2. If confirmed, click **Accept and open as draft**. The report converts into a draft security advisory — same object, no copying.
3. Fill in the draft advisory fields:
- **Affected products/versions**: ecosystem, package, affected version ranges, and patched versions (fill patched versions in once known).
- **CWE** classification.
- **Severity**: use the built-in **CVSS calculator** (v3.1 or v4.0). Score it yourself; do not just accept the reporter's score, but do share and discuss your assessment with them.
4. If declined, explain why in the thread and close the advisory.

Severity drives urgency:

| CVSS | Severity | Handling |
| ---- | -------- | -------- |
| 9.0–10.0 | Critical | Drop other work. Fix + advisory target: **14 business days**. Patch release for the supported release line. |
| 7.0–8.9 | High | Fix in the next patch release; target within 30 days. |
| 4.0–6.9 | Medium | Fix in a regular upcoming release. |
| 0.1–3.9 | Low | Fix opportunistically; may be handled as a public issue after agreeing with the reporter. |

While a fix is in progress, post a status update in the advisory thread at least every **14 days** — the reporter has no other visibility into progress.

## 3. Embargoed fix (temporary private fork)

Do **not** develop the fix in the public repository. Public commits, branches, or PRs leak the vulnerability before disclosure.

1. In the draft advisory, click **Start a temporary private fork**. GitHub creates `harbor-next-ghsa-xxxx-xxxx-xxxx`, visible only to advisory collaborators.
2. Add collaborators as needed via the advisory's collaborator list. The reporter is already a collaborator; add only the maintainers actually working the fix. Access is scoped to this one advisory and cleaned up automatically.
3. Develop and review the fix as PRs inside the private fork. Keep the commit message neutral — it becomes public on disclosure, but should not read as a public spoiler if seen early.
4. **CI does not run on private forks.** Run the test suite locally (`task test:quick`, `task test:ci`) and record in the advisory thread what was run and the results. Do not merge an untested fix.
5. Do not merge the private fork's PR into the public repo until publication time (step 6).

## 4. CVE request

For confirmed vulnerabilities in Harbor Next code:

1. In the draft advisory, choose **Request CVE**. GitHub (acting as CNA) reviews the request, usually within **72 hours**, and reserves a CVE ID bound to the advisory. The CVE is published to MITRE only when the advisory is published.
2. If the affected component is covered by another CNA (e.g. the vulnerability is really in a vendored/upstream component), GitHub may decline; coordinate with that component's security team instead and reference their CVE in our advisory.
3. Vulnerabilities inherited from upstream `goharbor/harbor` normally get their CVE through upstream's process; our advisory then references the upstream CVE rather than requesting a new one.

## 5. Pre-disclosure coordination

1. Agree on a disclosure date with the reporter in the advisory thread. Default: as soon as the fixed release is available; at most **90 days** from the report.
2. Prepare the patch release: the fix will need to land on `main` and be backported to the supported `release-X.Y` branch (see [SECURITY.md](../SECURITY.md) supported versions).
3. If the issue affects known downstream distributors or operators, notify them under embargo before publication (currently ad hoc — see "Open items" below).
4. Prefer publishing on a **weekday, not Friday**, so operators can respond during working hours.

## 6. Publish and release

Order matters — the fix must be available when the advisory goes public:

1. Merge the fix from the temporary private fork (the advisory's **Merge pull request** flow pushes the commits to the public repo).
2. Cut the patch release(s) through the normal release process. Release notes must mention the advisory: `Fixes GHSA-xxxx-xxxx-xxxx (CVE-YYYY-NNNNN)` with severity and a one-line description — no exploit details beyond the advisory.
3. Fill in the advisory's **patched versions** field.
4. Add **credits**: the reporter (with the appropriate role, e.g. *reporter* / *analyst*), who must accept the credit for it to display. Ask first if they want anonymity.
5. Click **Publish advisory**. This makes the advisory public, publishes the CVE to MITRE, and submits it to the GitHub Advisory Database (review can take up to 72h; Dependabot alerts then reach downstream Go-module consumers).
6. The temporary private fork is deleted automatically after publication.

Note: Dependabot alerts only reach consumers of Harbor Next **Go modules**, not users running container images. Image users learn about the fix from the advisory, the release notes, and the registry tags — which is why step 2's release-note convention is mandatory.

## 7. After disclosure

- Verify the advisory appears under [published advisories](https://github.com/container-registry/harbor-next/security/advisories) and the CVE record is live.
- Post-mortem (optional but encouraged for High/Critical): what allowed the bug, whether a test/linter/scanner could catch the class, and file follow-up issues.
- If the issue also affects upstream `goharbor/harbor`, make sure upstream's security team was informed **before** our disclosure, not after.

## Checklist (copy into the advisory thread)

```text
- [ ] Acknowledged reporter (≤3 business days)
- [ ] Triaged: reproduced / declined (≤7 days)
- [ ] Accepted as draft advisory; CWE + CVSS filled in
- [ ] Temporary private fork created; collaborators scoped
- [ ] Fix developed + reviewed in private fork
- [ ] Tests run locally, results recorded (no CI on private forks!)
- [ ] CVE requested via GitHub
- [ ] Disclosure date agreed with reporter
- [ ] Backport(s) prepared for supported release line(s)
- [ ] Release notes reference GHSA/CVE
- [ ] Credits added and accepted
- [ ] Advisory published; patched versions filled in
- [ ] Upstream goharbor/harbor informed (if affected)
```

## Open items (need org-level decisions)

- **Security responder roster**: create a GitHub team with the org **security manager** role instead of relying on repo admins, so the roster is explicit and auditable.
- **Distributor/operator embargo list**: upstream Harbor uses `cncf-harbor-distributors-announce`; Harbor Next has no equivalent yet. Decide if/when one is needed.
- **Fallback intake for reporters without a GitHub account**: currently "contact a maintainer privately"; a dedicated alias would be cleaner.
- **security.txt**: publish `/.well-known/security.txt` on the project website pointing at the GitHub report form (requires a website/domain decision, plus a yearly `Expires` refresh).