Skip to content

feat: add Cursor Agent CLI container image#103

Merged
EmilienM merged 1 commit intomainfrom
cursor-cli
Mar 13, 2026
Merged

feat: add Cursor Agent CLI container image#103
EmilienM merged 1 commit intomainfrom
cursor-cli

Conversation

@EmilienM
Copy link
Contributor

@EmilienM EmilienM commented Mar 12, 2026

Pull Request Description

Summary

Add a second container image for Cursor's Agent CLI alongside the
existing Claude Code CLI image. The build workflow now uses a matrix
strategy to build both images in parallel, and the Makefile supports
individual (build-claude, build-cursor) or combined (build) targets.

The Cursor image is published as ghcr.io/opendatahub-io/ai-helpers-cursor
and shares the same base tooling (Fedora, Node.js, Python, uv, gcloud,
oc) as the Claude image.

Test:

podman run -it --rm \
    --pull newer \
    --userns=keep-id \
    -e CURSOR_API_KEY="${CURSOR_API_KEY}" \
    -v "$(pwd):$(pwd):z" \
    -w "$(pwd)" localhost/ai-helpers-cursor:latest "how are you?"
I'm doing well, thanks for asking! Ready to help you with whatever you need in the ai-helpers repository. What can I do for you?

Type of Contribution

  • 📝 New command
  • 🎯 New skill
  • 🤖 New agent
  • 💎 New Gemini Gem
  • 📚 Documentation update
  • 🐛 Bug fix
  • 🔄 Refactoring/cleanup
  • 🏗️ Infrastructure/tooling
  • 📋 New category addition

Summary by CodeRabbit

  • New Features

    • Cursor Agent CLI now available as a containerized deployment option with pre-built images.
  • Documentation

    • Added comprehensive guide for running Cursor Agent in a container, including environment setup, configuration examples, and helper utilities for easy launching.
  • Build & Infrastructure

    • Build system extended to support multi-image container builds with expanded CI/CD pipeline triggers.

Add a second container image for Cursor's Agent CLI alongside the
existing Claude Code CLI image. The build workflow now uses a matrix
strategy to build both images in parallel, and the Makefile supports
individual (build-claude, build-cursor) or combined (build) targets.

The Cursor image is published as ghcr.io/opendatahub-io/ai-helpers-cursor
and shares the same base tooling (Fedora, Node.js, Python, uv, gcloud,
oc) as the Claude image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Emilien Macchi <emacchi@redhat.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

The pull request expands container image support from a single Claude image to multiple images (Claude and Cursor) across the build pipeline. The GitHub Actions workflow is updated to use a matrix strategy for building different container images with distinct Containerfiles and naming conventions. The Makefile is restructured to define per-image build variables and targets. A new Containerfile for the Cursor image is added, which installs development tools, Google Cloud CLI, OpenShift client, and configures a non-root user. Documentation is added to explain container execution patterns for the Cursor Agent CLI.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a Cursor Agent CLI container image alongside the existing Claude image.
Description check ✅ Passed The description covers the summary, type of contribution (infrastructure/tooling), and testing validation, but omits several template sections including Changes Made details, required checks completion, and platform testing confirmation.
Agentskills.Io Specification Compliance ✅ Passed The PR modifies only .github/workflows/build.yml, Makefile, README.md, and images/cursor/Containerfile; the helpers/skills/ directory remains unmodified, so the specification compliance check is not applicable.
Ethical Compliance ✅ Passed PR modifies only infrastructure and documentation files; no changes to helpers/ directory where ethical guidelines apply.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan for PR comments
  • Generate coding plan

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 and usage tips.


RUN echo '[google-cloud-cli]' > /etc/yum.repos.d/google-cloud-sdk.repo && \
echo 'name=Google Cloud CLI' >> /etc/yum.repos.d/google-cloud-sdk.repo && \
echo 'baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el10-$basearch' >> /etc/yum.repos.d/google-cloud-sdk.repo && \
Copy link
Contributor

Choose a reason for hiding this comment

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

I think they only support x86_64: https://docs.cloud.google.com/sdk/docs/install-sdk#rpm so the $basearch is not needed here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/build.yml (1)

38-46: ⚠️ Potential issue | 🟠 Major

Pin all GitHub Actions to full commit SHAs (CWE-494).

