Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ dependencies = [
"awscli>=1.44.2",
"bashlex>=0.18",
"click>=8.1.8",
"cryptography>=46.0.3",
"cryptography>=50.0.0",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n --hidden -S 'requires-python|python_requires|3\.9\.0|3\.9\.1' .
rg -n --hidden -S 'cryptography|DH|Diffie|x509|ocsp|sct|pkcs7|serialization' .

Repository: openshift-eng/art-tools

Length of output: 38584


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- pyproject.toml ---'
cat -n pyproject.toml | sed -n '1,60p'

printf '%s\n' '--- cryptography lock entry ---'
cat -n uv.lock | sed -n '810,875p'

printf '%s\n' '--- Python/tooling and test configuration ---'
rg -n --hidden -S 'python-version|python3|pytest|testpaths|requires-python|python_requires|cryptography' \
  .github pyproject.toml uv.lock 2>/dev/null || true

printf '%s\n' '--- Relevant cryptography API references ---'
rg -n --hidden -S \
  'DHParameterNumbers|DHPrivateKey|DHPublicKey|dh_parameters|generate_parameters|x509\.|Certificate|verify_directly_issued_by|ocsp|SignedCertificateTimestamp|sct|pkcs7|serialization\.' \
  --glob '*.py' --glob '*.toml' --glob '*.yaml' --glob '*.yml' --glob '*.json' . || true

Repository: openshift-eng/art-tools

Length of output: 39843


🌐 Web query:

cryptography 50.0.0 release notes Python 3.9.0 3.9.1 deprecations finite-field DH X.509 OCSP SCT PKCS7 serialization

💡 Result:

The cryptography library version 50.0.0, released on July 31, 2026, introduces several significant changes, deprecations, and security updates [1][2]. Deprecations and Security Updates - Diffie-Hellman Key Exchange (FFDH): Finite-field Diffie-Hellman (FFDH) is now deprecated [1][2]. This deprecation encompasses all associated types in cryptography.hazmat.primitives.asymmetric.dh and includes loading FFDH keys or parameters via the key loading APIs [1][2]. Users are advised to migrate to more modern key exchange algorithms [1][2]. - PKCS7 Security Fix: A security issue involving pkcs7_decrypt_der and its PEM/S/MIME variants was addressed [1][2]. These functions no longer expose distinguishable errors or timing when unwrapping a RecipientInfo encryptedKey to prevent potential Bleichenbacher oracle attacks [1][2]. A random key is substituted upon failure, following RFC 3218 [1][2]. X.509, OCSP, and SCT Updates - Stability: X.509 verification APIs are now considered stable and subject to the project's API stability policy [1][2]. - SCT Parsing: Parsing a Signed Certificate Timestamp (SCT) list now rejects encodings that contain trailing bytes after the list or after an individual SCT, rather than silently ignoring them [2][3]. - X.509/ASN.1: Support was added for using x509.Name as a field type in the cryptography.hazmat.asn1 module [2][4]. Additionally, parsing a CRL entry's InvalidityDate extension now strictly rejects GeneralizedTime values that contain fractional seconds or other non-DER forms [2]. Python Support - The cryptography library currently supports Python 3.9+ [2]. Support for older versions, such as Python 3.8, was removed in earlier releases (e.g., v48.0.0) [5]. Other Notable Changes - New features include the addition of xof class methods to SHAKE128 and SHAKE256 for XOFHash usage and the introduction of the Cobblestone recipe for streaming authenticated encryption [1][2]. Additionally, public key and EC private key loading now reject DER encodings where the BIT STRING declares a non-zero number of unused bits [2][4].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- project metadata ---'
sed -n '1,55p' pyproject.toml

printf '%s\n' '--- lock package metadata ---'
sed -n '818,830p' uv.lock

printf '%s\n' '--- test and CI Python versions ---'
rg -n --hidden -S 'python-version|python:|Python|pytest|testpaths' \
  .github pyproject.toml 2>/dev/null || true

printf '%s\n' '--- cryptography API usage in Python source ---'
rg -n --hidden -S \
  'Diffie|DHParameter|DHPrivate|DHPublic|generate_parameters|x509|ocsp|SignedCertificateTimestamp|pkcs7|serialization' \
  --glob '*.py' . || true

Repository: openshift-eng/art-tools

Length of output: 6550


🌐 Web query:

cryptography 50.0.0 changelog release notes supported Python versions deprecations

💡 Result:

The cryptography library version 50.0.0 was released on July 31, 2026 [1]. Supported Python Versions Cryptography 50.0.0 supports Python 3.9+ and PyPy3 3.11+ [2]. Key Changes and Deprecations in 50.0.0 - Security Issue: pkcs7_decrypt_der (including PEM and S/MIME variants) was updated to prevent a Bleichenbacher oracle vulnerability. It no longer exposes distinguishable errors or timing when unwrapping an encryptedKey; instead, a random key is substituted on failure [1][2]. - Deprecation: Diffie-Hellman key exchange over finite fields (FFDH) is now deprecated [1][2]. This includes the types in cryptography.hazmat.primitives.asymmetric.dh and loading FFDH keys or parameters via key loading APIs. Users are advised to migrate to modern key exchange algorithms [1][2]. - API Updates: - Added xof class methods to SHAKE128 and SHAKE256 for use with XOFHash [1][2]. - X.509 verification APIs are now considered stable and subject to the project's API stability policy [1][2]. - Introduced the Cobblestone recipe (implementing Cobblestone-128 and Cobblestone-256 for chunked-encryption) [2]. - Behavioral Changes: - Parsing a Signed Certificate Timestamp (SCT) list now strictly rejects encodings containing trailing bytes [2]. - Loading a public or EC private key now rejects DER where the subjectPublicKey/publicKey BIT STRING declares a non-zero number of unused bits [2]. - Parsing an InvalidityDate extension now rejects non-DER forms (such as those with fractional seconds) [2]. - Added support for using x509.Name as a field type in the cryptography.hazmat.asn1 module [2].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- pyproject dependency context ---'
cat -n pyproject.toml | sed -n '1,50p'

printf '%s\n' '--- direct cryptography call sites ---'
python3 - <<'PY'
from pathlib import Path
import re

terms = re.compile(
    r'(?:from\s+cryptography|import\s+cryptography|'
    r'\b(?:DHParameterNumbers|DHPrivateKey|DHPublicKey|'
    r'generate_parameters|x509|ocsp|SignedCertificateTimestamp|'
    r'pkcs7|serialization)\b)'
)
for path in Path('.').rglob('*.py'):
    text = path.read_text(errors='ignore')
    for number, line in enumerate(text.splitlines(), 1):
        if terms.search(line):
            print(f'{path}:{number}:{line}')
PY

printf '%s\n' '--- test matrix references ---'
find .github -type f -maxdepth 4 -print 2>/dev/null |
  xargs -r grep -nE 'python-version|3\.([0-9]+)' 2>/dev/null || true

Repository: openshift-eng/art-tools

Length of output: 3951


Pin and scope the cryptography compatibility check. Replace cryptography>=50.0.0 with cryptography==50.0.0 and update uv.lock. The project requires Python >=3.11, so Python 3.9.0 and 3.9.1 are outside its support range. Repository usage is limited to X.509 certificate loading and test certificate generation; no finite-field DH, X.509 verification, OCSP/SCT, PKCS#7, or key-serialization call sites require migration tests.

🤖 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 `@pyproject.toml` at line 40, Pin the cryptography dependency in the project
dependency list to exactly version 50.0.0 instead of using a lower-bound
constraint, then regenerate uv.lock so it reflects that exact requirement and
resolved version. No compatibility changes or migration tests are needed beyond
this dependency and lockfile update.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

curl -fsSL https://pypi.org/pypi/cryptography/50.0.0/json \
  | jq '[.releases["50.0.0"][] | {filename, yanked, digests}]'

curl -fsSL https://api.osv.dev/v1/query \
  -H 'Content-Type: application/json' \
  --data '{"package":{"ecosystem":"PyPI","name":"cryptography"},"version":"50.0.0"}' \
  | jq '{vulnerabilities: [.vulns[]? | {id, summary}]}'

rg -n --hidden -S 'cryptography|--hash=|pip-audit|osv|cyclonedx|syft|cosign|sigstore' .

Repository: openshift-eng/art-tools

Length of output: 219


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- pyproject.toml ---'
sed -n '1,100p' pyproject.toml

printf '%s\n' '--- dependency and supply-chain controls ---'
rg -n --hidden -S 'cryptography|--hash=|pip-audit|osv|cyclonedx|syft|cosign|sigstore|constraints|lock' \
  -g '!*.lock' -g '!node_modules' -g '!dist' -g '!build' . || true

printf '%s\n' '--- PyPI release metadata ---'
curl -fsSL https://pypi.org/pypi/cryptography/50.0.0/json \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); print(json.dumps({"info_version": d.get("info",{}).get("version"), "release_files": [{"filename": x.get("filename"), "yanked": x.get("yanked"), "digests": x.get("digests")} for x in d.get("releases",{}).get("50.0.0",[])]}, indent=2))'

printf '%s\n' '--- OSV result ---'
curl -fsSL https://api.osv.dev/v1/query \
  -H 'Content-Type: application/json' \
  --data '{"package":{"ecosystem":"PyPI","name":"cryptography"},"version":"50.0.0"}' \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); print(json.dumps({"vulnerabilities":[{"id":v.get("id"),"summary":v.get("summary")} for v in d.get("vulns",[])]}, indent=2))'

