From 7c89479ed528a663b90af284a47cbc930016c4ee Mon Sep 17 00:00:00 2001 From: Michalis Papadopoullos <156905910+mpapadopoullos@users.noreply.github.com> Date: Mon, 11 May 2026 12:45:26 +0200 Subject: [PATCH 1/3] feat(secdevai-tool): refined SKILL.md - Introduce `tool_resolution` mapping to select security tools per programming language (Python, Go, Java, JavaScript, Rust) - Add structured `input_schema` defining allowed tool selection (`bandit`, `gosec`, `scorecard`, `semgrep`, `all`) - Standardize script path usage via `${BASE_DIR}` for container execution helper script - Refactor tool execution documentation with clearer per-tool sections (Bandit, GoSec, Scorecard, Semgrep) - Improve Semgrep container workflow - Add `language_detection` rules based on common project files for automatic tool configuration - Provide explicit example of Semgrep command construction with multiple `--config` flags --- lola-module/skills/secdevai-tool/SKILL.md | 210 +++++++++++++++++++--- 1 file changed, 183 insertions(+), 27 deletions(-) diff --git a/lola-module/skills/secdevai-tool/SKILL.md b/lola-module/skills/secdevai-tool/SKILL.md index 7bf0c02..33cd2ca 100644 --- a/lola-module/skills/secdevai-tool/SKILL.md +++ b/lola-module/skills/secdevai-tool/SKILL.md @@ -27,6 +27,36 @@ Run external security analysis tools inside isolated, read-only containers. Invo | scorecard | https://github.com/ossf/scorecard | `gcr.io/openssf/scorecard:stable` | All | | semgrep | https://github.com/semgrep/semgrep | `local/semgrep` (built locally) | Multi-language | +```yaml +tool_resolution: + python: + tools: + - bandit + - semgrep + - scorecard + + go: + tools: + - gosec + - semgrep + - scorecard + + java: + tools: + - semgrep + - scorecard + + javascript: + tools: + - semgrep + - scorecard + + rust: + tools: + - semgrep + - scorecard +``` + ## Prerequisites Tools run exclusively inside containers for isolation and reproducibility. A container runtime is required: @@ -34,9 +64,9 @@ Tools run exclusively inside containers for isolation and reproducibility. A con - **Podman** (recommended): `brew install podman` / `dnf install podman` / `apt install podman` - **Docker**: https://docs.docker.com/get-docker/ -The helper script `scripts/container-run.sh` auto-detects podman or docker at runtime, runs containers with hardened defaults (all capabilities dropped, no-new-privileges, network disabled, resource limits), and prints installation guidance if neither runtime is found. +The helper script `scripts/container-run.sh` auto-detects `podman` or `docker` at runtime, runs containers with hardened defaults (all capabilities dropped, no-new-privileges, network disabled, resource limits), and prints installation guidance if neither runtime is found. -Note: All scripts are under the BASE directory (e.g.: `.claude/` or `.cursor/`). +**Note**: All scripts are under the `${BASE_DIR}` directory (e.g.: `.claude/` or `.cursor/`). ## Expected Response @@ -50,54 +80,180 @@ When this skill is invoked, follow these steps: - Show usage examples - Do NOT run any tool automatically — wait for user input +```yaml +input_schema: + tool: + - bandit + - gosec + - scorecard + - semgrep + - all +``` + ### Step 2: Run Tool -Use `scripts/container-run.sh` to run the container image for the chosen tool. The script auto-detects podman/docker, mounts the current directory read-only at `/src`, and forwards any extra arguments to the container entrypoint. +Use `${BASE_DIR}/scripts/container-run.sh` to run the container image for the chosen tool. The script auto-detects podman/docker, mounts the current directory read-only at `/src`, and forwards any extra arguments to the container entrypoint. -```bash +```sh # Usage: scripts/container-run.sh [--env K=V]... [args...] # Network is always disabled (--network=none). +``` + +#### Tool: Bandit +**Usage:** +```sh # bandit (Python) -scripts/container-run.sh ghcr.io/pycqa/bandit/bandit -r . -f json -q +${BASE_DIR}/scripts/container-run.sh ghcr.io/pycqa/bandit/bandit -r . -f json -q +``` + +#### Tool: GoSec +**Usage:** +```sh # gosec (Go) -scripts/container-run.sh ghcr.io/securego/gosec:latest -fmt=sarif ./... +${BASE_DIR}/scripts/container-run.sh ghcr.io/securego/gosec:latest -fmt=sarif ./... +``` -# scorecard (local-only, filesystem checks only — no GitHub API access) -scripts/container-run.sh gcr.io/openssf/scorecard:stable --local . --format json +#### Tool: Scorecard -# semgrep — requires a locally built image (see build instructions below) -scripts/container-run.sh --env HOME=/tmp local/semgrep scan /src --config /sgrules/ --sarif --metrics off --disable-version-check +**Usage:** +```sh +# scorecard (local-only, filesystem checks only — no GitHub API access) +${BASE_DIR}/scripts/container-run.sh gcr.io/openssf/scorecard:stable --local . --format json ``` **Scorecard**: Runs in `--local` mode only (no network, no GitHub token). Filesystem-based checks work (pinned dependencies, SECURITY.md, dangerous workflows); checks requiring the GitHub API (branch protection, CI/CD status) are skipped. +#### Tool: semgrep + +**Usage:** +```sh +# semgrep — requires a locally built image (see build instructions below) +${BASE_DIR}/scripts/container-run.sh --env HOME=/tmp local/semgrep scan /src --config /sgrules/ --sarif --metrics off --disable-version-check +``` + **Semgrep**: Uses a locally built image (`local/semgrep`) that bundles two offline rule sets: - `/sgrules` — [semgrep/semgrep-rules](https://github.com/semgrep/semgrep-rules) (community rules) - `/sgrules-trail` — [trailofbits/semgrep-rules](https://github.com/trailofbits/semgrep-rules) (security-focused, AGPL-3.0) -Because the rules are baked into the image, the container runs with `--network=none` like all other tools. `--env HOME=/tmp` is required because semgrep writes cache state to `$HOME` and the container filesystem is read-only (only `/tmp` is writable). +**Build Semgrep container**: +```sh +# Docker +docker buildx build . -t local/semgrep \ + -f ${BASE_DIR}/lola-module/skills/secdevai-tool/scripts/Dockerfile.semgrep -Build the image once from the project root (network required at build time only). Determine `` from the deployment context (`.cursor`, `.claude`, or `.gemini`): +# Podman +podman build . -t local/semgrep \ + -f ${BASE_DIR}/lola-module/skills/secdevai-tool/scripts/Dockerfile.semgrep +``` -```bash -docker buildx build . -t local/semgrep \ - -f /lola-module/skills/secdevai-tool/scripts/Dockerfile.semgrep +**Semgrep config resolution** +```yaml +semgrep_config_resolution: + python: + configs: + - /sgrules/python + + go: + configs: + - /sgrules/go + - /sgrules-trail/go + + javascript: + configs: + - /sgrules/javascript + + typescript: + configs: + - /sgrules/typescript + + java: + configs: + - /sgrules/java + + ruby: + configs: + - /sgrules/ruby + - /sgrules-trail/ruby + + rust: + configs: + - /sgrules/rust + - /sgrules-trail/rs + + all: + configs: + - /sgrules + - /sgrules-trail +``` + +Select `--config` based on the detected project language. + +**Language detection:** +```yaml +language_detection: + python: + files: + - pyproject.toml + - requirements.txt + - setup.py + - Pipfile + - poetry.lock + - "*.py" + + go: + files: + - go.mod + - go.sum + - "*.go" + + typescript: + files: + - tsconfig.json + - "*.ts" + - "*.tsx" + + javascript: + files: + - package.json + - "*.js" + - "*.jsx" + + java: + files: + - pom.xml + - build.gradle + - build.gradle.kts + - "*.java" + + ruby: + files: + - Gemfile + - Gemfile.lock + - "*.rb" + + rust: + files: + - Cargo.toml + - Cargo.lock + - "*.rs" +``` + +**Example Resolution:** +```sh +${BASE_DIR}/scripts/container-run.sh \ + --env HOME=/tmp \ + local/semgrep \ + scan /src \ + --config /sgrules/go \ + --config /sgrules-trail/go \ + --sarif \ + --metrics off \ + --disable-version-check ``` -Select `--config` based on the detected project language: - -| Language | `--config` flags | -|----------|-----------------| -| Python | `--config /sgrules/python` | -| Go | `--config /sgrules/go --config /sgrules-trail/go` | -| JavaScript | `--config /sgrules/javascript` | -| TypeScript | `--config /sgrules/typescript` | -| Java | `--config /sgrules/java` | -| Ruby | `--config /sgrules/ruby --config /sgrules-trail/ruby` | -| Rust | `--config /sgrules/rust --config /sgrules-trail/rs` | -| All | `--config /sgrules --config /sgrules-trail` | +#### Tool: all **If `all` is specified**: detect the project language and run each relevant(see Available Tools) tool sequentially, collecting all JSON output. From 284e7733dac65fad2c0d2df87e17cdde17e78912 Mon Sep 17 00:00:00 2001 From: Michalis Papadopoullos <156905910+mpapadopoullos@users.noreply.github.com> Date: Mon, 11 May 2026 13:34:28 +0200 Subject: [PATCH 2/3] feat(secdevai-tool): refined SKILL.md --- lola-module/skills/secdevai-tool/SKILL.md | 21 +++++----- .../secdevai-tool/scripts/build-semgrep.sh | 40 +++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) create mode 100755 lola-module/skills/secdevai-tool/scripts/build-semgrep.sh diff --git a/lola-module/skills/secdevai-tool/SKILL.md b/lola-module/skills/secdevai-tool/SKILL.md index 33cd2ca..a85340e 100644 --- a/lola-module/skills/secdevai-tool/SKILL.md +++ b/lola-module/skills/secdevai-tool/SKILL.md @@ -130,22 +130,23 @@ ${BASE_DIR}/scripts/container-run.sh gcr.io/openssf/scorecard:stable --local . - **Usage:** ```sh # semgrep — requires a locally built image (see build instructions below) -${BASE_DIR}/scripts/container-run.sh --env HOME=/tmp local/semgrep scan /src --config /sgrules/ --sarif --metrics off --disable-version-check +${BASE_DIR}/scripts/container-run.sh \ + --env HOME=/tmp \ + secdevai/semgrep:local \ + scan /src \ + --config /sgrules/ \ + --sarif \ + --metrics off \ + --disable-version-check ``` -**Semgrep**: Uses a locally built image (`local/semgrep`) that bundles two offline rule sets: +**Semgrep**: Uses a locally built image (`secdevai/semgrep:local`) that bundles two offline rule sets: - `/sgrules` — [semgrep/semgrep-rules](https://github.com/semgrep/semgrep-rules) (community rules) - `/sgrules-trail` — [trailofbits/semgrep-rules](https://github.com/trailofbits/semgrep-rules) (security-focused, AGPL-3.0) **Build Semgrep container**: ```sh -# Docker -docker buildx build . -t local/semgrep \ - -f ${BASE_DIR}/lola-module/skills/secdevai-tool/scripts/Dockerfile.semgrep - -# Podman -podman build . -t local/semgrep \ - -f ${BASE_DIR}/lola-module/skills/secdevai-tool/scripts/Dockerfile.semgrep +${BASE_DIR}/scripts/build-semgrep.sh ``` **Semgrep config resolution** @@ -244,7 +245,7 @@ language_detection: ```sh ${BASE_DIR}/scripts/container-run.sh \ --env HOME=/tmp \ - local/semgrep \ + secdevai/semgrep:local \ scan /src \ --config /sgrules/go \ --config /sgrules-trail/go \ diff --git a/lola-module/skills/secdevai-tool/scripts/build-semgrep.sh b/lola-module/skills/secdevai-tool/scripts/build-semgrep.sh new file mode 100755 index 0000000..69268aa --- /dev/null +++ b/lola-module/skills/secdevai-tool/scripts/build-semgrep.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -euo pipefail + +detect_runtime() { + if command -v podman &>/dev/null; then + echo "podman" + elif command -v docker &>/dev/null; then + echo "docker" + else + cat >&2 <<'MSG' +Error: No container runtime found. + +SecDevAI requires podman or docker to run security tools in isolated, +read-only containers. Please install one of the following: + + Podman (recommended): + macOS : brew install podman && podman machine init && podman machine start + Fedora : sudo dnf install podman + Ubuntu : sudo apt install podman + + Docker: + All OS : https://docs.docker.com/get-docker/ + +After installing, re-run this command. +MSG + exit 1 + fi +} + +runtime="$(detect_runtime)" +echo "Using runtime: ${runtime}" >&2 + +BASE_DIR="$(dirname "$0")" +IMAGE_TAG="secdevai/semgrep:local" + +exec "$runtime" build \ + -t "${IMAGE_TAG}" \ + -f "${BASE_DIR}/Dockerfile.semgrep" \ + ${BASE_DIR} From bcc8ac00055f34d0f31c74e897c7a6149331051c Mon Sep 17 00:00:00 2001 From: Michalis Papadopoullos <156905910+mpapadopoullos@users.noreply.github.com> Date: Mon, 11 May 2026 14:13:15 +0200 Subject: [PATCH 3/3] feat(secdevai-tool): refined SKILL.md --- lola-module/skills/secdevai-tool/SKILL.md | 33 +++++++++++------------ 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/lola-module/skills/secdevai-tool/SKILL.md b/lola-module/skills/secdevai-tool/SKILL.md index a85340e..fb0cd13 100644 --- a/lola-module/skills/secdevai-tool/SKILL.md +++ b/lola-module/skills/secdevai-tool/SKILL.md @@ -127,24 +127,11 @@ ${BASE_DIR}/scripts/container-run.sh gcr.io/openssf/scorecard:stable --local . - #### Tool: semgrep -**Usage:** -```sh -# semgrep — requires a locally built image (see build instructions below) -${BASE_DIR}/scripts/container-run.sh \ - --env HOME=/tmp \ - secdevai/semgrep:local \ - scan /src \ - --config /sgrules/ \ - --sarif \ - --metrics off \ - --disable-version-check -``` - **Semgrep**: Uses a locally built image (`secdevai/semgrep:local`) that bundles two offline rule sets: - `/sgrules` — [semgrep/semgrep-rules](https://github.com/semgrep/semgrep-rules) (community rules) - `/sgrules-trail` — [trailofbits/semgrep-rules](https://github.com/trailofbits/semgrep-rules) (security-focused, AGPL-3.0) -**Build Semgrep container**: +**Build Semgrep container**: (`secdevai/semgrep:local`) ```sh ${BASE_DIR}/scripts/build-semgrep.sh ``` @@ -189,8 +176,6 @@ semgrep_config_resolution: - /sgrules-trail ``` -Select `--config` based on the detected project language. - **Language detection:** ```yaml language_detection: @@ -241,7 +226,21 @@ language_detection: - "*.rs" ``` -**Example Resolution:** +Select `--config` based on the detected project language. + +**Usage:** +```sh +${BASE_DIR}/scripts/container-run.sh \ + --env HOME=/tmp \ + secdevai/semgrep:local \ + scan /src \ + --config /sgrules/ \ + --sarif \ + --metrics off \ + --disable-version-check +``` + +**Example resolution for Golang:** ```sh ${BASE_DIR}/scripts/container-run.sh \ --env HOME=/tmp \