Lines 38-46 and 52-64 use mutable tags (@v6, @v4, @v7) instead of commit SHAs. If upstream tags are retargeted or compromised, the workflow executes attacker-controlled code.

Replace each action with its full commit SHA:

  • actions/checkout@v6actions/checkout@<sha> (v6)
  • docker/setup-buildx-action@v4docker/setup-buildx-action@<sha> (v4)
  • docker/login-action@v4docker/login-action@<sha> (v4)
  • docker/metadata-action@v6docker/metadata-action@<sha> (v6)
  • docker/build-push-action@v7docker/build-push-action@<sha> (v7)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build.yml around lines 38 - 46, Replace mutable GitHub
Actions tags with their immutable commit SHAs for each action usage to mitigate
supply-chain risk: update actions/checkout@v6, docker/setup-buildx-action@v4,
docker/login-action@v4, docker/metadata-action@v6, and
docker/build-push-action@v7 to the exact commit SHA for the corresponding
release; locate the usages of these action identifiers in the workflow and
substitute the tag (e.g., `@v6/`@v4/@v7) with the full commit SHA retrieved from
the action's GitHub releases or commit history, ensuring every occurrence is
updated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build.yml:
- Around line 6-10: The pull_request workflow's 'paths' filter only watches
'images/**' and '.github/workflows/build.yml', which misses changes copied into
the image because both Containerfiles use 'context: .' and copy the repo into
'/opt/ai-helpers' (see images/cursor/Containerfile and
images/claude/Containerfile); update the workflow by removing the 'paths' filter
entirely or expanding it to include all files used in the build context (e.g.,
add '**' or explicit entries like 'helpers/**', 'scripts/**', 'Makefile',
'categories.yaml') so that changes affecting the image trigger the workflow.

In `@images/cursor/Containerfile`:
- Around line 32-33: The Dockerfile currently pipes remote installer scripts
straight into sh (the RUN curl -LsSf ... | ... sh invocation for the uv/astral
installer using UV_INSTALL_DIR and INSTALLER_NO_MODIFY_PATH), which risks
executing tampered code; change this to fetch a versioned release artifact,
verify its integrity (SHA256 or GPG) before execution, and only then run it:
download the installer to a file (pin a specific versioned URL), fetch or embed
the expected checksum or signature, validate the file with shasum/gpg, and
finally run the verified file (or prefer installing from a packaged release or
distro package) so the build fails if verification does not match.
- Around line 35-36: The Containerfile currently hardcodes the amd64 OpenShift
client archive in the RUN curl ... oc download line, which breaks arm64
multi-arch images; add a build ARG TARGETARCH at the top of the Containerfile
and use it to choose the correct archive name when downloading the oc binary
(e.g., map TARGETARCH to the archive suffix such that TARGETARCH=arm64 selects
openshift-client-linux-arm64.tar.gz and otherwise selects
openshift-client-linux.tar.gz), and then update the RUN curl ...
/usr/local/bin/oc command to reference that computed archive variable so
multi-arch builds pull the correct binary.

In `@Makefile`:
- Around line 65-71: Quote shell variables used in the image reference to
prevent word-splitting: update the Claude and Cursor build targets (the echo
lines and the build commands that use $(CONTAINER_RUNTIME),
$(CLAUDE_IMAGE_NAME), $(CURSOR_IMAGE_NAME), and $(IMAGE_TAG)) so the image tags
are quoted, e.g. use "$(CLAUDE_IMAGE_NAME):$(IMAGE_TAG)" and
"$(CURSOR_IMAGE_NAME):$(IMAGE_TAG)" in the -t arguments and in the echo
messages; keep $(CONTAINER_RUNTIME) invocation intact but ensure the image
references are wrapped in double quotes to avoid splitting.

In `@README.md`:
- Around line 215-224: The examples in README.md inline the actual
CURSOR_API_KEY value into the podman run command which leaks secrets via process
args; change both examples (the podman run snippets around the shown block and
the later one at 233-241) to avoid embedding the secret by passing only the
variable name (e.g., use -e CURSOR_API_KEY or --env CURSOR_API_KEY without
"=your-api-key"), or show using an env file (--env-file .env) or prompting to
export CURSOR_API_KEY in the shell beforehand, so the command no longer contains
the secret literal.

