Skip to content

Commit 155285f

Browse files
Merge pull request #86 from zacharyyonash/python-remediated-demo
Python remediated demo
2 parents 7bcc404 + 70c3ef7 commit 155285f

12 files changed

Lines changed: 250 additions & 0 deletions

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env bash
2+
3+
. ../../base.sh
4+
5+
TYPE_SPEED=100
6+
DEMO_PROMPT="${GREEN}${CYAN}\W ${COLOR_RESET}"
7+
clear
8+
9+
echo -e "
10+
Demo: Chainguard Libraries for Python - Remediated Repository
11+
12+
CVE-2021-23727 in Celery 5.2.1 - Three approaches:
13+
1. Vulnerable: Celery 5.2.1 from PyPI
14+
2. Upstream Fix: Celery 5.2.2 from PyPI
15+
3. Remediated: Celery 5.2.1 from Chainguard with backported fix
16+
"
17+
wait
18+
19+
banner "Setup"
20+
21+
read -p "Enter your Chainguard organization name: " ORG_NAME
22+
export ORG_NAME
23+
24+
banner "Step 1: Vulnerable (Celery 5.2.1 from PyPI)"
25+
wait
26+
pei "cd step1-orig"
27+
pe "cat requirements.txt"
28+
pei ""
29+
30+
pei "docker build --no-cache -t celery-demo:vulnerable ."
31+
32+
banner "This run will work, as celery 5.2.1 allows OS command injection."
33+
wait
34+
pei "docker run --rm celery-demo:vulnerable"
35+
36+
banner "Step 2: Upstream Fix (Celery 5.2.2 from PyPI)"
37+
wait
38+
39+
pei "cd ../step2-upstream-fix"
40+
pe "cat requirements.txt"
41+
42+
pei "docker build --no-cache -t celery-demo:fixed ."
43+
banner "This will throw an exception, as the OS command injection vuln is fixed in 5.2.2."
44+
wait
45+
pei "docker run --rm celery-demo:fixed"
46+
47+
banner "Step 3: Remediated (Celery 5.2.1 from Chainguard)"
48+
wait
49+
pei "cd ../step3-cg"
50+
pe "cat requirements.txt"
51+
52+
pei "CREDS=\$(chainctl auth pull-token --repository=python --parent=\$ORG_NAME --name=py-demo-\$USER --ttl=1h -o json)"
53+
54+
{
55+
echo "machine libraries.cgr.dev"
56+
echo "login $(echo $CREDS | jq -r .identity_id)"
57+
echo "password $(echo $CREDS | jq -r .token)"
58+
} > .netrc
59+
60+
pe "cat pyproject.toml"
61+
pei ""
62+
63+
pei "docker build --no-cache --secret id=netrc,src=.netrc -t celery-demo:remediated ."
64+
banner "This will throw an exception - celery 5.2.1 from Chainguard's python-remediated repository includes the CVE fix."
65+
wait
66+
pei "docker run --rm celery-demo:remediated"
67+
68+
banner "Use chainctl libraries verify to determine package coverage from Chainguard."
69+
wait
70+
pei "chainctl libraries verify celery-demo:remediated"
71+
72+
banner "Cleanup"
73+
wait
74+
pei "ID=\$(chainctl iam ids ls --parent=\$ORG_NAME -o json | jq -r '.items[] | select(.name | startswith(\"py-demo\")) | .id')"
75+
pei "chainctl iam identities delete \$ID --parent \$ORG_NAME --yes"
76+
pei "rm .netrc"
77+
pei "docker rmi celery-demo:vulnerable celery-demo:fixed celery-demo:remediated"
78+
79+
echo -e "
80+
${GREEN}Demo Complete!${COLOR_RESET}
81+
82+
Key Takeaways:
83+
✓ Celery 5.2.1 has CVE-2021-23727
84+
✓ Traditional fix: Upgrade to 5.2.2 (may break compatibility)
85+
✓ Chainguard: Use 5.2.1 with backported fix
86+
- Same version, no compatibility risk
87+
- Security fix included
88+
- Full SBOM and provenance
89+
"
90+
91+
exit 0
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Chainguard Libraries for Python Remediated
2+
3+
This demo shows how Chainguard's python-remediated repository backports security fixes to older package versions, letting you maintain version stability while staying secure.
4+
5+
We'll use CVE-2021-23727 (stored command injection in Celery 5.2.1) to demonstrate three approaches:
6+
1. **Vulnerable** - Celery 5.2.1 from PyPI
7+
2. **Upstream Fix** - Celery 5.2.2 from PyPI
8+
3. **Remediated** - Celery 5.2.1 from Chainguard with backported fix
9+
10+
Run `./demo.sh` for an interactive walkthrough.
11+
12+
## Prerequisites
13+
14+
- Docker with BuildKit support
15+
- chainctl authenticated with `libraries.python.pull` entitlements
16+
- jq for JSON parsing
17+
- Your Chainguard organization name
18+
19+
## Setup
20+
21+
```bash
22+
export ORG_NAME="<your-org-name>"
23+
```
24+
25+
## Step 1: Vulnerable Build (Celery 5.2.1 from PyPI)
26+
27+
```bash
28+
cd step1-orig
29+
docker build -t celery-demo:vulnerable .
30+
docker run --rm celery-demo:vulnerable
31+
```
32+
33+
## Step 2: Upstream Fix (Celery 5.2.2 from PyPI)
34+
35+
```bash
36+
cd ../step2-upstream-fix
37+
docker build -t celery-demo:fixed .
38+
docker run --rm celery-demo:fixed
39+
```
40+
41+
## Step 3: Chainguard Remediated (Celery 5.2.1 with Fix)
42+
43+
```bash
44+
cd ../step3-cg
45+
46+
CREDS=$(chainctl auth pull-token --repository=python --parent=$ORG_NAME --name="py-demo-$USER" --ttl=1h -o json)
47+
cat > .netrc <<EOF
48+
machine libraries.cgr.dev
49+
login $(echo $CREDS | jq -r .identity_id)
50+
password $(echo $CREDS | jq -r .token)
51+
EOF
52+
53+
docker build --secret id=netrc,src=.netrc -t celery-demo:remediated .
54+
docker run --rm celery-demo:remediated
55+
56+
chainctl libraries verify celery-demo:remediated
57+
```
58+
59+
## Cleanup
60+
61+
```bash
62+
ID=$(chainctl iam ids ls --parent=$ORG_NAME -o json | jq -r '.items[] | select(.name | startswith("py-demo")) | .id')
63+
chainctl iam identities delete "$ID" --parent $ORG_NAME --yes
64+
rm .netrc
65+
docker rmi celery-demo:vulnerable celery-demo:fixed celery-demo:remediated
66+
```
67+
68+
## About CVE-2021-23727
69+
70+
Stored command injection in Celery < 5.2.2. The `exception_to_python()` function loads arbitrary Python classes from backend metadata without validation. Version 5.2.2 added proper validation, and Chainguard backported this fix to 5.2.1.
71+
72+
## Why Remediated Libraries
73+
74+
Traditional security patching forces a choice:
75+
- **Upgrade**: Get fixes but risk breaking changes
76+
- **Stay**: Maintain stability but remain vulnerable
77+
78+
Chainguard's remediated libraries provide both:
79+
- Keep the same version (5.2.1)
80+
- Get the security fix backported
81+
- Full SBOM and provenance
82+
- Verifiable with chainctl
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM python:3.13
2+
3+
WORKDIR /app
4+
5+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
6+
ENV PATH="/root/.local/bin:$PATH"
7+
8+
COPY requirements.txt app.py ./
9+
10+
# Create virtual environment
11+
RUN uv venv /app/venv
12+
ENV PATH="/app/venv/bin:$PATH"
13+
RUN uv pip install --no-cache -r requirements.txt
14+
15+
ENTRYPOINT ["/app/venv/bin/python", "app.py"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from celery.backends.base import Backend
2+
from celery import Celery
3+
b = Backend(Celery())
4+
exc = {'exc_module':'os', 'exc_type':'system', 'exc_message':'id'}
5+
b.exception_to_python(exc)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
celery==5.2.1
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM python:3.13
2+
3+
WORKDIR /app
4+
5+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
6+
ENV PATH="/root/.local/bin:$PATH"
7+
8+
COPY requirements.txt app.py ./
9+
10+
# Create virtual environment
11+
RUN uv venv /app/venv
12+
ENV PATH="/app/venv/bin:$PATH"
13+
RUN uv pip install --no-cache -r requirements.txt
14+
15+
ENTRYPOINT ["/app/venv/bin/python", "app.py"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from celery.backends.base import Backend
2+
from celery import Celery
3+
b = Backend(Celery())
4+
exc = {'exc_module':'os', 'exc_type':'system', 'exc_message':'id'}
5+
b.exception_to_python(exc)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
celery==5.2.2
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM cgr.dev/chainguard-private/python:3.13-dev
2+
3+
WORKDIR /app
4+
5+
COPY pyproject.toml requirements.txt app.py ./
6+
7+
RUN --mount=type=secret,id=netrc,target=/home/nonroot/.netrc,uid=65532 \
8+
uv venv /app/venv && \
9+
export PATH="/app/venv/bin:$PATH" && \
10+
uv pip install --no-cache -r requirements.txt
11+
12+
ENTRYPOINT ["/app/venv/bin/python", "app.py"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from celery.backends.base import Backend
2+
from celery import Celery
3+
b = Backend(Celery())
4+
exc = {'exc_module':'os', 'exc_type':'system', 'exc_message':'id'}
5+
b.exception_to_python(exc)

0 commit comments

Comments
 (0)