Skip to content

fix(security): patch cryptography PKCS#7 oracle - #1004

Merged
seonghobae merged 4 commits into
developfrom
security/cryptography-cve-2026-69247
Sep 1, 2026
Merged

fix(security): patch cryptography PKCS#7 oracle#1004
seonghobae merged 4 commits into
developfrom
security/cryptography-cve-2026-69247

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Verification

  • uv pip compile --generate-hashes --python-version 3.13 --universal --upgrade-package cryptography requirements-release.in -o requirements-release.txt
  • uv pip install --python .venv/bin/python --require-hashes -r requirements-release.txt
  • Linux-targeted dry-run selects cryptography==50.0.0 with --python-platform linux.
  • .venv/bin/pip-audit -r requirements-release.txt → no known vulnerabilities.
  • uv run appguardrail scan --codegraph . → 0 deploy blockers.

The release workflows continue to install only the hash-pinned requirements-release.txt; no application runtime dependency boundary was broadened.


Open in Devin Review

Summary by CodeRabbit

  • 보안 업데이트

    • 암호화 라이브러리를 50.0.0으로 업데이트하여 CVE-2026-69247의 영향 범위를 벗어나도록 개선했습니다.
  • 의존성 업데이트

    • 릴리스 패키지 잠금 정보를 최신 상태로 갱신했습니다.
    • 플랫폼 및 Python 환경별 의존성 조건을 정비했습니다.
    • 일부 패키지를 추가·제거하고 의존성 구성을 간소화했습니다.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a282411f-3324-4183-8471-4ec77d67a785

📥 Commits

Reviewing files that changed from the base of the PR and between a68b57d and ff95e69.

📒 Files selected for processing (1)
  • requirements-release.txt

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

requirements-release.txt를 uv로 재생성했습니다. 패키지 버전, extras, 해시, 플랫폼 및 아키텍처 조건, 의존성 주석을 갱신했습니다.

Changes

릴리스 의존성

Layer / File(s) Summary
의존성 선언 및 환경 조건 갱신
requirements-release.txt
cryptography50.0.0으로 갱신하고 pip==26.2.1, pywin32-ctypes==0.2.3, colorama를 추가했습니다. cachecontroljsonschema의 extras를 조정했습니다. 여러 패키지에 플랫폼, Python 구현 및 CPU 아키텍처 조건을 적용했습니다. 해시와 의존성 주석을 재생성했습니다.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk: ⚪ Minimal · up to ff95e

This PR updates the hash-pinned release dependency lockfile to the patched cryptography release without broadening the application runtime dependency boundary. No actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 cryptography를 보안 취약점이 수정된 버전으로 업데이트하는 주요 변경 사항과 PKCS#7 오라클 문제를 명확하게 설명합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/cryptography-cve-2026-69247

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.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent @cwl-noema-review @coderabbitai please review the exact current PR head ff95e69.\n\nThis is a dependency-security remediation for Dependabot alert #1 (CVE-2026-69247 / GHSA-g6cj-pr64-35w5): the hash-pinned release-tooling lock updates transitive cryptography from 49.0.0 to first patched 50.0.0 using the documented uv compile command. Local evidence: hash-enforced install passed; Linux-targeted dry-run selects cryptography==50.0.0; pip-audit reports no known vulnerabilities; uv run appguardrail scan --codegraph . reports 0 deploy blockers. Please validate this current head and report any actionable finding with exact file/line and reproducible evidence.

@devin-ai-integration devin-ai-integration 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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent @cwl-noema-review @coderabbitai please review the exact current PR head .\n\nThis is a dependency-security remediation for Dependabot alert #1 (CVE-2026-69247 / GHSA-g6cj-pr64-35w5): the hash-pinned release-tooling lock updates transitive from 49.0.0 to first patched 50.0.0 using the documented uv compile command. Local evidence: hash-enforced install passed; Linux-targeted dry-run selects ; pip-audit reports no known vulnerabilities;
🔍 AppGuardrail scanning: /Users/seonghobae/Documents/ChatGPT/appguardrail

🧭 CodeGraph enabled: initializing or syncing structural index

CodeGraph Status

Project: /Users/seonghobae/Documents/ChatGPT/appguardrail

Index Statistics:
Files: 158
Nodes: 2,675
Edges: 6,526
DB Size: 7.79 MB
Backend: node:sqlite — built-in (full WAL)
Journal: wal

Nodes by Kind:
function 1,297
import 515
variable 323
method 263
class 144
file 133

Files by Language:
python 133
yaml 25

✓ Index is up to date

🧩 Detected language axes: python, web
🧭 Beginner profile: Python web application
Python web markers detected; AppGuardrail will prioritize web auth, deserialization, TLS, CORS, rendering, and dependency review.
Framework signals: templates
Optional external engines: bandit, ruff, semgrep, trivy
ZAP baseline: provide --zap-baseline for authorized DAST

⚙️ External auto mode:
Skipped Bandit: executable not found or not runnable
Skipped Ruff security rules: executable not found or not runnable

🔎 Semgrep enabled: config auto