---

Outside diff comments:
In @.github/workflows/build.yml:
- Around line 38-46: Replace mutable GitHub Actions tags with their immutable
commit SHAs for each action usage to mitigate supply-chain risk: update
actions/checkout@v6, docker/setup-buildx-action@v4, docker/login-action@v4,
docker/metadata-action@v6, and docker/build-push-action@v7 to the exact commit
SHA for the corresponding release; locate the usages of these action identifiers
in the workflow and substitute the tag (e.g., `@v6/`@v4/@v7) with the full commit
SHA retrieved from the action's GitHub releases or commit history, ensuring
every occurrence is updated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 83b79900-1b1e-44a9-ade2-120de783024d

📥 Commits

Reviewing files that changed from the base of the PR and between fdcdc36 and 3f024f8.

📒 Files selected for processing (4)
  • .github/workflows/build.yml
  • Makefile
  • README.md
  • images/cursor/Containerfile

Comment on lines 6 to 10
pull_request:
branches: [ main ]
paths:
- 'images/claude/**'
- 'images/**'
- '.github/workflows/build.yml'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the workflow file exists and read the pull_request trigger section
cat -n .github/workflows/build.yml | head -30

Repository: opendatahub-io/ai-helpers

Length of output: 780


🏁 Script executed:

# Check the Containerfiles mentioned
ls -la images/*/Containerfile

Repository: opendatahub-io/ai-helpers

Length of output: 222


🏁 Script executed:

# Read the Containerfiles to verify context and COPY statements
echo "=== images/cursor/Containerfile ===" && wc -l images/cursor/Containerfile
echo "=== images/claude/Containerfile ===" && wc -l images/claude/Containerfile

Repository: opendatahub-io/ai-helpers

Length of output: 202


🏁 Script executed:

# Read around lines 50-52 for both Containerfiles
echo "=== images/cursor/Containerfile lines 45-55 ===" && sed -n '45,55p' images/cursor/Containerfile
echo "=== images/claude/Containerfile lines 45-55 ===" && sed -n '45,55p' images/claude/Containerfile

Repository: opendatahub-io/ai-helpers

Length of output: 770


🏁 Script executed:

# Check what files exist in the root and subdirectories that might be in build context
git ls-files | head -50

Repository: opendatahub-io/ai-helpers

Length of output: 1421


🏁 Script executed:

# Check for scripts directory and other files at root that could be copied
ls -la | grep -E '^d|^-' | head -20

Repository: opendatahub-io/ai-helpers

Length of output: 1323


🏁 Script executed:

# Check if there's a scripts directory with files
find . -maxdepth 2 -type f -name "Makefile" -o -path "*/scripts/*" 2>/dev/null | head -20

Repository: opendatahub-io/ai-helpers

Length of output: 192


🏁 Script executed:

# Verify the build context in the workflow - check if there's a docker build step that specifies context
cat -n .github/workflows/build.yml | grep -A 20 "docker build\|context:"

Repository: opendatahub-io/ai-helpers

Length of output: 371


Major: the PR trigger skips files that are copied into the image.

Both Containerfiles build with context: . (line 66) and copy the entire repository into /opt/ai-helpers (line 51 in both images/cursor/Containerfile and images/claude/Containerfile), so a PR that only changes helpers/**, scripts/**, Makefile, categories.yaml, or other files at repository root can modify the image contents while this workflow never runs. The path filter at lines 8-10 only covers images/** and .github/workflows/build.yml. Remove the paths filter or expand it to include all files in the build context.

Remediation
  pull_request:
    branches: [ main ]
-    paths:
-      - 'images/**'
-      - '.github/workflows/build.yml'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build.yml around lines 6 - 10, The pull_request workflow's
'paths' filter only watches 'images/**' and '.github/workflows/build.yml', which
misses changes copied into the image because both Containerfiles use 'context:
.' and copy the repo into '/opt/ai-helpers' (see images/cursor/Containerfile and
images/claude/Containerfile); update the workflow by removing the 'paths' filter
entirely or expanding it to include all files used in the build context (e.g.,
add '**' or explicit entries like 'helpers/**', 'scripts/**', 'Makefile',
'categories.yaml') so that changes affecting the image trigger the workflow.

Comment on lines +32 to +33
RUN curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR="/usr/local/bin/" INSTALLER_NO_MODIFY_PATH=1 sh

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n images/cursor/Containerfile | sed -n '25,65p'

Repository: opendatahub-io/ai-helpers

Length of output: 1850


Critical: uv and Cursor installers execute remote scripts without integrity verification (CWE-829).

Lines 32 and 58 both pipe unverified remote scripts directly to shell interpreters, allowing arbitrary code execution from upstream sources or CDN compromise during build. Version the installer URLs and verify checksums before execution.

Remediation
 # Install uv for PEP 723 script dependency management
-RUN curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR="/usr/local/bin/" INSTALLER_NO_MODIFY_PATH=1 sh
+ARG UV_INSTALL_URL=<versioned-url>
+ARG UV_INSTALL_SHA256=<published-sha256>
+RUN curl -fsSLo /tmp/uv-install.sh "${UV_INSTALL_URL}" \
+    && echo "${UV_INSTALL_SHA256}  /tmp/uv-install.sh" | sha256sum -c - \
+    && UV_INSTALL_DIR="/usr/local/bin/" INSTALLER_NO_MODIFY_PATH=1 sh /tmp/uv-install.sh \
+    && rm -f /tmp/uv-install.sh

 # Install Cursor CLI
-RUN curl -fsSL https://cursor.com/install | bash
+ARG CURSOR_INSTALL_URL=<versioned-url>
+ARG CURSOR_INSTALL_SHA256=<published-sha256>
+RUN curl -fsSLo /tmp/cursor-install.sh "${CURSOR_INSTALL_URL}" \
+    && echo "${CURSOR_INSTALL_SHA256}  /tmp/cursor-install.sh" | sha256sum -c - \
+    && bash /tmp/cursor-install.sh \
+    && rm -f /tmp/cursor-install.sh
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@images/cursor/Containerfile` around lines 32 - 33, The Dockerfile currently
pipes remote installer scripts straight into sh (the RUN curl -LsSf ... | ... sh
invocation for the uv/astral installer using UV_INSTALL_DIR and
INSTALLER_NO_MODIFY_PATH), which risks executing tampered code; change this to
fetch a versioned release artifact, verify its integrity (SHA256 or GPG) before
execution, and only then run it: download the installer to a file (pin a
specific versioned URL), fetch or embed the expected checksum or signature,
validate the file with shasum/gpg, and finally run the verified file (or prefer
installing from a packaged release or distro package) so the build fails if
verification does not match.

Comment on lines +35 to +36
RUN curl -LsSf https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz | tar xzf - -C /usr/local/bin/ oc \
&& chmod +x /usr/local/bin/oc
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "Containerfile" -type f

Repository: opendatahub-io/ai-helpers

Length of output: 128


🏁 Script executed:

find . -type f -name "*docker*" -o -name "*compose*" -o -name "*.yml" -o -name "*.yaml" | grep -E "(workflow|action|build)" | head -20

Repository: opendatahub-io/ai-helpers

Length of output: 264


🏁 Script executed:

find . -type f \( -name ".github" -o -name "docker-compose*" \) | head -20

Repository: opendatahub-io/ai-helpers

Length of output: 51


🏁 Script executed:

cd images/cursor && ls -la

Repository: opendatahub-io/ai-helpers

Length of output: 242


🏁 Script executed:

cat -n images/cursor/Containerfile

Repository: opendatahub-io/ai-helpers

Length of output: 2949


🏁 Script executed:

cat -n .github/workflows/build.yml

Repository: opendatahub-io/ai-helpers

Length of output: 2387


🏁 Script executed:

web_search
OpenShift mirror openshift-client-linux artifact naming conventions amd64 arm64

Repository: opendatahub-io/ai-helpers

Length of output: 167


🌐 Web query:

OpenShift client mirror openshift-client-linux-arm64.tar.gz amd64 arm64 artifacts

💡 Result:

OpenShift oc client tarballs are published on the public mirror under these patterns (pick either a specific version directory like 4.17.17/ or a moving channel like stable/, stable-4.14/, latest-4.16/, etc.):

Linux amd64 (x86_64)

https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/<channel-or-version>/openshift-client-linux.tar.gz

Red Hat docs also reference this ${ARCH} form (where ${ARCH} is x86_64, aarch64, etc.). (docs.redhat.com)

Linux arm64 (aarch64)

Commonly published as an explicit arm64 filename:

https://mirror.openshift.com/pub/openshift-v4/clients/ocp/<channel-or-version>/openshift-client-linux-arm64.tar.gz

Examples seen in the wild:

“Multi” layout (also used for arch-separated listings)

You may also find arch-separated directories like:

https://mirror.openshift.com/pub/openshift-v4/multi/clients/ocp/stable/amd64/

(mirror.openshift.com)

Citations:


Major: oc binary download must be architecture-aware for multi-arch builds.

The build workflow (.github/workflows/build.yml:68) publishes for both linux/amd64 and linux/arm64, but the Containerfile hardcodes the generic amd64 archive. The OpenShift mirror publishes distinct artifacts: openshift-client-linux.tar.gz (amd64) and openshift-client-linux-arm64.tar.gz (arm64). The arm64 image will receive the amd64 binary, causing runtime failures.

Parameterize the archive name using Docker's TARGETARCH build argument before publishing multi-arch images:

Remediation
+ARG TARGETARCH
-RUN curl -LsSf https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz | tar xzf - -C /usr/local/bin/ oc \
-    && chmod +x /usr/local/bin/oc
+RUN case "${TARGETARCH}" in \
+      amd64) oc_archive="openshift-client-linux.tar.gz" ;; \
+      arm64) oc_archive="openshift-client-linux-arm64.tar.gz" ;; \
+      *) echo "Unsupported TARGETARCH=${TARGETARCH}" >&2; exit 1 ;; \
+    esac \
+    && curl -fsSLo /tmp/oc.tgz "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/${oc_archive}" \
+    && tar xzf /tmp/oc.tgz -C /usr/local/bin/ oc \
+    && chmod +x /usr/local/bin/oc \
+    && rm -f /tmp/oc.tgz
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@images/cursor/Containerfile` around lines 35 - 36, The Containerfile
currently hardcodes the amd64 OpenShift client archive in the RUN curl ... oc
download line, which breaks arm64 multi-arch images; add a build ARG TARGETARCH
at the top of the Containerfile and use it to choose the correct archive name
when downloading the oc binary (e.g., map TARGETARCH to the archive suffix such
that TARGETARCH=arm64 selects openshift-client-linux-arm64.tar.gz and otherwise
selects openshift-client-linux.tar.gz), and then update the RUN curl ...
/usr/local/bin/oc command to reference that computed archive variable so
multi-arch builds pull the correct binary.

Comment on lines +65 to +71
@echo "Building Claude container image $(CLAUDE_IMAGE_NAME):$(IMAGE_TAG) with $(CONTAINER_RUNTIME)..."
$(CONTAINER_RUNTIME) build -f images/claude/Containerfile -t $(CLAUDE_IMAGE_NAME):$(IMAGE_TAG) .

.PHONY: build-cursor
build-cursor: ## Build Cursor CLI container image
@echo "Building Cursor container image $(CURSOR_IMAGE_NAME):$(IMAGE_TAG) with $(CONTAINER_RUNTIME)..."
$(CONTAINER_RUNTIME) build -f images/cursor/Containerfile -t $(CURSOR_IMAGE_NAME):$(IMAGE_TAG) .
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find and read the Makefile
fd -name Makefile -type f | head -5

Repository: opendatahub-io/ai-helpers

Length of output: 299


🏁 Script executed:

# Read the Makefile to see the full context
if [ -f Makefile ]; then
  wc -l Makefile
  cat -n Makefile
fi

Repository: opendatahub-io/ai-helpers

Length of output: 3695


Quote the image reference in build targets.

IMAGE_TAG, CLAUDE_IMAGE_NAME, and CURSOR_IMAGE_NAME are overrideable from the environment/CLI. Per the Makefile security guideline, quote shell variables in targets to prevent word-splitting.

Remediation
-	$(CONTAINER_RUNTIME) build -f images/claude/Containerfile -t $(CLAUDE_IMAGE_NAME):$(IMAGE_TAG) .
+	$(CONTAINER_RUNTIME) build -f images/claude/Containerfile -t "$(CLAUDE_IMAGE_NAME):$(IMAGE_TAG)" .

-	$(CONTAINER_RUNTIME) build -f images/cursor/Containerfile -t $(CURSOR_IMAGE_NAME):$(IMAGE_TAG) .
+	$(CONTAINER_RUNTIME) build -f images/cursor/Containerfile -t "$(CURSOR_IMAGE_NAME):$(IMAGE_TAG)" .
📝 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
@echo "Building Claude container image $(CLAUDE_IMAGE_NAME):$(IMAGE_TAG) with $(CONTAINER_RUNTIME)..."
$(CONTAINER_RUNTIME) build -f images/claude/Containerfile -t $(CLAUDE_IMAGE_NAME):$(IMAGE_TAG) .
.PHONY: build-cursor
build-cursor: ## Build Cursor CLI container image
@echo "Building Cursor container image $(CURSOR_IMAGE_NAME):$(IMAGE_TAG) with $(CONTAINER_RUNTIME)..."
$(CONTAINER_RUNTIME) build -f images/cursor/Containerfile -t $(CURSOR_IMAGE_NAME):$(IMAGE_TAG) .
`@echo` "Building Claude container image $(CLAUDE_IMAGE_NAME):$(IMAGE_TAG) with $(CONTAINER_RUNTIME)..."
$(CONTAINER_RUNTIME) build -f images/claude/Containerfile -t "$(CLAUDE_IMAGE_NAME):$(IMAGE_TAG)" .
.PHONY: build-cursor
build-cursor: ## Build Cursor CLI container image
`@echo` "Building Cursor container image $(CURSOR_IMAGE_NAME):$(IMAGE_TAG) with $(CONTAINER_RUNTIME)..."
$(CONTAINER_RUNTIME) build -f images/cursor/Containerfile -t "$(CURSOR_IMAGE_NAME):$(IMAGE_TAG)" .
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 65 - 71, Quote shell variables used in the image
reference to prevent word-splitting: update the Claude and Cursor build targets
(the echo lines and the build commands that use $(CONTAINER_RUNTIME),
$(CLAUDE_IMAGE_NAME), $(CURSOR_IMAGE_NAME), and $(IMAGE_TAG)) so the image tags
are quoted, e.g. use "$(CLAUDE_IMAGE_NAME):$(IMAGE_TAG)" and
"$(CURSOR_IMAGE_NAME):$(IMAGE_TAG)" in the -t arguments and in the echo
messages; keep $(CONTAINER_RUNTIME) invocation intact but ensure the image
references are wrapped in double quotes to avoid splitting.

Comment on lines +215 to +224
To use the Cursor Agent CLI, you need to pass your `CURSOR_API_KEY`:

```bash
podman run -it --rm \
--pull newer \
--userns=keep-id \
-e CURSOR_API_KEY=your-api-key \
-v $(pwd):$(pwd):z \
-w $(pwd) \
ghcr.io/opendatahub-io/ai-helpers-cursor:latest
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Major: both examples expose CURSOR_API_KEY in host process args (CWE-312/CWE-200).

Inlining the value in podman run — including "${CURSOR_API_KEY}" in the helper — expands the secret into the spawned command line. That leaks it via ps, and the one-off example also encourages shell-history exposure. Pass the variable name through instead.

Remediation
-  -e CURSOR_API_KEY=your-api-key \
+  -e CURSOR_API_KEY \
...
-    -e CURSOR_API_KEY="${CURSOR_API_KEY}" \
+    -e CURSOR_API_KEY \

Also applies to: 233-241

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 215 - 224, The examples in README.md inline the
actual CURSOR_API_KEY value into the podman run command which leaks secrets via
process args; change both examples (the podman run snippets around the shown
block and the later one at 233-241) to avoid embedding the secret by passing
only the variable name (e.g., use -e CURSOR_API_KEY or --env CURSOR_API_KEY
without "=your-api-key"), or show using an env file (--env-file .env) or
prompting to export CURSOR_API_KEY in the shell beforehand, so the command no
longer contains the secret literal.

@EmilienM EmilienM merged commit 0d41f30 into main Mar 13, 2026
4 checks passed
@EmilienM
Copy link
Contributor Author

I'll go with the PR as is and we can improve later.

@EmilienM EmilienM deleted the cursor-cli branch March 13, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants