Skip to content

security(api): reject non-text controls in multiline SQL - #832

Open
seonghobae wants to merge 10 commits into
mainfrom
codex/sql-control-validation
Open

security(api): reject non-text controls in multiline SQL#832
seonghobae wants to merge 10 commits into
mainfrom
codex/sql-control-validation

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • reject NUL, every non-text C0 control, DEL, and the complete C1 block (U+007F–U+009F) at the ApplySqlIn request-schema boundary
  • preserve tab, LF, CR, printable Unicode, and the existing 262,144-character size limit
  • redact raw rejected inputs from application-wide FastAPI 422 validation responses so SQL and credential-bearing values are not reflected
  • preserve the deterministic DDL allowlist as the separate execution authority
  • document the transport/log-integrity boundary and its failure behavior

Test-first evidence

  • original RED: 91 focused failures before the validator/response handler existed
  • C1 extension RED on predecessor fcc908e60d54a8ccfa9c6f2440f1c6984fb52e71: 96 missing beginning/middle/end cases for U+0080–U+009F
  • GREEN: 187 exhaustive apply-SQL control cases; 192 schema-validation tests
  • full backend: 570 passed, 1 skipped
  • changed production module: app/schemas.py 148/148 statements and 2/2 branches (100%)
  • mypy: clean across 68 source files
  • git diff --check: clean

The first local full-suite probe inherited the sandbox SOCKS proxy and failed only three Clearfolio HTTPX constructors because the hash-locked environment intentionally lacks socksio; removing uppercase and lowercase proxy transport variables produced the full green result above, matching CI’s test boundary.

No dependency, lockfile, database migration, frontend, or workflow changes.

Closes #764.

Exact-head reconciliation

Head 7aff5c8524d82d52a93c86028bd16bc0f396737f merges protected main 3c1c7aae7b72e34ca9b48b578b0573736daba8fd; the sole changelog conflict preserved all three entries. Local combined-tree evidence passed 233 focused security/identifier tests, the full backend suite (596 passed, 1 skipped), mypy across 69 source files, and diff check. GitHub exact-head checks and independent review are rerunning and remain authoritative.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@opencode-agent[bot], you've reached your PR review limit, so we couldn't start this review.

Next review available in: 85 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: de0429be-dfc4-4ceb-8f18-15e7150e1285

📥 Commits

Reviewing files that changed from the base of the PR and between 1f8b859 and 6b2c0f4.

📒 Files selected for processing (16)
  • CHANGELOG.md
  • backend/app/api/dbml.py
  • backend/app/ddl/export.py
  • backend/app/ddl/identifiers.py
  • backend/app/pg_introspect/forward_ddl.py
  • backend/app/schemas.py
  • backend/app/snowflake_introspect/introspect.py
  • backend/app/spec/dbml_import.py
  • backend/app/spec/index_design.py
  • backend/tests/test_api_connections.py
  • backend/tests/test_dbml_import.py
  • backend/tests/test_index_design.py
  • backend/tests/test_pooler.py
  • backend/tests/test_schema_validation.py
  • docs/security/apply-sql-transport-validation.md
  • docs/security/dbml-identifier-boundary.md
📝 Walkthrough

Walkthrough

ApplySqlIn이 허용된 공백과 Unicode를 보존하면서 비텍스트 제어 문자와 DEL을 거부합니다. FastAPI 422 검증 응답은 원본 입력을 제거합니다. 관련 테스트와 보안 문서를 추가하고 기존 권한, DSN, 헤더 동작을 검증합니다.

Changes

SQL 전송 보안

Layer / File(s) Summary
ApplySqlIn 제어 문자 검증
backend/app/schemas.py
탭, LF, CR과 Unicode는 유지하고 비텍스트 C0 제어 문자 및 DEL이 포함된 SQL은 거부합니다.
검증 오류 응답 정제
backend/app/main.py
RequestValidationError 처리기가 원본 input을 제거하고 안전한 오류 정보만 HTTP 422 응답에 포함합니다.
SQL 검증 수용 기준과 문서
backend/tests/test_schema_validation.py, backend/tests/test_api_connections.py, docs/security/apply-sql-transport-validation.md, CHANGELOG.md
허용 문자 보존, 제어 문자 위치별 거부, 응답과 로그의 원문 제거를 검증하고 변경 내용을 문서화합니다.