Repository: openshift-eng/art-tools

Length of output: 50380


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- dependency declaration ---'
nl -ba pyproject.toml | sed -n '30,50p'

printf '%s\n' '--- relevant tracked files only ---'
git ls-files | rg '(^|/)(pyproject\.toml|requirements[^/]*\.txt|Pipfile[^/]*|poetry\.lock|uv\.lock|.*constraints.*|.*requirements.*|.*lock.*|.*workflow.*\.ya?ml)$' | head -200

printf '%s\n' '--- exact control matches in tracked files ---'
git grep -n -E -- '--hash=|pip-audit|osv|cyclonedx|syft|cosign|sigstore|cryptography' -- \
  '*.toml' '*.txt' '*.lock' '*.yaml' '*.yml' '*.json' '*.ini' '*.cfg' '*.conf' 2>/dev/null | head -300

printf '%s\n' '--- PyPI metadata for the declared version ---'
curl -fsSL https://pypi.org/pypi/cryptography/50.0.0/json \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); r=d.get("releases",{}).get("50.0.0"); print(json.dumps({"info_version":d.get("info",{}).get("version"),"release_count":None if r is None else len(r),"release_files":r},indent=2))'

printf '%s\n' '--- OSV metadata for the declared version ---'
curl -fsSL https://api.osv.dev/v1/query \
  -H 'Content-Type: application/json' \
  --data '{"package":{"ecosystem":"PyPI","name":"cryptography"},"version":"50.0.0"}' \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); print(json.dumps({"vulnerability_ids":[v.get("id") for v in d.get("vulns",[])],"count":len(d.get("vulns",[]))},indent=2))'

