diff --git a/components/runners/ambient-runner/Dockerfile b/components/runners/ambient-runner/Dockerfile index 0d15b77cf..ca2c7a36a 100755 --- a/components/runners/ambient-runner/Dockerfile +++ b/components/runners/ambient-runner/Dockerfile @@ -46,6 +46,12 @@ RUN npm install -g @google/gemini-cli@${GEMINI_CLI_VERSION} && \ # Install CodeRabbit CLI (official install script, binary for current arch) RUN curl -fsSL https://cli.coderabbit.ai/install.sh | CODERABBIT_INSTALL_DIR=/usr/local/bin sh +# Install prodsec-skills (Product Security guidance available to every session) +ARG PRODSEC_SKILLS_REF=d1b9800932ca3bf5265b4bb5dccf6662000fc4c4 +RUN git clone https://github.com/RedHatProductSecurity/prodsec-skills.git /app/prodsec-skills && \ + git -C /app/prodsec-skills checkout --detach "${PRODSEC_SKILLS_REF}" && \ + rm -rf /app/prodsec-skills/.git + # Set environment variables ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/components/runners/ambient-runner/ambient_runner/bridges/claude/bridge.py b/components/runners/ambient-runner/ambient_runner/bridges/claude/bridge.py index 893e2348c..49980349f 100644 --- a/components/runners/ambient-runner/ambient_runner/bridges/claude/bridge.py +++ b/components/runners/ambient-runner/ambient_runner/bridges/claude/bridge.py @@ -15,6 +15,7 @@ import os import time from collections.abc import AsyncIterator +from pathlib import Path from typing import Any from ag_ui.core import ( @@ -674,6 +675,13 @@ async def _setup_platform(self) -> None: # Workspace paths cwd_path, add_dirs = resolve_workspace_paths(self._context) + + # Prodsec-skills: expose the AI Context Module (module/) so agents + # find module/AGENTS.md as the entry point, not the contributor AGENTS.md + _prodsec_module = "/app/prodsec-skills/module" + if Path(f"{_prodsec_module}/skills").exists() and _prodsec_module not in add_dirs: + add_dirs.append(_prodsec_module) + if add_dirs: os.environ["CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD"] = "1" diff --git a/components/runners/ambient-runner/ambient_runner/platform/prompts.py b/components/runners/ambient-runner/ambient_runner/platform/prompts.py index 7de1f8433..bb3c6a0e9 100644 --- a/components/runners/ambient-runner/ambient_runner/platform/prompts.py +++ b/components/runners/ambient-runner/ambient_runner/platform/prompts.py @@ -98,6 +98,19 @@ "attention.\n\n" ) +PRODSEC_SKILLS_PROMPT = ( + "## Security Skills\n" + "Product Security skills are available at `/app/prodsec-skills/module/skills/`. " + "Each skill is a directory containing a `SKILL.md` file. Choose a skill by reading " + "its `description` field — it is written as an invocation condition, not a summary. " + "When performing security-sensitive tasks (code review, writing auth/crypto/network " + "code, configuring infrastructure, auditing), read the relevant skill before " + "proceeding. Example:\n" + " `Using /app/prodsec-skills/module/skills/go-security/SKILL.md`: review this " + "handler for injection risks.\n" + "See `/app/prodsec-skills/module/AGENTS.md` for the full index and usage guide.\n\n" +) + RESTART_TOOL_DESCRIPTION = ( "Restart the Claude session to recover from issues, clear state, " "or get a fresh connection. Use this if you detect you're in a " @@ -231,6 +244,10 @@ def build_workspace_context_prompt( if os.getenv("GITLAB_TOKEN"): prompt += GITLAB_TOKEN_PROMPT + # Prodsec-skills: security guidance for every session + if Path("/app/prodsec-skills/module/skills").exists(): + prompt += PRODSEC_SKILLS_PROMPT + # Workflow instructions if ambient_config.get("systemPrompt"): prompt += f"## Workflow Instructions\n{ambient_config['systemPrompt']}\n\n"