fix(security): patch cryptography PKCS#7 oracle - #1004
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthrough
Changes릴리스 의존성
Estimated code review effort: 1 (Trivial) | ~5 minutes Merge Risk: ⚪ Minimal · up to 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)
✨ Finishing Touches🧪 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 |
|
@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. |
|
@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; 🧭 CodeGraph enabled: initializing or syncing structural index CodeGraph Status Project: /Users/seonghobae/Documents/ChatGPT/appguardrail Index Statistics: Nodes by Kind: Files by Language: ✓ Index is up to date 🧩 Detected language axes: python, web ⚙️ External auto mode: 🔎 Semgrep enabled: config auto [🔴 CRITICAL] checklists/secrets.md:65 [🔴 CRITICAL] checklists/secrets.md:65 [🔴 CRITICAL] checklists/secrets.md:65 [🔴 CRITICAL] checklists/secrets.md:65 [🔴 CRITICAL] checklists/stripe.md:62 [🔴 CRITICAL] tests/test_issueops_core.py:158 [🔴 CRITICAL] tests/test_issueops_core.py:159 [🔴 CRITICAL] tests/test_more_secret_rules.py:20 [🔴 CRITICAL] tests/test_more_secret_rules.py:21 [🔴 CRITICAL] tests/test_secret_injection_rules.py:19 [🔴 CRITICAL] tests/test_secret_injection_rules.py:19 [🔴 CRITICAL] tests/test_secret_injection_rules.py:23 [🔴 CRITICAL] tests/test_secret_injection_rules.py:32 [🔴 CRITICAL] tests/test_secret_injection_rules.py:32 [🔴 CRITICAL] tests/test_audit_events.py:128 [🔴 CRITICAL] tests/test_audit_events.py:148 [🔴 CRITICAL] tests/test_injection_rules.py:34 [🔴 CRITICAL] tests/test_appguardrail.py:1742 [🔴 CRITICAL] tests/test_appguardrail.py:1743 [🔴 CRITICAL] tests/test_appguardrail.py:1744 [🔴 CRITICAL] tests/test_appguardrail.py:1746 [🔴 CRITICAL] tests/test_appguardrail.py:478 [🔴 CRITICAL] tests/test_appguardrail.py:1303 [🔴 CRITICAL] tests/test_appguardrail.py:1329 [🔴 CRITICAL] tests/test_appguardrail.py:201 [🔴 CRITICAL] tests/test_appguardrail.py:206 [🔴 CRITICAL] tests/test_appguardrail.py:197 [🔴 CRITICAL] tests/test_appguardrail.py:253 [🔴 CRITICAL] tests/test_appguardrail.py:478 [🔴 CRITICAL] tests/test_coverage_edge_cases.py:306 [🔴 CRITICAL] examples/vulnerable-vibe-app/README.md:54 [🔴 CRITICAL] examples/vulnerable-vibe-app/README.md:54 [🔴 CRITICAL] scanner/cli/appguardrail.py:429 [🔴 CRITICAL] scanner/rules/stripe.yml:62 [🔴 CRITICAL] scanner/rules/stripe.yml:62 [🔴 CRITICAL] scanner/rules/stripe.yml:62 [🔴 CRITICAL] scanner/rules/stripe.yml:63 [🔴 CRITICAL] scanner/rules/supabase.yml:16 [🔴 CRITICAL] scanner/rules/supabase.yml:16 [🔴 CRITICAL] scanner/rules/nextjs.yml:63 [🟠 HIGH] tests/test_auth_deferral_comment_rule.py:63 [🟠 HIGH] tests/test_auth_deferral_comment_rule.py:67 [🟠 HIGH] tests/test_auth_deferral_comment_rule.py:71 [🟠 HIGH] tests/test_more_secret_rules.py:29 [🟠 HIGH] tests/test_appguardrail.py:189 [🟠 HIGH] tests/test_appguardrail.py:231 [🟠 HIGH] tests/test_appguardrail.py:193 [🟠 HIGH] tests/test_appguardrail.py:240 [🟠 HIGH] tests/test_appguardrail.py:296 [🟠 HIGH] tests/test_appguardrail.py:240 [🟠 HIGH] tests/test_appguardrail.py:266 [🟠 HIGH] tests/test_appguardrail.py:266 [🟠 HIGH] tests/test_appguardrail.py:281 [🟠 HIGH] tests/test_appguardrail.py:289 [🟠 HIGH] tests/test_appguardrail.py:231 [🟠 HIGH] tests/test_appguardrail.py:296 [🟠 HIGH] tests/test_appguardrail.py:1848 [🟠 HIGH] tests/test_appguardrail.py:1895 [🟠 HIGH] tests/test_appguardrail.py:312 [🟠 HIGH] tests/test_appguardrail.py:346 [🟠 HIGH] tests/test_appguardrail.py:878 [🟠 HIGH] tests/test_appguardrail.py:937 [🟠 HIGH] tests/test_appguardrail.py:1581 [🟠 HIGH] tests/test_appguardrail.py:1611 [🟠 HIGH] tests/test_appguardrail.py:350 [🟠 HIGH] tests/test_appguardrail.py:354 [🟠 HIGH] tests/test_appguardrail.py:958 [🟠 HIGH] tests/test_appguardrail.py:959 [🟠 HIGH] tests/test_appguardrail.py:1003 [🟠 HIGH] tests/test_appguardrail.py:358 [🟠 HIGH] tests/test_appguardrail.py:362 [🟠 HIGH] tests/test_python_command_injection_ast.py:42 [🟠 HIGH] tests/test_python_command_injection_ast.py:94 [🟠 HIGH] tests/test_python_command_injection_ast.py:127 [🟠 HIGH] tests/test_python_command_injection_ast.py:137 [🟠 HIGH] tests/test_python_command_injection_ast.py:163 [🟠 HIGH] tests/test_python_command_injection_ast.py:292 [🟠 HIGH] tests/test_python_command_injection_ast.py:335 [🟠 HIGH] tests/test_org_security_failure_collector.py:154 [🟠 HIGH] tests/test_reports_core.py:16 [🟠 HIGH] tests/test_coverage_edge_cases.py:116 [🟠 HIGH] scanner/cli/appguardrail.py:799 [🟡 WARNING] tests/test_appguardrail.py:235 [🔵 INFO] .github/dependabot.yml:3 [🔵 INFO] .github/dependabot.yml:10 ──────────────────────────────────────────────────────────── ✅ 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. |
|
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.txtLength 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' . || trueLength 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' . || trueLength of output: 15483
Validated items:
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. |
|
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
I validated commit
The 46 committed hashes for The prepare and publish workflows run on You are interacting with an AI system. |
|
Caution Review failedAn 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. Comment |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
🚧 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. 📝 WalkthroughWalkthrough릴리스 의존성 잠금 파일이 재생성되었습니다. Changes릴리스 의존성
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to 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)
Full details: Docstring CoverageExplanation 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)
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 |
…tch, central callers) and record hourly-loop wiring
Summary
cryptographyfrom49.0.0to the first patched50.0.0release.requirements-release.txtwith hashes using the documenteduv pip compilecommand.Verification
uv pip compile --generate-hashes --python-version 3.13 --universal --upgrade-package cryptography requirements-release.in -o requirements-release.txtuv pip install --python .venv/bin/python --require-hashes -r requirements-release.txtcryptography==50.0.0with--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.Summary by CodeRabbit
보안 업데이트
의존성 업데이트