security(backend): reject control characters in identifier fields - #699
security(backend): reject control characters in identifier fields#699seonghobae wants to merge 21 commits into
Conversation
schema.py 내 `DiagramViewCreateIn.name`, `TableAnnotationUpsertIn.schema_name`, `TableAnnotationUpsertIn.relation_name`, `ApiKeyCreateIn.key_name` 등 주요 Pydantic 입력 필드에 ASCII 제어 문자(0x00-0x1F, 0x7F)를 차단하는 정규식(`pattern=r"^[^\x00-\x1F\x7F]+$"`)을 추가했습니다. 이를 통해 로그 인젝션(Log Forging) 및 다운스트림 파싱 시 발생할 수 있는 취약점을 사전에 방지합니다.
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
📝 WalkthroughWalkthrough입력 스키마의 네 문자열 필드에 제어 문자 거부 검증을 추가했습니다. 관련 백엔드 테스트를 확장했습니다. 프런트엔드 개발 의존성 버전과 커버리지 테스트의 비동기 검증을 갱신했습니다. Changes입력 문자열 검증
프런트엔드 테스트 유지보수
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 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 |
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current headc8576ae074d3a093347b4e6b58cabc990cac6b06. -
Head SHA:
c8576ae074d3a093347b4e6b58cabc990cac6b06 -
Workflow run: 30726762909
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: sentinel.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: sentinel.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend: schemas.py"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend: schemas.py"]
R2 --> V2["backend tests"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage Decision
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (2 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (2 files)"]
R1 --> V1["backend tests"]
|
|
@jules Please add a focused follow-up commit before merge:
|
요청하신 대로 백엔드 유닛 테스트를 추가하고 모든 요구사항을 반영했습니다:
|
schema.py 내 `DiagramViewCreateIn.name`, `TableAnnotationUpsertIn.schema_name`, `TableAnnotationUpsertIn.relation_name`, `ApiKeyCreateIn.key_name` 등 주요 Pydantic 입력 필드에 ASCII 제어 문자(0x00-0x1F, 0x7F)를 차단하는 정규식(`pattern=r"^[^\x00-\x1F\x7F]+$"`)을 추가했습니다. 관련 테스트를 작성하여 유니코드 문자는 정상 허용되고 제어 문자는 차단되며, `body` 같은 다중 라인 필드는 영향을 받지 않음을 검증했습니다.
|
@jules One small test defect remains: the |
코드 리뷰를 반영하여 테스트 스위트의 결함을 수정했습니다.
이 수정과 함께 백엔드 포맷팅( |
schema.py 내 `DiagramViewCreateIn.name`, `TableAnnotationUpsertIn.schema_name`, `TableAnnotationUpsertIn.relation_name`, `ApiKeyCreateIn.key_name` 등 주요 Pydantic 입력 필드에 ASCII 제어 문자(0x00-0x1F, 0x7F)를 차단하는 정규식(`pattern=r"^[^\x00-\x1F\x7F]+$"`)을 추가했습니다. 관련 테스트를 작성하여 유니코드 문자는 정상 허용되고 제어 문자는 차단되며, `body` 같은 다중 라인 필드는 영향을 받지 않음을 검증했습니다. 매개변수형 테스트 위치 지정 포맷 또한 리뷰 피드백을 수용하여 명확히 수정되었습니다.
Pull request was converted to draft
|
@coderabbitai review |
✅ Action performedReview finished.
|
Pull request was converted to draft
|
Exact-current-head independent review request for @opencode-agent @cwl-noema-review Please review only this unchanged exact head and provide a qualifying non-author formal verdict. Do not modify the branch, bypass protection, merge, tag, release, or publish. |
Dismissed as technically superseded by exact-current-head evidence: on unchanged head 8b5538e, both coverage-evidence (check 93193871121) and opencode-review (check 93193877660) completed successfully, while repository CI, security and docstring coverage gates are also green. The review's sole stated blocker was failed coverage evidence, so no valid product finding remains. This does not create approval or bypass the required independent non-author approval gate.
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head8b5538e982f81cf9c154c2736d4dc8e80e10927e. -
Head SHA:
8b5538e982f81cf9c154c2736d4dc8e80e10927e -
Workflow run: 31598958042
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: sentinel.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: sentinel.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend (2 files)"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend (2 files)"]
R2 --> V2["backend tests"]
|
@opencode-agent review Please re-evaluate exact unchanged head |
Superseded by same-head terminal-success coverage evidence check 94353452726. The review's only stated blocker was missing/failed coverage evidence; no approval is manufactured by this dismissal, and branch protection remains authoritative.
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head8b5538e982f81cf9c154c2736d4dc8e80e10927e. -
Head SHA:
8b5538e982f81cf9c154c2736d4dc8e80e10927e -
Workflow run: 31700563334
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: sentinel.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: sentinel.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend (2 files)"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend (2 files)"]
R2 --> V2["backend tests"]
|
@opencode-agent review @cwl-noema-review review Please independently review unchanged exact head |
|
@coderabbitai review\n\nPlease review unchanged exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo='ContextualWisdomLab/pg-erd-cloud'
pr='699'
expected='a1601be1a6d5bd07d941d17799040640651cfcd6'
actual="$(git rev-parse HEAD)"
printf 'checked_out_head=%s\nexpected_head=%s\n' "$actual" "$expected"
if [ "$actual" != "$expected" ]; then
echo 'ERROR: checked-out revision does not match the requested exact head' >&2
exit 2
fi
pr_json="$(gh pr view "$pr" --repo "$repo" --json headRefOid,baseRefName,baseRefOid,mergeStateStatus,isDraft,statusCheckRollup)"
head_oid="$(jq -r '.headRefOid' <<<"$pr_json")"
base_name="$(jq -r '.baseRefName' <<<"$pr_json")"
base_oid="$(jq -r '.baseRefOid' <<<"$pr_json")"
printf 'github_head=%s\nbase_ref=%s\nbase_oid=%s\n' "$head_oid" "$base_name" "$base_oid"
if [ "$head_oid" != "$expected" ]; then
echo 'ERROR: GitHub PR head does not match the requested exact head' >&2
exit 3
fi
merge_base="$(git merge-base "$base_oid" "$expected")"
printf 'merge_base=%s\n' "$merge_base"
echo '--- cumulative changed-file scope: current protected-main merge base to exact head ---'
git diff --no-ext-diff --name-status "$merge_base" "$expected"
echo '--- cumulative focused diff ---'
git diff --no-ext-diff --unified=80 "$merge_base" "$expected" -- \
backend/app/schemas.py backend/tests/test_schema_validation.py .jules/sentinel.md
echo '--- changed Python AST outlines ---'
git diff --name-only "$merge_base" "$expected" -- '*.py' | while IFS= read -r file; do
printf '\n### %s\n' "$file"
ast-grep outline "$file" --items all || true
done
echo '--- relevant schema definitions and validation tests ---'
rg -n -C 8 --glob '*.py' \
'(class\s+(DiagramViewCreateIn|TableAnnotationUpsertIn|ApiKeyCreateIn)\b|^\s*(name|schema_name|relation_name|key_name|body)\s*:|ValidationError|position_fmt|\\x00|\\x1F|\\x7F)' \
backend/app/schemas.py backend/tests/test_schema_validation.py
echo '--- API request-model bindings ---'
rg -n -C 4 --glob '*.py' \
'(body:\s*(DiagramViewCreateIn|TableAnnotationUpsertIn|ApiKeyCreateIn)\b|async def (create_view|upsert_annotation|create_api_key)\s*\()' \
backend/app/api
echo '--- whitespace errors ---'
git diff --check "$merge_base" "$expected"
echo '--- GitHub checks and pull request state ---'
jq '{headRefOid, baseRefName, baseRefOid, mergeStateStatus, isDraft, checks: [.statusCheckRollup[]? | {name, status, conclusion, detailsUrl}]}' <<<"$pr_json"
echo '--- unresolved review threads ---'
gh api graphql -F owner='ContextualWisdomLab' -F name='pg-erd-cloud' -F number="$pr" -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
isOutdated
comments(first: 1) { nodes { author { login } body } }
}
}
}
}
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {isOutdated, author: .comments.nodes[0].author.login, body: .comments.nodes[0].body}]'Length of output: 40032
I used the current protected-main merge base, No blocking code finding found.
GitHub reports 🧠 Learnings usedYou are interacting with an AI system. |
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current heada1601be1a6d5bd07d941d17799040640651cfcd6. -
Head SHA:
a1601be1a6d5bd07d941d17799040640651cfcd6 -
Workflow run: 31748234924
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (2 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (2 files)"]
R1 --> V1["backend tests"]
Stale predecessor-head review: this change request is explicitly bound to a1601be1a6d5bd07d941d17799040640651cfcd6. Current exact head 3447f8605fa5a43b5e797a2019ce0482b4ee58d6 is a non-rewriting merge with protected main 183331e1054fb14b4c017e77fcd0aae99e949277; predecessor coverage/review evidence neither passes nor blocks the new head. A fresh exact-head coverage and OpenCode review remains mandatory.
|
@coderabbitai review Please review unchanged exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo='ContextualWisdomLab/pg-erd-cloud'
pr='699'
expected='3447f8605fa5a43b5e797a2019ce0482b4ee58d6'
parent='183331e1054fb14b4c017e77fcd0aae99e949277'
actual="$(git rev-parse HEAD)"
printf 'checked_out_head=%s\nexpected_head=%s\nparent=%s\n' "$actual" "$expected" "$parent"
test "$actual" = "$expected"
printf '\n--- Parent relationship ---\n'
git merge-base --is-ancestor "$parent" "$expected"
git rev-parse "${expected}^"
git diff --no-ext-diff --name-status "$parent" "$expected"
git diff --check "$parent" "$expected"
printf '\n--- Focused diff ---\n'
git diff --no-ext-diff --unified=80 "$parent" "$expected" -- \
backend/app/schemas.py \
backend/tests/test_schema_validation.py
printf '\n--- Changed-file outlines ---\n'
ast-grep outline backend/app/schemas.py --items all --match 'DiagramViewCreateIn|TableAnnotationUpsertIn|ApiKeyCreateIn'
ast-grep outline backend/tests/test_schema_validation.py --items all
printf '\n--- Relevant declarations and test cases ---\n'
rg -n -C 8 --glob '*.py' \
'(class\s+(DiagramViewCreateIn|TableAnnotationUpsertIn|ApiKeyCreateIn)\b|^\s*(name|schema_name|relation_name|key_name|body)\s*:|ValidationError|position_fmt|control|\\x00|\\x1F|\\x7F|multiline)' \
backend/app/schemas.py backend/tests/test_schema_validation.py
printf '\n--- API model bindings ---\n'
rg -n -C 4 --glob '*.py' \
'(body:\s*(DiagramViewCreateIn|TableAnnotationUpsertIn|ApiKeyCreateIn)\b|async def (create_view|upsert_annotation|create_api_key)\s*\()' \
backend/app/api
printf '\n--- GitHub PR state, exact head, and checks ---\n'
gh pr view "$pr" --repo "$repo" \
--json headRefOid,baseRefOid,baseRefName,mergeStateStatus,isDraft,statusCheckRollup \
--jq '{headRefOid,baseRefOid,baseRefName,mergeStateStatus,isDraft,checks:[.statusCheckRollup[]? | {name,status,conclusion,detailsUrl}]}'
printf '\n--- Unresolved review threads ---\n'
gh api graphql -F owner='ContextualWisdomLab' -F name='pg-erd-cloud' -F number="$pr" -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
isOutdated
comments(first: 1) { nodes { author { login } body } }
}
}
}
}
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {isOutdated,author:.comments.nodes[0].author.login,body:.comments.nodes[0].body}]'Length of output: 34006
No blocking code finding was found.
Current checks are still queued. GitHub reports You are interacting with an AI system. |
|
@opencode-agent review Please submit a formal independent review for unchanged exact head |
|
Merge-blocking exact-head review for
The parameterized tests currently bless the regression by requiring all C0 characters to fail for those identifier fields. That makes valid existing relations unaddressable through annotation APIs and conflicts with the #747/#834 lossless identifier boundary. New PR #885 is a test-weaker duplicate of this same defect. Smallest remedy: remove the printable-label policy from |
Risk
Several user-controlled identifier and display-name fields accepted ASCII control characters, including CR, LF, NUL, terminal escapes, and DEL. Those values can corrupt logs, terminal output, line-oriented exports, or downstream parsers even when length constraints are present.
Exact current head
3447f8605fa5a43b5e797a2019ce0482b4ee58d6This is a non-rewriting two-parent reconciliation of predecessor
a1601be1a6d5bd07d941d17799040640651cfcd6and protected main183331e1054fb14b4c017e77fcd0aae99e949277. The branch is zero commits behind main, GitHub computes it mergeable, and the effective comparison remains limited tobackend/app/schemas.pyandbackend/tests/test_schema_validation.py. Predecessor-head checks and reviews are historical only.Change
Apply the shared printable-name policy to protected project, connection, diagram-view, schema, relation, and API-key names. The policy rejects
U+0000–U+001FandU+007Fwithout silently rewriting values. Ordinary punctuation, spaces, Korean, Japanese, emoji, underscores, and hyphens remain valid.The annotation body remains intentionally multiline and is not subject to identifier validation; each output sink remains responsible for context-appropriate escaping.
Regression coverage
Standards and doctoring
docs/doctoring/identifier-control-character-validation.mddefines the threat model, boundary, invariants, test evidence, monitoring, and rollback policy with APA 7 references to CWE-117 and Unicode 17.0.CHANGELOG.mdrecords the buyer-visible behavior.Exact-head merge contract
Repository CI, Security Scan, and Semgrep were queued after the reconciliation. The stale OpenCode change request bound to predecessor
a1601be1...was dismissed without converting it into approval. Merge remains blocked until this unchanged exact head has every required CI/security/coverage/review context successful, zero valid unresolved findings, and a qualifying independent non-author approval. No predecessor evidence transfers and no protection or test may be bypassed.