[🔴 CRITICAL] checklists/secrets.md:65
Rule: next-public-secret
Details: appguardrail-rule | secrets | doc
Message: Secret environment variable uses NEXT_PUBLIC_ prefix — this exposes it to the browser bundle. [OWASP A05:2021 - Security Misconfiguration]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] checklists/secrets.md:65
Rule: nextjs-env-secret-client-prefix
Details: appguardrail-rule | secrets | doc
Message: Secret environment variable uses NEXT_PUBLIC_ prefix, which exposes it
in the browser bundle. Remove the NEXT_PUBLIC_ prefix and ensure it is
only referenced in server-side code.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] checklists/secrets.md:65
Rule: stripe-secret-key-client-exposure
Details: appguardrail-rule | secrets | doc
Message: Stripe secret key appears to use NEXT_PUBLIC_ prefix, which exposes it
to the browser. Remove the NEXT_PUBLIC_ prefix immediately. The Stripe
secret key must only be used server-side.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] checklists/secrets.md:65
Rule: stripe-secret-key-client-exposure
Details: appguardrail-rule | secrets | doc
Message: Stripe secret key appears to use NEXT_PUBLIC_ prefix, which exposes it
to the browser. Remove the NEXT_PUBLIC_ prefix immediately. The Stripe
secret key must only be used server-side.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] checklists/stripe.md:62
Rule: stripe-secret-key-client-exposure
Details: appguardrail-rule | secrets | doc
Message: Stripe secret key appears to use NEXT_PUBLIC_ prefix, which exposes it
to the browser. Remove the NEXT_PUBLIC_ prefix immediately. The Stripe
secret key must only be used server-side.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_issueops_core.py:158
Rule: hardcoded-api-credential
Details: appguardrail-rule | secrets | test
Message: Hardcoded API credential detected. Move credentials to secret storage and rotate any committed value. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_issueops_core.py:159
Rule: hardcoded-api-credential
Details: appguardrail-rule | secrets | test
Message: Hardcoded API credential detected. Move credentials to secret storage and rotate any committed value. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_more_secret_rules.py:20
Rule: hardcoded-slack-token
Details: appguardrail-rule | secrets | test
Message: Hardcoded Slack token detected (xoxb/xoxa/xoxp/xoxr/xoxs prefix). This
grants access to your Slack workspace and its data. Revoke it in the Slack
app settings, rotate it, and store it as an environment variable.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_more_secret_rules.py:21
Rule: hardcoded-slack-token
Details: appguardrail-rule | secrets | test
Message: Hardcoded Slack token detected (xoxb/xoxa/xoxp/xoxr/xoxs prefix). This
grants access to your Slack workspace and its data. Revoke it in the Slack
app settings, rotate it, and store it as an environment variable.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_secret_injection_rules.py:19
Rule: hardcoded-aws-access-key-id
Details: appguardrail-rule | misconfig | test
Message: Hardcoded AWS access key ID detected (AKIA/ASIA prefix). This grants
programmatic access to your AWS account. Remove it, rotate the key in IAM,
and load credentials from the environment or an instance role.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_secret_injection_rules.py:19
Rule: hardcoded-aws-access-key-id
Details: appguardrail-rule | misconfig | test
Message: Hardcoded AWS access key ID detected (AKIA/ASIA prefix). This grants
programmatic access to your AWS account. Remove it, rotate the key in IAM,
and load credentials from the environment or an instance role.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_secret_injection_rules.py:23
Rule: hardcoded-github-token
Details: appguardrail-rule | secrets | test
Message: Hardcoded GitHub token detected (personal access, OAuth, or fine-grained
token). This grants access to repositories and possibly your org. Revoke it
in GitHub settings and store it as an environment secret.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_secret_injection_rules.py:32
Rule: hardcoded-private-key-block
Details: appguardrail-rule | misconfig | test
Message: A private key PEM block appears to be committed to source. Private keys
must never live in the repository. Remove it, rotate the key pair, and load
the key from a secret store or mounted file.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_secret_injection_rules.py:32
Rule: hardcoded-private-key-block
Details: appguardrail-rule | misconfig | test
Message: A private key PEM block appears to be committed to source. Private keys
must never live in the repository. Remove it, rotate the key pair, and load
the key from a secret store or mounted file.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_audit_events.py:128
Rule: hardcoded-anthropic-api-key
Details: appguardrail-rule | secrets | test
Message: Possible hardcoded Anthropic API key detected. This key grants access to
your Claude API account and billing. Rotate it immediately in the Anthropic
console and store it as an environment variable (ANTHROPIC_API_KEY).
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_audit_events.py:148
Rule: hardcoded-anthropic-api-key
Details: appguardrail-rule | secrets | test
Message: Possible hardcoded Anthropic API key detected. This key grants access to
your Claude API account and billing. Rotate it immediately in the Anthropic
console and store it as an environment variable (ANTHROPIC_API_KEY).
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_injection_rules.py:34
Rule: hardcoded-anthropic-api-key
Details: appguardrail-rule | secrets | test
Message: Possible hardcoded Anthropic API key detected. This key grants access to
your Claude API account and billing. Rotate it immediately in the Anthropic
console and store it as an environment variable (ANTHROPIC_API_KEY).
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:1742
Rule: python-insecure-deserialization
Details: appguardrail-rule | misconfig | test
Message: Insecure deserialization detected. Loading untrusted data with pickle, marshal, yaml.load, or yaml.unsafe_load can lead to arbitrary code execution. [OWASP A08:2021 - Software and Data Integrity Failures]
Code: "pickle.loads(data)\n"
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:1743
Rule: python-insecure-deserialization
Details: appguardrail-rule | misconfig | test
Message: Insecure deserialization detected. Loading untrusted data with pickle, marshal, yaml.load, or yaml.unsafe_load can lead to arbitrary code execution. [OWASP A08:2021 - Software and Data Integrity Failures]
Code: "yaml.load(raw_config)\n"
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:1744
Rule: python-insecure-deserialization
Details: appguardrail-rule | misconfig | test
Message: Insecure deserialization detected. Loading untrusted data with pickle, marshal, yaml.load, or yaml.unsafe_load can lead to arbitrary code execution. [OWASP A08:2021 - Software and Data Integrity Failures]
Code: "yaml.unsafe_load(raw_config)\n"
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:1746
Rule: python-insecure-deserialization
Details: appguardrail-rule | misconfig | test
Message: Insecure deserialization detected. Loading untrusted data with pickle, marshal, yaml.load, or yaml.unsafe_load can lead to arbitrary code execution. [OWASP A08:2021 - Software and Data Integrity Failures]
Code: "marshal.load(stream)\n"
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:478
Rule: next-public-secret
Details: appguardrail-rule | secrets | test
Message: Secret environment variable uses NEXT_PUBLIC_ prefix — this exposes it to the browser bundle. [OWASP A05:2021 - Security Misconfiguration]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:1303
Rule: dangerous-eval
Details: appguardrail-rule | injection | test
Message: Use of eval() detected. This is a critical risk for arbitrary code execution and injection attacks. [OWASP A03:2021 - Injection]
Code: (scanner_cli / "appguardrail.py").write_text('"message": "Use eval() detected"\n')
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:1329
Rule: dangerous-eval
Details: appguardrail-rule | injection | test
Message: Use of eval() detected. This is a critical risk for arbitrary code execution and injection attacks. [OWASP A03:2021 - Injection]
Code: scanner_file.write_text('"message": "Use eval() detected"\n')
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:201
Rule: python-dynamic-sql
Details: appguardrail-rule | injection | test
Message: Dynamic SQL query construction detected. Use parameterized queries or query-builder binding instead of string formatting or concatenation. [OWASP A03:2021 - Injection]
Code: "content": 'cursor.execute(f"SELECT * FROM users WHERE name = {name}")\n',
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:206
Rule: tool-execute-parameters-passthrough
Details: appguardrail-rule | misconfig | test
Message: Tool execution endpoint appears to pass request parameters directly into a registry or handler. Validate the tool code allowlist and parameter schema before dispatch. [OWASP A03:2021 - Injection]
Code: "@router.post('/tools/{code}/execute')\n"
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:197
Rule: python-jwt-decode-without-algorithms
Details: appguardrail-rule | authz | test
Message: JWT decode call does not appear to pin accepted algorithms. Explicitly require expected algorithms and validate issuer, audience, expiry, and key id. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:253
Rule: hardcoded-api-credential
Details: appguardrail-rule | secrets | test
Message: Hardcoded API credential detected. Move credentials to secret storage and rotate any committed value. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_appguardrail.py:478
Rule: nextjs-env-secret-client-prefix
Details: appguardrail-rule | secrets | test
Message: Secret environment variable uses NEXT_PUBLIC_ prefix, which exposes it
in the browser bundle. Remove the NEXT_PUBLIC_ prefix and ensure it is
only referenced in server-side code.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] tests/test_coverage_edge_cases.py:306
Rule: hardcoded-api-credential
Details: appguardrail-rule | secrets | test
Message: Hardcoded API credential detected. Move credentials to secret storage and rotate any committed value. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] examples/vulnerable-vibe-app/README.md:54
Rule: next-public-secret
Details: appguardrail-rule | secrets | example
Message: Secret environment variable uses NEXT_PUBLIC_ prefix — this exposes it to the browser bundle. [OWASP A05:2021 - Security Misconfiguration]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] examples/vulnerable-vibe-app/README.md:54
Rule: nextjs-env-secret-client-prefix
Details: appguardrail-rule | secrets | example
Message: Secret environment variable uses NEXT_PUBLIC_ prefix, which exposes it
in the browser bundle. Remove the NEXT_PUBLIC_ prefix and ensure it is
only referenced in server-side code.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/cli/appguardrail.py:429
Rule: dangerous-eval
Details: appguardrail-rule | injection | scanner-fixture
Message: Use of eval() detected. This is a critical risk for arbitrary code execution and injection attacks. [OWASP A03:2021 - Injection]
Code: "message": "Use of eval() detected. This is a critical risk for arbitrary code execution and injection attacks. [OWASP A
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/stripe.yml:62
Rule: next-public-secret
Details: appguardrail-rule | secrets | scanner-fixture
Message: Secret environment variable uses NEXT_PUBLIC_ prefix — this exposes it to the browser bundle. [OWASP A05:2021 - Security Misconfiguration]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/stripe.yml:62
Rule: nextjs-env-secret-client-prefix
Details: appguardrail-rule | secrets | scanner-fixture
Message: Secret environment variable uses NEXT_PUBLIC_ prefix, which exposes it
in the browser bundle. Remove the NEXT_PUBLIC_ prefix and ensure it is
only referenced in server-side code.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/stripe.yml:62
Rule: stripe-secret-key-client-exposure
Details: appguardrail-rule | secrets | scanner-fixture
Message: Stripe secret key appears to use NEXT_PUBLIC_ prefix, which exposes it
to the browser. Remove the NEXT_PUBLIC_ prefix immediately. The Stripe
secret key must only be used server-side.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/stripe.yml:63
Rule: stripe-secret-key-client-exposure
Details: appguardrail-rule | secrets | scanner-fixture
Message: Stripe secret key appears to use NEXT_PUBLIC_ prefix, which exposes it
to the browser. Remove the NEXT_PUBLIC_ prefix immediately. The Stripe
secret key must only be used server-side.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/supabase.yml:16
Rule: next-public-secret
Details: appguardrail-rule | secrets | scanner-fixture
Message: Secret environment variable uses NEXT_PUBLIC_ prefix — this exposes it to the browser bundle. [OWASP A05:2021 - Security Misconfiguration]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/supabase.yml:16
Rule: nextjs-env-secret-client-prefix
Details: appguardrail-rule | secrets | scanner-fixture
Message: Secret environment variable uses NEXT_PUBLIC_ prefix, which exposes it
in the browser bundle. Remove the NEXT_PUBLIC_ prefix and ensure it is
only referenced in server-side code.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🔴 CRITICAL] scanner/rules/nextjs.yml:63
Rule: stripe-secret-key-client-exposure
Details: appguardrail-rule | secrets | scanner-fixture
Message: Stripe secret key appears to use NEXT_PUBLIC_ prefix, which exposes it
to the browser. Remove the NEXT_PUBLIC_ prefix immediately. The Stripe
secret key must only be used server-side.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🟠 HIGH] tests/test_auth_deferral_comment_rule.py:63
Rule: todo-skip-auth
Details: appguardrail-rule | authz | test
Message: Comment suggests authentication or security check was intentionally skipped
or deferred. This is a common pattern in AI-generated code. Review and ensure
proper authentication and authorization are in place before deploying.
Code: "/*\n * TODO: restore authentication before deployment\n */\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_auth_deferral_comment_rule.py:67
Rule: todo-skip-auth
Details: appguardrail-rule | authz | test
Message: Comment suggests authentication or security check was intentionally skipped
or deferred. This is a common pattern in AI-generated code. Review and ensure
proper authentication and authorization are in place before deploying.
Code: "/* temporary disable security checks for the prototype */\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_auth_deferral_comment_rule.py:71
Rule: todo-skip-auth
Details: appguardrail-rule | authz | test
Message: Comment suggests authentication or security check was intentionally skipped
or deferred. This is a common pattern in AI-generated code. Review and ensure
proper authentication and authorization are in place before deploying.
Code: "/*\n * release notes\n // TODO: restore authentication before deployment\n */\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_more_secret_rules.py:29
Rule: hardcoded-slack-webhook-url
Details: appguardrail-rule | payment | test
Message: Hardcoded Slack incoming webhook URL detected. Anyone with this URL can
post messages into your Slack workspace. Delete the webhook in Slack,
recreate it, and load the URL from an environment variable.
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:189
Rule: upload-filename-path-traversal-risk
Details: appguardrail-rule | injection | test
Message: Uploaded filename is used in a filesystem path. Sanitize with a strict allowlist and verify the resolved path stays inside the intended directory. [OWASP A01:2021 - Broken Access Control]
Code: "content": "target = os.path.join(tmpdir, upload.filename)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:231
Rule: python-subprocess-string-command
Details: appguardrail-rule | injection | test
Message: Subprocess command is built as a formatted or concatenated string. Pass an argument list and validate attacker-controlled command arguments. [OWASP A03:2021 - Injection]
Code: "content": 'subprocess.run(f"ffmpeg -i {source_path}")\n',
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:193
Rule: python-permissive-cors
Details: appguardrail-rule | misconfig | test
Message: CORS allows every origin. Restrict authenticated APIs to known origins. [OWASP A05:2021 - Security Misconfiguration]
Code: "content": "app.add_middleware(CORSMiddleware, allow_origins=['*'])\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:240
Rule: python-subprocess-user-controlled-args
Details: appguardrail-rule | injection | test
Message: Subprocess argument list includes high-risk user-controlled media or filename parameters. Validate each argument with strict allowlists and bounds before invoking external tools. [OWASP A03:2021 - Injection]
Code: "subprocess.run(['ffmpeg', '-i', source_path, '-fs', str(target_bytes)])\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:296
Rule: python-subprocess-user-controlled-args
Details: appguardrail-rule | injection | test
Message: Subprocess argument list includes high-risk user-controlled media or filename parameters. Validate each argument with strict allowlists and bounds before invoking external tools. [OWASP A03:2021 - Injection]
Code: "content": "subprocess.run(['ffmpeg', '-i', source_path], check=True)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:240
Rule: python-target-bytes-missing-upper-bound
Details: appguardrail-rule | misconfig | test
Message: target_bytes is checked only for a lower bound. Add a server-side upper bound to prevent resource exhaustion in media processing. [OWASP A04:2021 - Insecure Design]
Code: "subprocess.run(['ffmpeg', '-i', source_path, '-fs', str(target_bytes)])\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:266
Rule: pydantic-bounding-box-unconstrained
Details: appguardrail-rule | misconfig | test
Message: Bounding box schema fields are unconstrained numeric values. Add min/max bounds to reject invalid coordinates before document processing. [OWASP A04:2021 - Insecure Design]
Code: "class BoundingBox(BaseModel):\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:266
Rule: pydantic-unbounded-nested-list
Details: appguardrail-rule | misconfig | test
Message: Pydantic model accepts nested lists without an obvious size or depth bound. Add max_length/depth validation for untrusted recursive structures. [OWASP A04:2021 - Insecure Design]
Code: "class BoundingBox(BaseModel):\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:281
Rule: python-absolute-path-traversal-check-missing
Details: appguardrail-rule | injection | test
Message: Path validation checks '..' parts but does not reject absolute paths nearby. Reject absolute paths and verify resolved paths stay under the allowed root. [OWASP A01:2021 - Broken Access Control]
Code: "candidate = Path(input_path)\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:289
Rule: python-okta-host-endswith-ssrf
Details: appguardrail-rule | misconfig | test
Message: Okta/Snowflake authenticator host validation uses a suffix check. Parse the URL hostname and allow only exact Okta domains or verified subdomains to prevent SSRF bypasses. [OWASP A10:2021 - Server-Side Request Forgery]
Code: "parsed = urlparse(authenticator)\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:231
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "content": 'subprocess.run(f"ffmpeg -i {source_path}")\n',
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:296
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "content": "subprocess.run(['ffmpeg', '-i', source_path], check=True)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:1848
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "subprocess.call(command, shell=True)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:1895
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "subprocess.call(command)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:312
Rule: python-expanduser-user-path-traversal
Details: appguardrail-rule | injection | test
Message: User-controlled path is expanded before containment validation. Reject traversal and verify resolved paths stay under the allowed root. [OWASP A01:2021 - Broken Access Control]
Code: "content": "audio_file = Path(input_path).expanduser()\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:346
Rule: python-requests-verify-false
Details: appguardrail-rule | misconfig | test
Message: HTTP client disables TLS certificate verification. Keep verification enabled or pin a trusted CA bundle. [CWE-295 - Improper Certificate Validation]
Code: "content": "requests.get('https://api.example.test', verify=False)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:878
Rule: python-requests-verify-false
Details: appguardrail-rule | misconfig | test
Message: HTTP client disables TLS certificate verification. Keep verification enabled or pin a trusted CA bundle. [CWE-295 - Improper Certificate Validation]
Code: "requests.get(url, verify=False)",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:937
Rule: python-requests-verify-false
Details: appguardrail-rule | misconfig | test
Message: HTTP client disables TLS certificate verification. Keep verification enabled or pin a trusted CA bundle. [CWE-295 - Improper Certificate Validation]
Code: "code": "requests.get(url, verify=False)",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:1581
Rule: python-requests-verify-false
Details: appguardrail-rule | misconfig | test
Message: HTTP client disables TLS certificate verification. Keep verification enabled or pin a trusted CA bundle. [CWE-295 - Improper Certificate Validation]
Code: "snippet": "requests.get(url, verify=False)",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:1611
Rule: python-requests-verify-false
Details: appguardrail-rule | misconfig | test
Message: HTTP client disables TLS certificate verification. Keep verification enabled or pin a trusted CA bundle. [CWE-295 - Improper Certificate Validation]
Code: "snippet": "requests.get(url, verify=False)",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:350
Rule: python-tempfile-mktemp
Details: appguardrail-rule | misconfig | test
Message: tempfile.mktemp creates predictable names without opening the file atomically. Use NamedTemporaryFile or mkstemp. [CWE-377 - Insecure Temporary File]
Code: "content": "name = tempfile.mktemp()\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:354
Rule: python-flask-debug-true
Details: appguardrail-rule | misconfig | test
Message: Debug mode is enabled in application code. Disable active debug code before deployment. [CWE-489 - Active Debug Code]
Code: "content": "app.run(host='0.0.0.0', debug=True)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:958
Rule: python-flask-debug-true
Details: appguardrail-rule | misconfig | test
Message: Debug mode is enabled in application code. Disable active debug code before deployment. [CWE-489 - Active Debug Code]
Code: "issue_text": "Flask app run with debug=True",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:959
Rule: python-flask-debug-true
Details: appguardrail-rule | misconfig | test
Message: Debug mode is enabled in application code. Disable active debug code before deployment. [CWE-489 - Active Debug Code]
Code: "code": "app.run(debug=True)",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:1003
Rule: python-flask-debug-true
Details: appguardrail-rule | misconfig | test
Message: Debug mode is enabled in application code. Disable active debug code before deployment. [CWE-489 - Active Debug Code]
Code: "message": "flask app with debug=True",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:358
Rule: python-jinja-autoescape-disabled
Details: appguardrail-rule | misconfig | test
Message: Jinja2 autoescaping is disabled. Keep autoescape enabled for HTML templates to reduce XSS risk. [CWE-79 - Cross-site Scripting]
Code: "content": "env = jinja2.Environment(loader=loader, autoescape=False)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_appguardrail.py:362
Rule: python-django-csrf-exempt
Details: appguardrail-rule | misconfig | test
Message: Django CSRF protection is explicitly disabled on a view. Require CSRF protection or document a safe non-browser authentication boundary. [CWE-352 - Cross-Site Request Forgery]
Code: "content": "@csrf_exempt\ndef update_profile(request):\n return HttpResponse('ok')\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:42
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "subprocess.run(build(one(two(user_input))), shell=True)\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:94
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "import subprocess\nsubprocess.run(['id'])\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:127
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "subprocess.check_output(second, shell=True)\n"
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:137
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: assert calls[1].snippet == "subprocess.check_output(second, shell=True)"
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:163
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: "import subprocess\nsubprocess.run(command, shell=True\n",
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:292
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: assert find_python_shell_calls("import subprocess\nsubprocess.run(value, shell=True)\n")
Gate: non-blocking context