Repository: openshift-eng/art-tools

Length of output: 18405


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- project metadata and dependency groups ---'
sed -n '1,90p' pyproject.toml

printf '%s\n' '--- uv lock metadata and cryptography entry ---'
sed -n '1,35p' uv.lock
sed -n '810,880p' uv.lock

printf '%s\n' '--- build and CI use of uv.lock ---'
git grep -n -E 'uv\.lock|uv (sync|pip|lock)|--(locked|frozen)|pip(3)? (install|sync)|requirements\.txt' -- \
  ':!uv.lock' ':!*.json' ':!*.md' ':!*.py' ':!*.go' ':!*.js' ':!*.ts' ':!*.tsx' ':!*.yaml' ':!*.yml' \
  2>/dev/null | head -300

Repository: openshift-eng/art-tools

Length of output: 24867


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- production container dependency installation ---'
sed -n '70,105p' art-cluster/pipelines/data/project/art-cd/image/Containerfile.base
sed -n '1,25p' art-cluster/pipelines/data/project/art-cd/image/Containerfile.latest

printf '%s\n' '--- audit target and callers ---'
sed -n '35,70p' Makefile
git grep -n -E 'make( [^[:space:]]*)*audit|uv audit|audit --locked' -- \
  '.github' 'Makefile' '*.yaml' '*.yml' 2>/dev/null | head -100

Repository: openshift-eng/art-tools

Length of output: 3752


🌐 Web query:

uv documentation whether uv pip installreads or enforcesuv.lock, and how to install from a uv lockfile in production

💡 Result:

The uv pip install command does not read or enforce uv.lock [1][2]. The uv pip interface is designed as an alternative to pip and pip-tools and interacts with packages similarly to traditional pip, without awareness of the project-specific uv.lock file [1][2][3]. To install from a lockfile in production, you should use uv sync [4][5]. ### Installing from a Lockfile in Production For reproducible production environments—such as in CI/CD pipelines or Docker builds—the uv sync command is the standard and recommended approach [4][6][5]. * Standard Usage: Running uv sync will automatically lock (if necessary) and sync the environment to match the dependencies specified in uv.lock [4]. * Production/Docker Usage: To ensure strict adherence to the lockfile during build processes, use: uv sync --frozen --no-install-project [7][5] * --frozen: This flag forces uv to use the existing uv.lock file as-is without attempting to update or re-resolve dependencies [7][6]. It will cause the operation to fail if the lockfile is missing or out of sync with pyproject.toml [6]. * --no-install-project: This is often used in Docker builds to install only the dependencies into the environment without installing the current project itself, which is useful for optimizing layer caching [4][7][5]. By using uv sync --frozen, you guarantee that the exact versions specified in your uv.lock are installed, providing the reproducibility required for production deployments [6][5].

Citations:


Security Misconfiguration (CWE-494): Download of Code Without Integrity Check

Reachability: External · Exploitability: Moderate

Install production dependencies from uv.lock.

uv.lock records hashes for cryptography==50.0.0, and CI runs uv audit --locked. The production container uses uv pip install -e ., which ignores uv.lock and resolves the open-ended requirements. Replace it with uv sync --frozen or an equivalent hashed installation.

🤖 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 `@pyproject.toml` at line 40, Update the production container dependency
installation to use the locked dependencies from uv.lock, replacing the uv pip
install -e . flow with uv sync --frozen or an equivalent hashed installation so
CI’s uv audit --locked requirements are preserved.

Source: Path instructions


🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- dependency and lock files ---'
git ls-files | grep -E '(^|/)(pyproject\.toml|poetry\.lock|uv\.lock|Pipfile(\.lock)?|requirements[^/]*\.txt|constraints[^/]*\.txt|pdm\.lock)$' || true

printf '%s\n' '--- pyproject context ---'
sed -n '1,100p' pyproject.toml

printf '%s\n' '--- dependency and install-control references ---'
rg -n -i 'cryptography|--require-hashes|hashes|poetry|uv sync|pip install|pip-compile|constraints|lock|sbom|cosign|sigstore|provenance' \
  -g '*.yml' -g '*.yaml' -g '*.toml' -g '*.txt' -g '*.md' -g 'Dockerfile*' -g '*.sh' . || true

printf '%s\n' '--- parsed project metadata ---'
python3 - <<'PY'
import tomllib
from pathlib import Path
p = Path("pyproject.toml")
data = tomllib.loads(p.read_text())
project = data.get("project", {})
print("project.dependencies =", project.get("dependencies"))
print("build-system =", data.get("build-system"))
for section in ("tool.poetry", "tool.uv", "tool.pdm"):
    cur = data
    for part in section.split("."):
        cur = cur.get(part, {}) if isinstance(cur, dict) else {}
    print(section, "=", cur)
PY

Repository: openshift-eng/art-tools

Length of output: 7524


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- dependency and lock files ---'
git ls-files | grep -E '(^|/)(pyproject\.toml|poetry\.lock|uv\.lock|Pipfile(\.lock)?|requirements[^/]*\.txt|constraints[^/]*\.txt|pdm\.lock)$' || true

printf '%s\n' '--- pyproject context ---'
sed -n '1,100p' pyproject.toml

printf '%s\n' '--- dependency and install-control references ---'
rg -n -i 'cryptography|--require-hashes|hashes|poetry|uv sync|pip install|pip-compile|constraints|lock|sbom|cosign|sigstore|provenance' \
  -g '*.yml' -g '*.yaml' -g '*.toml' -g '*.txt' -g '*.md' -g 'Dockerfile*' -g '*.sh' . || true

printf '%s\n' '--- parsed project metadata ---'
python3 - <<'PY'
import tomllib
from pathlib import Path
data = tomllib.loads(Path("pyproject.toml").read_text())
print("project.dependencies =", data.get("project", {}).get("dependencies"))
print("build-system =", data.get("build-system"))
PY

Repository: openshift-eng/art-tools

Length of output: 7524


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- cryptography entries in uv.lock ---'
rg -n -C 8 'name = "cryptography"|cryptography' uv.lock