기존 동작 회귀 검증

Layer / File(s) Summary
기존 동작 회귀 테스트
backend/tests/test_permissions.py, backend/tests/test_pooler.py, backend/tests/test_security_headers.py
최소 역할이 없는 viewer 검증, pgcat DSN 생성, 기존 X-Frame-Options 값 보존을 검증합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant FastAPI
  participant ApplySqlIn
  participant redact_request_validation_input
  Client->>FastAPI: /apply-sql 요청
  FastAPI->>ApplySqlIn: sql 필드 검증
  ApplySqlIn-->>FastAPI: ValidationError
  FastAPI->>redact_request_validation_input: RequestValidationError 전달
  redact_request_validation_input-->>Client: 입력값이 제거된 422 응답
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning [#764]와 직접 관련 없는 권한, 풀러 DSN, 보안 헤더 테스트 변경이 포함되어 범위를 벗어납니다. 관련 없는 test_permissions.py, test_pooler.py, test_security_headers.py 변경을 별도 PR로 분리하거나 제거하십시오.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed [#764] 제어 문자 거부, 허용 문자 보존, 입력값 비노출, 경계 테스트, 문서 갱신 요구를 구현과 테스트로 충족합니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 멀티라인 SQL에서 비텍스트 제어 문자를 거부하는 핵심 변경을 정확하고 간결하게 설명합니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/sql-control-validation

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/security/apply-sql-transport-validation.md (1)

35-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

문헌별 근거 요약을 추가하십시오.

현재 References에는 인용과 링크가 있지만 각 문헌이 어떤 검증 경계를 뒷받침하는지 설명이 없습니다. 각 참조 아래에 이 PR의 JSON transport, PostgreSQL lexical 처리, 또는 Unicode control-character 분류와의 관련성을 한 문장으로 추가하십시오.

As per coding guidelines, substantive pull requests must provide relevant citations, links, and summaries when permissible paper PDFs are not attached.

🤖 Prompt for 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.

In `@docs/security/apply-sql-transport-validation.md` around lines 35 - 45, 각 참고문헌
항목 아래에 해당 자료가 뒷받침하는 검증 경계를 한 문장으로 요약하십시오. Bray의 RFC 8259는 JSON transport 검증,
PostgreSQL 문헌은 lexical 처리, Unicode 표준은 control-character 분류와 연결되도록 작성하고 기존 인용 및
링크는 유지하십시오.

Source: Coding guidelines

🤖 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 `@backend/tests/test_api_connections.py`:
- Around line 192-200: Ruff S105를 피하도록 테스트의 하드코딩된 비밀번호 marker를 여러 비밀이 아닌 문자열
조각으로 분리하십시오. test_api_connections의 해당 테스트에서 조각을 결합해 SQL의 credential 기본값을 만들고,
동일한 결합 값을 응답 및 로그 비노출 assertion에 재사용하십시오.

In `@backend/tests/test_pooler.py`:
- Around line 41-47: Update the test input surrounding the DSN construction so
the PostgreSQL URL is assembled at runtime from non-sensitive components rather
than committed as a full DSN containing credentials and connection details.
Remove the hardcoded password literal and the `# noqa: S105` suppression while
preserving the existing DSN and password assertions.

---

Nitpick comments:
In `@docs/security/apply-sql-transport-validation.md`:
- Around line 35-45: 각 참고문헌 항목 아래에 해당 자료가 뒷받침하는 검증 경계를 한 문장으로 요약하십시오. Bray의 RFC
8259는 JSON transport 검증, PostgreSQL 문헌은 lexical 처리, Unicode 표준은
control-character 분류와 연결되도록 작성하고 기존 인용 및 링크는 유지하십시오.
🪄 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: 5386a4d2-f966-40fa-838e-100bbbdae878

📥 Commits

Reviewing files that changed from the base of the PR and between 72afe6d and 1f8b859.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • backend/app/main.py
  • backend/app/schemas.py
  • backend/tests/test_api_connections.py
  • backend/tests/test_permissions.py
  • backend/tests/test_pooler.py
  • backend/tests/test_schema_validation.py
  • backend/tests/test_security_headers.py
  • docs/security/apply-sql-transport-validation.md

Comment thread backend/tests/test_api_connections.py Outdated
Comment thread backend/tests/test_pooler.py Outdated

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Please review the unchanged exact head fcc908e60d54a8ccfa9c6f2440f1c6984fb52e71. All prior inline findings are resolved and CI, Security Scan, and SAST Semgrep pass on this head.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

@seonghobae I will run a full review of PR #832 at commit fcc908e60d54a8ccfa9c6f2440f1c6984fb52e71. This review will re-evaluate the existing changes.

⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 35 minutes.

Copy link
Copy Markdown
Collaborator Author

Exact-current-head independent review request for fcc908e60d54a8ccfa9c6f2440f1c6984fb52e71.

@opencode-agent @cwl-noema-review Please provide a qualifying non-author review of this unchanged predecessor. CI 31320017558, Security Scan 31320017576, and SAST Semgrep 31320017539 are terminal-success on this SHA, and there are zero unresolved review threads. CodeRabbit's last retry was rate-limited and is not approval evidence. Do not mutate the branch or merge.

Copy link
Copy Markdown
Collaborator Author

Exact-current-head independent review request for 5bf6cc56ca4e80d89fed852362a6ae4f8717be98.

@opencode-agent @cwl-noema-review Please review this unchanged exact head and provide a qualifying non-author formal verdict. Current-head CI 31479659678, Security Scan 31479659654, and SAST Semgrep 31479659679 are terminal-success; all prior inline threads are resolved. The successor adds exhaustive C1 (U+0080–U+009F) rejection coverage and implementation without changing the deterministic DDL execution authority.

* security(dbml): enforce identifier rendering boundary

* test(dbml): fuzz identifier round trips

* fix(dbml): reject trailing reference tokens

* fix(dbml): fail closed on oversized input

* fix(dbml): preserve named reference blocks

Copy link
Copy Markdown
Collaborator Author

@opencode-agent review
@cwl-noema-review review

Please independently review exact unchanged head d775e88abfdaec306758991df33358514c7b6eef for non-text control rejection in multiline SQL requests. All reported exact-head checks are terminal-success and zero inline threads remain. Submit a qualifying formal verdict only if this exact head has no blocker; do not modify the branch or bypass protections.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head d775e88abfdaec306758991df33358514c7b6eef.

  • Head SHA: d775e88abfdaec306758991df33358514c7b6eef

  • Workflow run: 31700722778

  • 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: CHANGELOG.md"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
  R1 --> V1["required checks"]
  Evidence --> S2["Backend (16 files)"]
  S2 --> I2["API and service runtime"]
  I2 --> R2["Review risk: Backend (16 files)"]
  R2 --> V2["backend tests"]
  Evidence --> S3["Docs (2 files)"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs (2 files)"]
  R3 --> V3["docs review"]
Loading

@opencode-agent

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: d775e88abfdaec306758991df33358514c7b6eef
  • Workflow run: 31700722778
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head d775e88abfdaec306758991df33358514c7b6eef.

  • Head SHA: d775e88abfdaec306758991df33358514c7b6eef

  • Workflow run: 31700722778

  • 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: CHANGELOG.md"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
  R1 --> V1["required checks"]
  Evidence --> S2["Backend (16 files)"]
  S2 --> I2["API and service runtime"]
  I2 --> R2["Review risk: Backend (16 files)"]
  R2 --> V2["backend tests"]
  Evidence --> S3["Docs (2 files)"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs (2 files)"]
  R3 --> V3["docs review"]
Loading

Copy link
Copy Markdown
Collaborator Author

@opencode-agent review

Please re-evaluate unchanged exact head d775e88abfdaec306758991df33358514c7b6eef. The current formal CHANGES_REQUESTED verdict reports failed same-head coverage evidence, but GitHub now records coverage-evidence as terminal success (https://github.com/ContextualWisdomLab/pg-erd-cloud/actions/runs/31667163798/job/94352213812), with repository CI/security and all organization-required workflows also successful and zero unresolved review threads. The bounded product scope is non-text SQL-control rejection plus validation-response confidentiality and deterministic identifier-sink hardening covered by focused security contracts. Please submit a new formal verdict anchored only to this SHA.

Copy link
Copy Markdown
Collaborator Author

@opencode-agent review
@coderabbitai review

Please re-evaluate unchanged exact head 7aff5c8524d82d52a93c86028bd16bc0f396737f. The stale formal change request was based on an earlier coverage-evidence failure; GitHub now records same-head repository CI, Security Scan, and SAST Semgrep as terminal success after the cancelled dependency-root jobs were rerun successfully. All inline threads are resolved. Verify the bounded SQL-control validation and submit a qualifying exact-head verdict only if every required current-head gate is satisfied. Do not modify or merge.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

sha="7aff5c8524d82d52a93c86028bd16bc0f396737f"
repo="ContextualWisdomLab/pg-erd-cloud"

printf '%s\n' '== Checked-out commit =='
git rev-parse HEAD
git status --short
git cat-file -e "${sha}^{commit}"
git merge-base --is-ancestor "$sha" HEAD && echo "requested SHA is reachable from HEAD"

printf '%s\n' '== PR metadata and exact-head verification =='
gh pr view 832 --repo "$repo" --json number,headRefOid,state,isDraft,url \
  --jq '{number, state, isDraft, url, headRefOid, exact_head: (.headRefOid == "'"$sha"'")}'

printf '%s\n' '== Changed files and stat =='
git diff --stat "${sha}^" "$sha"
git diff --name-status "${sha}^" "$sha"

printf '%s\n' '== Source/test outlines =='
ast-grep outline backend/app/schemas.py --match 'ApplySqlIn' --view expanded
ast-grep outline backend/app/main.py --match 'redact_request_validation_input' --view expanded
ast-grep outline backend/tests/test_schema_validation.py --match 'apply_sql' --view expanded
ast-grep outline backend/tests/test_api_connections.py --match 'validation' --view expanded

printf '%s\n' '== Exact changed hunks =='
git diff --unified=80 "${sha}^" "$sha" -- backend/app/schemas.py backend/app/main.py backend/tests/test_schema_validation.py backend/tests/test_api_connections.py docs/security/apply-sql-transport-validation.md CHANGELOG.md

printf '%s\n' '== Checks on requested SHA =='
gh api "repos/${repo}/commits/${sha}/check-runs?per_page=100" --paginate \
  --jq '.check_runs[] | [.name, .status, .conclusion, .details_url] | `@tsv`' | sort

printf '%s\n' '== Review threads =='
gh api graphql -F owner="ContextualWisdomLab" -F name="pg-erd-cloud" -F number=832 -f query='
query($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    pullRequest(number: $number) {
      reviewThreads(first: 100) {
        nodes { isResolved comments(first: 1) { nodes { author { login } body } } }
      }
    }
  }
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length'

Length of output: 9073


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sha="7aff5c8524d82d52a93c86028bd16bc0f396737f"
repo="ContextualWisdomLab/pg-erd-cloud"

printf '%s\n' '== PR base and full changed files =='
base_sha=$(gh pr view 832 --repo "$repo" --json baseRefOid --jq .baseRefOid)
base_ref=$(gh pr view 832 --repo "$repo" --json baseRefName --jq .baseRefName)
printf 'base_ref=%s\nbase_sha=%s\nhead_sha=%s\n' "$base_ref" "$base_sha" "$sha"
git diff --name-status "$base_sha" "$sha"

printf '%s\n' '== Current request schema and error handler =='
sed -n '60,115p' backend/app/schemas.py
sed -n '50,115p' backend/app/main.py

printf '%s\n' '== Current focused validation tests =='
sed -n '1,125p' backend/tests/test_schema_validation.py
sed -n '155,235p' backend/tests/test_api_connections.py

printf '%s\n' '== Full PR diff for SQL-control boundary =='
git diff --unified=35 "$base_sha" "$sha" -- \
  backend/app/schemas.py \
  backend/app/main.py \
  backend/tests/test_schema_validation.py \
  backend/tests/test_api_connections.py \
  docs/security/apply-sql-transport-validation.md \
  CHANGELOG.md

printf '%s\n' '== Branch protection / rulesets =='
gh api "repos/${repo}/branches/${base_ref}/protection/required_status_checks" 2>&1 || true
gh api "repos/${repo}/rules/branches/${base_ref}" 2>&1 || true

printf '%s\n' '== Remaining current-SHA checks =='
gh api "repos/${repo}/commits/${sha}/check-runs?per_page=100" --paginate \
  --jq '.check_runs[] | select(.status != "completed" or .conclusion != "success") | [.name, .status, .conclusion, .details_url] | `@tsv`' | sort

Length of output: 34008


@seonghobae I reviewed exact head 7aff5c8524d82d52a93c86028bd16bc0f396737f.

I found no blocker in the bounded SQL-control validation.

  • ApplySqlIn.reject_non_text_controls() preserves tab, LF, CR, and Unicode.
  • It rejects the specified C0 controls, DEL, and C1 controls.
  • The regression tests cover each rejected code point at the beginning, middle, and end of DDL input.
  • The application-wide RequestValidationError handler removes the raw input field from 422 responses.
  • The HTTP regression test verifies that secret-bearing SQL is absent from the response and captured logs.
  • The PR has zero unresolved review threads.

I cannot submit a qualifying exact-head verdict yet.

The organization-required strix.yml workflow is still in progress on this SHA. coverage-source-tree is also queued. The branch protection endpoint was not accessible to this integration, but the organization ruleset explicitly requires strix.yml. No branch changes or merge actions were performed.


🧠 Learnings used
Learnt from: seonghobae
Repo: ContextualWisdomLab/pg-erd-cloud PR: 834
File: docs/TEST_STRATEGY.md:0-0
Timestamp: 2026-08-09T14:44:31.377Z
Learning: For ContextualWisdomLab/pg-erd-cloud, organization-required pull-request workflows centrally operate the authoritative `osv-scan`, `dependency-review`, `trivy-fs`, OpenSSF Scorecard, and separate SAST Semgrep checks. Leaf repository workflows must require exact-head results from these checks but must not duplicate their implementation.

Learnt from: CR
Repo: ContextualWisdomLab/pg-erd-cloud PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-07-31T12:38:25.676Z
Learning: Applies to **/* : Every pull request must pass the required Security Scan gate: `osv-scan`, diff-scoped `dependency-review` for Medium and above, and repo-wide `trivy-fs` for CRITICAL/HIGH/MEDIUM findings.

Learnt from: seonghobae
Repo: ContextualWisdomLab/pg-erd-cloud PR: 0
File: :0-0
Timestamp: 2026-08-11T17:35:50.945Z
Learning: In PR `#834`, `backend/app/forward/live_preflight.py` is an execution-neutral primitive for structured `table_is_empty`, `no_null_values`, and `castable_values` preconditions. It server-quotes identifiers, uses the canonical PostgreSQL type allow-list, enforces at most 1,000 queries, runs a read-only repeatable-read transaction with bounded timeouts, and returns only boolean evidence. It must not own target credentials, worker lifecycle, run transitions, sandboxing, DDL, or apply authority.

Learnt from: seonghobae
Repo: ContextualWisdomLab/pg-erd-cloud PR: 0
File: :0-0
Timestamp: 2026-08-11T19:37:25.016Z
Learning: In PR `#834`, `backend/app/forward/live_preflight.py` must sanitize driver failures from transaction construction, transaction startup, query execution, and rollback. It must expose only fixed `LivePreflightContractError` diagnostics without a cause or context for ordinary driver failures, and must call rollback only after transaction startup succeeds.

You are interacting with an AI system.

Copy link
Copy Markdown
Collaborator Author

Exact-head Strix RCA for 7aff5c8524d82d52a93c86028bd16bc0f396737f: rerun job 94520531555 is a genuine non-passing gate and must remain blocking. Three NVIDIA attempts hit HTTP 429; the fallback then emitted artifact 9190478312. Its sole HIGH item explicitly says no credential or exploitable vulnerability was found and identifies SQL parser punctuation ((, ), ,) in backend/app/pg_introspect/forward_ddl.py as Bandit B105 false positives. The supplied PoC is only an echo stating no exploit. The workflow nevertheless failed closed because it could not safely map/normalize that contradictory report. No #nosec, allow-list, gate bypass, branch mutation, or merge is justified. A fresh provider-backed Strix success or a reviewed central-workflow correction is still required; coverage remains queued.

@seonghobae
seonghobae dismissed opencode-agent[bot]’s stale review August 13, 2026 18:48

Dismissed as predecessor-only evidence: this review explicitly binds its coverage failure to d775e88. Current exact head 7aff5c8 has same-head coverage-evidence, coverage-source-tree, opencode-review, backend, frontend, CI, and security checks successful; only the separately queued Strix run remains non-passing and is not treated as approval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security(api): reject non-text controls in multiline SQL requests

1 participant