[🟠 HIGH] tests/test_python_command_injection_ast.py:335
Rule: hardcoded-password
Details: appguardrail-rule | secrets | test
Message: Possible hardcoded password detected. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🟠 HIGH] tests/test_org_security_failure_collector.py:154
Rule: python-subprocess-missing-timeout
Details: appguardrail-rule | injection | test
Message: External process call has no timeout. Add a bounded timeout and handle TimeoutExpired to prevent worker exhaustion. [OWASP A04:2021 - Insecure Design]
Code: result = subprocess.run(
Gate: non-blocking context

[🟠 HIGH] tests/test_reports_core.py:16
Rule: python-requests-verify-false
Details: appguardrail-rule | misconfig | test
Message: HTTP client disables TLS certificate verification. Keep verification enabled or pin a trusted CA bundle. [CWE-295 - Improper Certificate Validation]
Code: "snippet": "requests.get(url, verify=False)",
Gate: non-blocking context

[🟠 HIGH] tests/test_coverage_edge_cases.py:116
Rule: hardcoded-password
Details: appguardrail-rule | secrets | test
Message: Possible hardcoded password detected. [OWASP A07:2021 - Identification and Authentication Failures]
Code: [REDACTED: sensitive match suppressed]
Gate: non-blocking context

[🟠 HIGH] scanner/cli/appguardrail.py:799
Rule: python-django-csrf-exempt
Details: appguardrail-rule | misconfig | scanner-fixture
Message: Django CSRF protection is explicitly disabled on a view. Require CSRF protection or document a safe non-browser authentication boundary. [CWE-352 - Cross-Site Request Forgery]
Code: "pattern": re.compile(r"@csrf_exempt\b", re.MULTILINE),
Gate: non-blocking context

[🟡 WARNING] tests/test_appguardrail.py:235
Rule: http-exception-chains-internal-error
Details: appguardrail-rule | misconfig | test
Message: HTTPException is chained from an internal exception. Avoid leaking implementation details in API error responses. [OWASP A05:2021 - Security Misconfiguration]
Code: "content": "raise HTTPException(status_code=500) from exc\n",
Gate: non-blocking context

[🔵 INFO] .github/dependabot.yml:3
Rule: semgrep:package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown
Details: semgrep | misconfig | app-code
Message: This Dependabot configuration does not set a cooldown period. Newly published packages can be malicious or unstable. Add a cooldown block with default-days: 7 to each package-ecosystem entry under updates to wait 7 days before proposing updates to newly published package versions. Reference: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#cooldown
Code: requires login

[🔵 INFO] .github/dependabot.yml:10
Rule: semgrep:package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown
Details: semgrep | misconfig | app-code
Message: This Dependabot configuration does not set a cooldown period. Newly published packages can be malicious or unstable. Add a cooldown block with default-days: 7 to each package-ecosystem entry under updates to wait 7 days before proposing updates to newly published package versions. Reference: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#cooldown
Code: requires login

────────────────────────────────────────────────────────────
Scanned 278 files | Deploy blockers: 🔴 0 critical issues 🟠 0 high issues 🟡 0 warnings 🔵 2 info issues
Non-blocking findings in docs/tests/examples/fixtures: 83

✅ No deploy-blocking critical or high issues found.

💡 Hint: Run 'appguardrail review' to get an AI prompt for fixing these issues. reports 0 deploy blockers. Please validate this current head and report any actionable finding with exact file/line and reproducible evidence.

@coderabbitai

coderabbitai Bot commented Aug 21, 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

echo '== checked-out revision =='
git rev-parse HEAD
git status --short
echo '== PR diff summary =='
git diff --stat HEAD^
echo '== changed paths =='
git diff --name-status HEAD^
echo '== requirements inputs =='
fd -a '^requirements-release\.(in|txt)$' -x sh -c 'echo "--- $1"; grep -nE "^(cryptography|cffi|pycparser|setuptools|pip|uv)[<>=!~; ]" "$1" || true' sh {}
echo '== cryptography lock entry and adjacent resolution markers =='
if [ -f requirements-release.txt ]; then
  grep -n -A8 -B4 -E '^cryptography(==|[<>=!~; ])' requirements-release.txt || true
fi
echo '== diff for release requirement files =='
git diff --unified=80 HEAD^ -- requirements-release.in requirements-release.txt

Length of output: 75182


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== direct release requirements =='
nl -ba requirements-release.in

echo '== workflows that consume requirements-release.txt =='
rg -n -C 5 --glob '*.yml' --glob '*.yaml' --glob '*.yaml' \
  'requirements-release\.txt|pip-audit|uv pip (compile|install)' .github 2>/dev/null || true

echo '== workflow runner platforms =='
rg -n -C 3 --glob '*.yml' --glob '*.yaml' \
  'runs-on:|matrix:|os:' .github 2>/dev/null || true

echo '== normalized package changes from the parent revision =='
python3 - <<'PY'
import re
import subprocess

def parse(text):
    out = {}
    for line in text.splitlines():
        m = re.match(r'^([A-Za-z0-9][A-Za-z0-9_.-]*)==([^\s;\\]+)(.*)$', line)
        if m:
            out[m.group(1).lower().replace('_','-')] = (m.group(2), m.group(3).strip())
    return out

old = parse(subprocess.check_output(
    ['git','show','HEAD^:requirements-release.txt'], text=True))
new = parse(open('requirements-release.txt', encoding='utf-8').read())
for name in sorted(set(old) | set(new)):
    if old.get(name) != new.get(name):
        print(f'{name}: {old.get(name)} -> {new.get(name)}')
PY

echo '== references to cryptography or secretstorage outside the generated lock =='
rg -n -C 2 --glob '!requirements-release.txt' \
  '\b(cryptography|secretstorage|keyring)\b' . || true

Length of output: 1713


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== direct release requirements =='
awk '{ printf "%6d  %s\n", NR, $0 }' requirements-release.in

echo '== workflows that consume requirements-release.txt =='
if [ -d .github ]; then
  rg -n -C 5 --glob '*.yml' --glob '*.yaml' \
    'requirements-release\.txt|pip-audit|uv pip (compile|install)' .github || true
fi

echo '== workflow runner platforms =='
if [ -d .github ]; then
  rg -n -C 3 --glob '*.yml' --glob '*.yaml' \
    'runs-on:|matrix:|os:' .github || true
fi

echo '== normalized package changes from the parent revision =='
python3 - <<'PY'
import re
import subprocess

def parse(text):
    out = {}
    for line in text.splitlines():
        m = re.match(r'^([A-Za-z0-9][A-Za-z0-9_.-]*)==([^\s;\\]+)(.*)$', line)
        if m:
            out[m.group(1).lower().replace('_','-')] = (m.group(2), m.group(3).strip())
    return out

old = parse(subprocess.check_output(
    ['git', 'show', 'HEAD^:requirements-release.txt'], text=True))
with open('requirements-release.txt', encoding='utf-8') as file:
    new = parse(file.read())
for name in sorted(set(old) | set(new)):
    if old.get(name) != new.get(name):
        print(f'{name}: {old.get(name)} -> {new.get(name)}')
PY

echo '== references to cryptography or secretstorage outside the generated lock =='
rg -n -C 2 --glob '!requirements-release.txt' \
  '\b(cryptography|secretstorage|keyring)\b' . || true

Length of output: 15483


@seonghobae No actionable findings for commit ff95e695550ce8aec665b5d6468d7463abead3a8.

Validated items:

  • requirements-release.txt is the only changed file.
  • requirements-release.txt Line 254 replaces cryptography==49.0.0 with hash-pinned cryptography==50.0.0.
  • The release workflows install this file with --require-hashes.
  • All workflows that consume this lock run on ubuntu-latest.
  • The regenerated Linux platform markers for cryptography, cffi, pycparser, and secretstorage are compatible with those workflows.
  • requirements-release.in remains unchanged. The remediation does not broaden the direct release-tooling dependency boundary.

I performed static validation only. I did not execute dependency installation, audit, or build commands in the sandbox.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 21, 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

expected="ff95e695550ce8aec665b5d6468d7463abead3a8"
printf 'Checked-out HEAD: '
git rev-parse HEAD
printf '\nExpected commit object:\n'
git cat-file -t "$expected"
printf '\nHEAD matches expected: '
test "$(git rev-parse HEAD)" = "$expected" && echo yes || echo no

printf '\nPR merge-base and changed files:\n'
base="$(git merge-base "$expected" origin/main 2>/dev/null || true)"
if [ -n "$base" ]; then
  printf 'merge-base=%s\n' "$base"
  git diff --stat "$base" "$expected"
  git diff --name-status "$base" "$expected"
  printf '\nFull PR diff:\n'
  git diff --no-ext-diff --unified=80 "$base" "$expected"
else
  echo "Could not determine merge base against origin/main"
  git show --stat --oneline "$expected"
  git show --format=fuller --no-ext-diff --unified=80 "$expected"
fi

printf '\nCandidate requirement and workflow files:\n'
fd -HI -t f '^(requirements-release\.(in|txt)|.*\.(yml|yaml))$' . \
  -E .git -E node_modules -E dist -E build | sort

printf '\nrequirements-release.in contents:\n'
infile="$(fd -HI -t f '^requirements-release\.in$' . -E .git | head -n 1 || true)"
if [ -n "$infile" ]; then cat -n "$infile"; else echo 'not found'; fi

printf '\ncryptography entries and direct dependency context:\n'
lockfile="$(fd -HI -t f '^requirements-release\.txt$' . -E .git | head -n 1 || true)"
if [ -n "$lockfile" ]; then
  rg -n -i -C 5 '^(cryptography|pyopenssl|authlib|.*cryptography.*)\b|cryptography==' "$lockfile"
else
  echo 'not found'
fi

printf '\nAll requirements-release references and install/compile commands:\n'
rg -n -i -C 3 \
  '(requirements-release\.txt|requirements-release\.in|uv\s+pip\s+(compile|install)|pip\s+install.*require-hashes)' \
  -g '*.yml' -g '*.yaml' -g '*.md' -g '*.sh' -g '*.txt' -g '*.in' .

Length of output: 82798


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/appguardrail"
head="ff95e695550ce8aec665b5d6468d7463abead3a8"

printf '%s\n' 'GitHub PR metadata:'
gh pr view 1004 --repo "$repo" --json number,state,baseRefName,baseRefOid,headRefName,headRefOid,commits,files \
  --jq '{number,state,baseRefName,baseRefOid,headRefName,headRefOid,commits:[.commits[].oid],files:[.files[].path]}'

printf '\n%s\n' 'Exact parent diff summary and selected dependency changes:'
git diff --no-ext-diff --unified=4 "${head}^" "$head" -- requirements-release.txt |
  rg -n -C 4 '^[+-](cryptography|cffi|pycparser|secretstorage|keyring|cachecontrol|cyclonedx-python-lib|jsonschema|pip)==|^\+.*platform|^\-.*platform|^@@'

printf '\n%s\n' 'Release workflow structure and requirements installation commands:'
for f in \
  .github/workflows/prepare-pypi-release.yml \
  .github/workflows/publish-pypi.yml \
  docs/release-automation.md
do
  if [ -f "$f" ]; then
    printf '\n--- %s ---\n' "$f"
    rg -n -C 4 '(runs-on|requirements-release\.txt|require-hashes|pip-audit|python-version)' "$f" || true
  fi
done

printf '\n%s\n' 'All cryptography entries and their immediate dependency provenance:'
awk '
  /^cryptography==/ {show=1}
  show {printf "%d:%s\n", NR, $0}
  show && /^    # via/ {show=0}
' requirements-release.txt

printf '\n%s\n' 'Static checks for lockfile integrity and marker applicability:'
python3 - <<'PY'
from pathlib import Path
import re

text = Path("requirements-release.txt").read_text()
packages = re.findall(r"(?m)^([A-Za-z0-9_.-]+(?:\[[^]]+\])?)==([^\s\\]+)(?:\s*;\s*(.*?))?\s*\\$", text)
print(f"package entries: {len(packages)}")
for name, version, marker in packages:
    if name.lower().split("[")[0] == "cryptography":
        print(f"cryptography: version={version}; marker={marker or '<none>'}")
print(f"cryptography==49.0.0 occurrences: {text.count('cryptography==49.0.0')}")
print(f"cryptography==50.0.0 occurrences: {text.count('cryptography==50.0.0')}")
for target in ("linux/x86_64", "linux/ppc64le", "linux/s390x", "darwin/arm64", "win32/AMD64"):
    print(f"target considered: {target}")
PY

printf '\n%s\n' 'Public PyPI release-file validation for cryptography 50.0.0:'
curl --fail --silent --show-error --location \
  'https://pypi.org/pypi/cryptography/50.0.0/json' |
  python3 -c '
import json, sys
data = json.load(sys.stdin)
files = data.get("urls", [])
print("version:", data["info"]["version"])
print("release files:", len(files))
print("sha256 values:", len({x["digests"]["sha256"] for x in files}))
for item in files:
    print(item["filename"], item["digests"]["sha256"])
'

Length of output: 28472


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="ff95e695550ce8aec665b5d6468d7463abead3a8"
expected_base="a68b57d4ccad4f895d7a3d9f909fffbc4653b17e"

printf 'Commit parent: '
git rev-parse "${head}^"
printf 'PR base:      %s\n' "$expected_base"
printf 'Parent equals PR base: '
test "$(git rev-parse "${head}^")" = "$expected_base" && echo yes || echo no

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

awk '
  /^cryptography==50\.0\.0 / {in_pkg=1; next}
  in_pkg && /^    --hash=sha256:/ {
    sub(/^    --hash=sha256:/, "")
    sub(/ \\/, "")
    print
    next
  }
  in_pkg && /^    # via/ {exit}
' requirements-release.txt | sort -u > "$tmpdir/committed-hashes"

curl --fail --silent --show-error --location \
  'https://pypi.org/pypi/cryptography/50.0.0/json' |
  python3 -c '
import json, sys
for item in json.load(sys.stdin)["urls"]:
    print(item["digests"]["sha256"])
' | sort -u > "$tmpdir/pypi-hashes"

printf '\nCommitted cryptography hashes: '; wc -l < "$tmpdir/committed-hashes"
printf 'PyPI cryptography hashes:      '; wc -l < "$tmpdir/pypi-hashes"
printf '\nCommitted hashes absent from PyPI:\n'
comm -23 "$tmpdir/committed-hashes" "$tmpdir/pypi-hashes" || true
printf 'PyPI hashes absent from lockfile:\n'
comm -13 "$tmpdir/committed-hashes" "$tmpdir/pypi-hashes" || true
printf 'Hash sets match: '
cmp -s "$tmpdir/committed-hashes" "$tmpdir/pypi-hashes" && echo yes || echo no

printf '\nGitHub advisory record:\n'
gh api \
  -H 'Accept: application/vnd.github+json' \
  '/advisories/GHSA-g6cj-pr64-35w5' \
  --jq '{ghsa_id,cve_id,severity,withdrawn_at,vulnerabilities:[.vulnerabilities[] | {package:.package.name,vulnerable_version_range,first_patched_version:(.first_patched_version.identifier // null)}]}'

Length of output: 2434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

awk '
  /^cryptography==50\.0\.0 / {in_pkg=1; next}
  in_pkg && /^    --hash=sha256:/ {
    sub(/^    --hash=sha256:/, "")
    sub(/ \\/, "")
    print
    next
  }
  in_pkg && /^    # via/ {exit}
' requirements-release.txt | sort -u > "$tmpdir/committed-hashes"

curl --fail --silent --show-error --location \
  'https://pypi.org/pypi/cryptography/50.0.0/json' |
  python3 -c 'import json,sys; print("\n".join(sorted({x["digests"]["sha256"] for x in json.load(sys.stdin)["urls"]})))' \
  > "$tmpdir/pypi-hashes"

python3 - "$tmpdir/committed-hashes" "$tmpdir/pypi-hashes" <<'PY'
from pathlib import Path
import sys
committed = set(Path(sys.argv[1]).read_text().splitlines())
pypi = set(Path(sys.argv[2]).read_text().splitlines())
print("hash sets equal:", committed == pypi)
print("committed-only hashes:", len(committed - pypi))
print("PyPI-only hashes:", len(pypi - committed))
PY

printf '\nGitHub advisory record:\n'
gh api \
  -H 'Accept: application/vnd.github+json' \
  '/advisories/GHSA-g6cj-pr64-35w5' |
  jq '{
    ghsa_id,
    cve_id,
    severity,
    withdrawn_at,
    vulnerabilities: [
      .vulnerabilities[] |
      {
        package: .package.name,
        vulnerable_version_range,
        first_patched_version
      }
    ]
  }'

Length of output: 1850


@seonghobae No actionable findings.

I validated commit ff95e695550ce8aec665b5d6468d7463abead3a8. Its parent matches the PR base commit.

requirements-release.txt updates cryptography to 50.0.0 at Line 254. GitHub advisory GHSA-g6cj-pr64-35w5 defines the affected range as >= 44.0.0, < 50.0.0 and identifies 50.0.0 as the first patched version.

The 46 committed hashes for cryptography==50.0.0 exactly match the 46 hashes published by PyPI.

The prepare and publish workflows run on ubuntu-latest with Python 3.13. They install this lockfile with --require-hashes. The Linux marker on the cryptography entry therefore covers the active release workflow path.

You are interacting with an AI system.

@opencode-agent opencode-agent Bot added area: security Security boundary, hardening, or vulnerability prevention priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: bug Defect or incorrect behavior labels Aug 22, 2026
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: b7b60fd4-4028-4867-b576-b9827713e12a

📥 Commits

Reviewing files that changed from the base of the PR and between c94b2c8 and 9844cd4.

📒 Files selected for processing (1)
  • CHANGELOG.d/1004-cryptography-cve-2026-69247.md
🚧 Files skipped from review as they are similar to previous changes (1)

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

릴리스 의존성 잠금 파일이 재생성되었습니다. cryptography50.0.0으로 갱신되었습니다. 플랫폼·아키텍처 조건과 패키지 주석이 조정되었습니다. 관련 CVE 변경 로그가 갱신되었습니다.