printf '%s\n' '--- lock metadata and package source/hash fields ---'
sed -n '1,80p' uv.lock
python3 - <<'PY'
from pathlib import Path
text = Path("uv.lock").read_text().splitlines()
for i, line in enumerate(text):
    if line.strip() == 'name = "cryptography"':
        start = max(0, i - 3)
        end = min(len(text), i + 35)
        print("\n".join(f"{j+1}: {text[j]}" for j in range(start, end)))
PY

printf '%s\n' '--- tracked install entry points ---'
for f in install.sh doozer/Dockerfile doozer/container_install.sh ocp-build-data-validator/Dockerfile ocp-build-data-validator/deploy/Dockerfile.base; do
  if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
    echo "### $f"
    sed -n '1,180p' "$f"
  fi
done

printf '%s\n' '--- targeted diff summary ---'
git diff --stat -- pyproject.toml uv.lock
git diff --unified=3 -- pyproject.toml uv.lock || true

Repository: openshift-eng/art-tools

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- cryptography entries in uv.lock ---'
rg -n -C 8 'name = "cryptography"|cryptography' uv.lock

printf '%s\n' '--- lock metadata and package source/hash fields ---'
sed -n '1,80p' uv.lock
python3 - <<'PY'
from pathlib import Path
text = Path("uv.lock").read_text().splitlines()
for i, line in enumerate(text):
    if line.strip() == 'name = "cryptography"':
        for j in range(max(0, i - 3), min(len(text), i + 35)):
            print(f"{j+1}: {text[j]}")
PY

printf '%s\n' '--- tracked install entry points ---'
for f in install.sh doozer/Dockerfile doozer/container_install.sh ocp-build-data-validator/Dockerfile ocp-build-data-validator/deploy/Dockerfile.base; do
  if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
    echo "### $f"
    sed -n '1,180p' "$f"
  fi
done

printf '%s\n' '--- targeted diff summary ---'
git diff --stat -- pyproject.toml uv.lock
git diff --unified=3 -- pyproject.toml uv.lock || true

Repository: openshift-eng/art-tools

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import re
from pathlib import Path

pyproject = Path("pyproject.toml").read_text()
lock = Path("uv.lock").read_text()

dep = re.search(r'^\s*"cryptography([^"]*)",\s*$', pyproject, re.M)
pkg = re.search(
    r'\[\[package\]\]\s*name = "cryptography"\s*'
    r'version = "([^"]+)"\s*'
    r'.*?sdist = \{[^}]*hash = "([^"]+)"',
    lock,
    re.S,
)
assert dep, "cryptography is absent from pyproject.toml"
assert pkg, "cryptography is absent or lacks a locked source hash in uv.lock"

print("pyproject_specifier:", dep.group(1))
print("locked_version:", pkg.group(1))
print("locked_sdist_hash:", pkg.group(2))
print("specifier_is_exact:", bool(re.fullmatch(r"==\d+\.\d+\.\d+", dep.group(1))))
print("lock_version_satisfies_declared_lower_bound:",
      tuple(map(int, pkg.group(1).split("."))) >=
      tuple(map(int, re.search(r">=(\d+\.\d+\.\d+)", dep.group(1)).group(1).split("."))))
PY

printf '%s\n' '--- uv installation controls in tracked files ---'
rg -n -S 'uv (sync|lock)|--locked|--frozen|pip install \.' \
  -g '*.yml' -g '*.yaml' -g '*.sh' -g 'Dockerfile*' -g '*.md' . || true

printf '%s\n' '--- lockfile tracking ---'
git ls-files --stage uv.lock

Repository: openshift-eng/art-tools

Length of output: 787


Dependency Version Not Pinned (CWE-829): Inclusion of Functionality from Untrusted Control Sphere

Reachability: External · Exploitability: Difficult

Pin the production dependency to an exact version.

uv.lock currently resolves cryptography to 50.0.0 with hashes, but the project metadata still permits later versions. Use cryptography==50.0.0 and update uv.lock.

Suggested change
-    "cryptography>=50.0.0",
+    "cryptography==50.0.0",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"cryptography>=50.0.0",
"cryptography==50.0.0",
🤖 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 `@pyproject.toml` at line 40, Update the cryptography dependency declaration in
pyproject.toml from a minimum version to the exact version 50.0.0, then
regenerate uv.lock so its metadata matches the pinned requirement.

Source: Path instructions

"defusedxml>=0.7.1",
"dockerfile-parse>=2.0.1",
"errata-tool~=1.31.0",
Expand Down
Loading
Loading