docs(security): establish coordinated vulnerability disclosure - #72
docs(security): establish coordinated vulnerability disclosure#72seonghobae wants to merge 22 commits into
Conversation
📝 WalkthroughWalkthrough공개 보안 정책과 취약점 공개 지침을 추가했습니다. 접수부터 검증, 수정, 릴리스, 공개, 복구, 증거 보존까지의 처리 lifecycle을 정의했습니다. 관련 문서의 필수 내용을 검증하는 Vitest 계약 테스트를 추가했습니다. Changes취약점 공개 및 처리
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Reporter
participant GitHubPrivateReport
participant MaintainerLifecycle
participant ReleaseEvidence
Reporter->>GitHubPrivateReport: 비공개 취약점 신고와 재현 증거 제출
GitHubPrivateReport->>MaintainerLifecycle: 신고 접수 및 case identifier 생성
MaintainerLifecycle->>ReleaseEvidence: 검증, 수정, 테스트, 승인 증거 기록
ReleaseEvidence-->>MaintainerLifecycle: 릴리스·배포·복구 검증 결과 반환
MaintainerLifecycle-->>Reporter: 상태 업데이트와 조정된 공개 일정 전달
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review Please perform a substantive read-only review of exact current head |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
expected='d43b09386e5fd10aaf72882c9d34e3a9b6b3cc64'
actual="$(git rev-parse HEAD)"
printf 'HEAD=%s\nEXPECTED=%s\n' "$actual" "$expected"
if [ "$actual" != "$expected" ]; then
printf 'ERROR: checked-out revision does not match the requested exact head\n' >&2
exit 2
fi
printf '\n== Commit ==\n'
git show -s --format='%H%n%P%n%s' HEAD
printf '\n== Changed files versus parent ==\n'
git diff-tree --no-commit-id --name-status -r HEAD
printf '\n== Candidate policy/lifecycle files ==\n'
fd -HI -t f '^(SECURITY\.md|CHANGELOG\.md|.*[Ss]ecur.*\.(md|test\.(ts|js))|.*[Vv]ulnerab.*\.(md|test\.(ts|js)))$' . \
-E .git -E node_modules -E dist -E build | sort
printf '\n== Diff stat ==\n'
git diff --stat HEAD^ HEADLength of output: 1567 🏁 Script executed: #!/bin/bash
set -euo pipefail
base='9adb784902cae19a150146a8fadd6a0491f67814'
head='d43b09386e5fd10aaf72882c9d34e3a9b6b3cc64'
git cat-file -e "${base}^{commit}"
git cat-file -e "${head}^{commit}"
printf '%s\n' '== Files changed in the complete PR range =='
git diff --name-status "$base" "$head"
printf '%s\n' '== Complete PR diff =='
git diff --find-renames --find-copies --unified=40 "$base" "$head" -- \
SECURITY.md \
CHANGELOG.md \
docs/doctoring/vulnerability-disclosure.md \
docs/security/vulnerability-handling.md \
docs/security-validation-checklist.md \
test/security-policy-contract.test.ts \
test/security-checklist.test.ts \
test/security-validation-evidence.test.ts
printf '%s\n' '== Numbered relevant file contents at exact head =='
for f in \
SECURITY.md \
CHANGELOG.md \
docs/doctoring/vulnerability-disclosure.md \
docs/security/vulnerability-handling.md \
docs/security-validation-checklist.md \
test/security-policy-contract.test.ts \
test/security-checklist.test.ts \
test/security-validation-evidence.test.ts
do
if [ -f "$f" ]; then
printf '\n----- %s -----\n' "$f"
cat -n "$f"
fi
doneLength of output: 123710 🤖 web_search executed:
Length of output: 11929 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='d43b09386e5fd10aaf72882c9d34e3a9b6b3cc64'
test "$(git rev-parse HEAD)" = "$head"
printf '%s\n' '== Policy-related claims at exact head =='
rg -n -i -C 2 \
'(private (vulnerability )?report|report a vulnerability|security (email|contact)|bug bounty|compensation|contractual SLA|24.?7|production.ready|supported version|security support|release readiness|deployment readiness|coordinated disclosure|CVE|CVSS|known exploited|safe harbor)' \
--glob '*.md' --glob '*.ts' --glob '*.js' --glob '*.mjs' \
-g '!node_modules/**' -g '!dist/**' -g '!build/**' .
printf '%s\n' '== Markdown links in new policy documents =='
python3 - <<'PY'
import re
from pathlib import Path
files = [
Path("SECURITY.md"),
Path("docs/security/vulnerability-handling.md"),
Path("docs/doctoring/vulnerability-disclosure.md"),
]
for path in files:
print(f"\n{path}:")
text = path.read_text(encoding="utf-8")
for line, value in enumerate(text.splitlines(), 1):
for url in re.findall(r'https?://[^\s)>]+', value):
print(f"{line}: {url}")
for target in re.findall(r'\[[^\]]+\]\((?!https?://)([^)#]+)', value):
resolved = (path.parent / target).resolve()
print(f"{line}: internal {target} -> {'OK' if resolved.exists() else 'MISSING'}")
PY
printf '%s\n' '== Changed-file whitespace and conflict markers =='
git diff --check 9adb784902cae19a150146a8fadd6a0491f67814 "$head"
rg -n '^(<<<<<<<|=======|>>>>>>>)' SECURITY.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md CHANGELOG.md test/security-policy-contract.test.ts || trueLength of output: 30999
Finding — medium priority: The regression contract does not protect the no-operational-guarantee boundary.
A future edit could state that private reporting is available or monitored, while this test still passes. Add assertions for these negative boundaries. This change will preserve the central buyer-visible constraint that repository text cannot prove live administrative or operational controls. I found no other actionable issue in the requested scope. The current policy text correctly keeps private reporting conditional, provides a content-free public fallback, limits support to pre-release investigation and remediation, separates source/release/deployment evidence, uses CVSS v4.0 with exploitation-aware prioritization, and avoids bounty, SLA, and 24/7 claims.
|
|
@coderabbitai review Please perform a substantive read-only review of exact current head |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base='9adb784902cae19a150146a8fadd6a0491f67814'
head='e5db307d54675914640f03e5b92695bc57664d39'
actual="$(git rev-parse HEAD)"
printf 'HEAD=%s\nREQUESTED_HEAD=%s\n' "$actual" "$head"
if [ "$actual" != "$head" ]; then
printf 'ERROR: checked-out revision does not match the requested exact head\n' >&2
exit 2
fi
git cat-file -e "${base}^{commit}"
git cat-file -e "${head}^{commit}"
printf '\n== Exact commit ==\n'
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$head"
printf '\n== Files changed across the PR range ==\n'
git diff --name-status "$base" "$head"
printf '\n== Relevant file outlines ==\n'
for f in SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts; do
if [ -f "$f" ]; then
printf '\n--- %s ---\n' "$f"
if [[ "$f" == *.ts ]]; then
ast-grep outline "$f" --items all || true
else
rg -n '^#{1,6} ' "$f" || true
fi
else
printf 'MISSING: %s\n' "$f"
fi
done
printf '\n== PR diff for review scope ==\n'
git diff --find-renames --unified=20 "$base" "$head" -- \
SECURITY.md \
CHANGELOG.md \
docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md \
test/security-policy-contract.test.ts
printf '\n== Numbered exact-head content for review scope ==\n'
for f in SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts; do
if [ -f "$f" ]; then
printf '\n--- %s ---\n' "$f"
cat -n "$f"
fi
done
printf '\n== Targeted policy-claim search ==\n'
rg -n -i -C 2 \
'(report a vulnerability|private vulnerability reporting|when that control is available|enabled|monitored|staffed|exercised|bug bounty|bounty|compensation|SLA|24.?7|production.ready|supported release|pre.release|content.free|safe harbor|CVSS|known exploited|KEV|incident escalation|CVE|advisory|source identity|release identity|deployment identity|retention)' \
SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts
printf '\n== Whitespace and conflict-marker checks ==\n'
git diff --check "$base" "$head"
rg -n '^(<<<<<<<|=======|>>>>>>>)' \
SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts || trueLength of output: 146414
I found no actionable findings in the requested scope. The predecessor regression-contract finding is addressed.
The reviewed documents are consistent on the requested boundaries:
This is review evidence only. It is not approval or merge authority. ✏️ Learnings added
|
|
@coderabbitai review Please perform a substantive read-only review of exact current head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base='9adb784902cae19a150146a8fadd6a0491f67814'
head='e5db307d54675914640f03e5b92695bc57664d39'
actual="$(git rev-parse HEAD)"
printf 'HEAD=%s\nREQUESTED_HEAD=%s\n' "$actual" "$head"
if [ "$actual" != "$head" ]; then
printf 'ERROR: checked-out revision does not match the requested exact head\n' >&2
exit 2
fi
git cat-file -e "${base}^{commit}"
git cat-file -e "${head}^{commit}"
printf '\n== Exact commit ==\n'
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$head"
printf '\n== PR-range changed files ==\n'
git diff --name-status "$base" "$head"
printf '\n== Scoped document structure ==\n'
for f in \
SECURITY.md \
CHANGELOG.md \
docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md \
test/security-policy-contract.test.ts
do
printf '\n--- %s ---\n' "$f"
test -f "$f" || { printf 'MISSING\n'; continue; }
if [[ "$f" == *.ts ]]; then
ast-grep outline "$f" --items all
else
rg -n '^#{1,6} ' "$f" || true
fi
done
printf '\n== Complete scoped diff ==\n'
git diff --find-renames --unified=30 "$base" "$head" -- \
SECURITY.md \
CHANGELOG.md \
docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md \
test/security-policy-contract.test.ts
printf '\n== Exact-head scoped contents ==\n'
for f in \
SECURITY.md \
CHANGELOG.md \
docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md \
test/security-policy-contract.test.ts
do
printf '\n--- %s ---\n' "$f"
cat -n "$f"
done
printf '\n== Claims and regression anchors ==\n'
rg -n -i -C 3 \
'(report a vulnerability|when that control is available|private vulnerability reporting|enabled|monitored|staffed|exercised|notification subscription|response objective|security email|bounty|compensation|SLA|24.?7|production.ready|pre.release|safe harbor|prohibited|destructive|third.party|CVSS|KEV|known exploited|source identity|release identity|deployment identity|incident escalation|CVE|advisory|retention|APA|ISO/IEC|NIST)' \
SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts
printf '\n== Link targets and diff hygiene ==\n'
python3 - <<'PY'
import re
from pathlib import Path
for name in [
"SECURITY.md",
"docs/security/vulnerability-handling.md",
"docs/doctoring/vulnerability-disclosure.md",
]:
p = Path(name)
print(f"\n{name}")
for n, line in enumerate(p.read_text(encoding="utf-8").splitlines(), 1):
for target in re.findall(r'\[[^\]]+\]\((?!https?://|#)([^)#]+)', line):
print(f"{n}: {target}: {'OK' if (p.parent / target).exists() else 'MISSING'}")
PY
git diff --check "$base" "$head"
rg -n '^(<<<<<<<|=======|>>>>>>>)' \
SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts || trueLength of output: 172329 You are interacting with an AI system. |
|
@coderabbitai review Please perform a substantive review of the exact current head |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base='9adb784902cae19a150146a8fadd6a0491f67814'
head='e5db307d54675914640f03e5b92695bc57664d39'
actual="$(git rev-parse HEAD)"
printf 'HEAD=%s\nREQUESTED_HEAD=%s\n' "$actual" "$head"
if [ "$actual" != "$head" ]; then
printf 'ERROR: checked-out revision does not match requested exact head\n' >&2
exit 2
fi
git cat-file -e "${base}^{commit}"
git cat-file -e "${head}^{commit}"
printf '\n== Exact commit ==\n'
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$head"
printf '\n== PR-range changed files ==\n'
git diff --name-status "$base" "$head"
printf '\n== Document structure and test outline ==\n'
for f in \
SECURITY.md \
CHANGELOG.md \
docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md \
test/security-policy-contract.test.ts
do
printf '\n--- %s ---\n' "$f"
test -f "$f" || { printf 'MISSING\n'; continue; }
if [[ "$f" == *.ts ]]; then
ast-grep outline "$f" --items all
else
rg -n '^#{1,6} ' "$f" || true
fi
done
printf '\n== Exact-head review-scope contents ==\n'
for f in \
SECURITY.md \
CHANGELOG.md \
docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md \
test/security-policy-contract.test.ts
do
printf '\n--- %s ---\n' "$f"
cat -n "$f"
done
printf '\n== Claims and regression anchors ==\n'
rg -n -i -C 3 \
'(report a vulnerability|when that control is available|private vulnerability reporting|enabled|monitored|staffed|exercised|notification subscription|response objective|security email|bounty|compensation|SLA|24.?7|production.ready|pre.release|safe harbor|prohibited|destructive|third.party|CVSS|KEV|known exploited|source identity|release identity|deployment identity|incident escalation|CVE|advisory|retention|APA|ISO/IEC|NIST)' \
SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts
printf '\n== Internal documentation links ==\n'
python3 - <<'PY'
import re
from pathlib import Path
for filename in (
"SECURITY.md",
"docs/security/vulnerability-handling.md",
"docs/doctoring/vulnerability-disclosure.md",
):
path = Path(filename)
print(f"\n{filename}")
for line_number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
for target in re.findall(r'\[[^\]]+\]\((?!https?://|#)([^)#]+)', line):
print(f"{line_number}: {target}: {'OK' if (path.parent / target).exists() else 'MISSING'}")
PY
printf '\n== Diff hygiene ==\n'
git diff --check "$base" "$head"
rg -n '^(<<<<<<<|=======|>>>>>>>)' \
SECURITY.md CHANGELOG.md docs/security/vulnerability-handling.md \
docs/doctoring/vulnerability-disclosure.md test/security-policy-contract.test.ts || trueLength of output: 118394 🤖 web_search executed: `Use primary sources only. Verify the following claims for a documentation review:
Length of output: 12197 🤖 web_search executed:
Length of output: 17412
I found no actionable findings in the requested scope. The regression contract now protects the operational boundary.
The reviewed documents are consistent:
The scoped inspection found no broken internal links, conflict markers, or whitespace errors. I did not execute tests. This review is current-head evidence only. It is not approval, merge authority, release authority, or deployment authority. It does not treat queued, failed, stale-head, or status-only evidence as success. ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/security/vulnerability-handling.md`:
- Line 147: Expand the evidence-retention guidance around “Retain only the data
necessary” to define bounded maximum retention periods for each evidence class,
the owner responsible for expiry review, role-based access, legal-hold
exceptions, and secure deletion or redaction evidence. Add contract tests that
lock these lifecycle requirements and explicitly cover reporter contact data,
PII, and secrets.
- Around line 43-48: 문서 절차에 SECURITY.md의 공개 fallback lifecycle을 추가하세요. Private
security contact requested 이슈의 담당자 지정, private channel 안내, 취약점 세부정보를 공개 이슈에 요청하지
않는 원칙, private case로 전환하는 단계를 명시하고, 6단계의 “public service objective”를
SECURITY.md의 published service objective와 동일한 용어로 변경하세요.
In `@test/security-policy-contract.test.ts`:
- Around line 89-90: Update the changelog assertion in the security policy
contract test to extract only the section beginning at the “## Unreleased”
heading and ending before the next “##” heading, then check that section for
“coordinated vulnerability disclosure”. Make the test fail when the “##
Unreleased” heading is absent.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: dcd0e23b-b32d-482c-8b63-278c1171e3e7
📒 Files selected for processing (5)
CHANGELOG.mdSECURITY.mddocs/doctoring/vulnerability-disclosure.mddocs/security/vulnerability-handling.mdtest/security-policy-contract.test.ts
Supersession state
This pre-#76 direct-main branch is now historical. Protected
mainhas advanced toc85d710804139c0697d7ef8fa47d02b1389e6d84with the bounded nanoid remediation integrated.Clean post-#76 successor Draft #95 (
docs/security): restack coordinated vulnerability disclosure after nanoid) preserves this PR's exact 10-path disclosure workstream on current protected main without package/lock/workflow drift. #95 head at successor creation is525aea3279ca3dcb4d84ff124496d6f338a7cf05; its fresh application CI, reviewer-ci and central Security Scan were queued at the latest read and are non-passing until terminal conclusions exist.Do not merge this stale branch and do not transfer this PR's old checks, reviews or integration evidence to #95. Keep #72 open only until #95 proves the bounded successor with fresh exact-head technical evidence; then close #72 as superseded rather than merging stale ancestry.
Preserved product boundary
The successor preserves:
SECURITY.mdwith pre-release support scope, private-first reporting, content-free fallback, bounded safe harbor, non-contractual response objectives, CVSS v4.0/exploitation-aware priority, coordinated disclosure and no invented bounty/support commitment;enabled === truesemantics;## Unreleasedchangelog entry.Operational gap remains separate
Neither #72 nor #95 proves that GitHub private vulnerability reporting is enabled/usable, reporter UI is visible, notification routing works, at least two security owners are staffed, or a benign end-to-end private report/advisory exercise passed. Issue #73 owns those live administrator/operational facts. Setting evidence cannot substitute for review, branch governance, release, deployment or acquisition evidence.
Merge / closure boundary
Related: #27, #29, #73, #76, #95