Changes

릴리스 의존성

Layer / File(s) Summary
의존성 선언 및 보안 변경 기록
requirements-release.txt, CHANGELOG.d/1004-cryptography-cve-2026-69247.md
패키지 버전, extras, 해시, 플랫폼 조건, CPU 아키텍처 조건 및 의존성 주석이 갱신되었습니다. cryptography49.0.0에서 50.0.0으로 변경되었습니다. CVE-2026-69247 관련 변경 로그가 갱신되었습니다.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 9844c

This PR updates the release-tooling cryptography dependency to a patched version and regenerates the hash-pinned requirements file; no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 cryptography를 50.0.0으로 업데이트하여 PKCS#7 oracle 취약점을 해결하는 주요 변경 사항을 정확하게 설명합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/cryptography-cve-2026-69247

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.

devin-ai-integration[bot]

This comment was marked as resolved.

seonghobae added a commit that referenced this pull request Aug 25, 2026
…tch, central callers) and record hourly-loop wiring
@seonghobae
seonghobae enabled auto-merge (squash) September 1, 2026 10:01
@seonghobae
seonghobae merged commit e71d37e into develop Sep 1, 2026
37 of 39 checks passed
@seonghobae
seonghobae deleted the security/cryptography-cve-2026-69247 branch September 1, 2026 12:08
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Security Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: security Security boundary, hardening, or vulnerability prevention priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: bug Defect or incorrect behavior

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant