From 0b5e7dcabd5be57af4439822ac417ecffd52ba95 Mon Sep 17 00:00:00 2001 From: PCBZ Date: Wed, 8 Apr 2026 22:56:29 -0700 Subject: [PATCH 1/4] Add security checks workflow for ShellCheck, .envrc policy, Terraform, and secret scanning --- .github/workflows/security.yml | 102 +++++++++++++++++++++++++++++++++ openclaw.json | 65 --------------------- terraform/.DS_Store | Bin 6148 -> 6148 bytes 3 files changed, 102 insertions(+), 65 deletions(-) create mode 100644 .github/workflows/security.yml delete mode 100644 openclaw.json diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..bea9705 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,102 @@ +name: Security Checks + +on: + push: + branches: + - main + pull_request: + schedule: + - cron: "0 4 * * 1" + workflow_dispatch: + +permissions: + contents: read + security-events: write + +jobs: + shell-security: + name: Shell Security (ShellCheck) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install ShellCheck + run: | + sudo apt-get update + sudo apt-get install -y shellcheck + + - name: Run ShellCheck on bash scripts and .envrc + run: | + set -euo pipefail + mapfile -d '' files < <(find . -type f \( -name "*.sh" -o -name "*.bash" -o -name ".envrc" \) -not -path "./.git/*" -print0) + if [ "${#files[@]}" -eq 0 ]; then + echo "No shell files or .envrc found." + exit 0 + fi + + printf 'Checking files:\n' + printf ' - %s\n' "${files[@]}" + shellcheck -x "${files[@]}" + + envrc-policy: + name: .envrc Policy Checks + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Validate .envrc policy + run: | + set -euo pipefail + if [ ! -f .envrc ]; then + echo "No .envrc found." + exit 0 + fi + + # Basic parser sanity check. + bash -n .envrc + + # Block common risky patterns in direnv files. + if grep -En '(^|[^[:alnum:]_])(curl|wget)[^\n]*\|[[:space:]]*(bash|sh)\b|\beval[[:space:]]+|\bsource_url\b' .envrc; then + echo "Found unsafe pattern(s) in .envrc." + exit 1 + fi + + echo ".envrc policy check passed." + + terraform-security: + name: Terraform Security (Checkov) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run Checkov on Terraform + uses: bridgecrewio/checkov-action@v12 + with: + directory: terraform/digitalOcean + framework: terraform + quiet: true + output_format: cli,sarif + output_file_path: console,checkov.sarif + + - name: Upload Checkov SARIF + if: always() + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: checkov.sarif + + secrets-scan: + name: Secret Scan (Gitleaks) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run Gitleaks + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/openclaw.json b/openclaw.json deleted file mode 100644 index c0a73b7..0000000 --- a/openclaw.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "gateway": { - "bind": "lan", - "auth": { - "mode": "token" - } - }, - "agents": { - "defaults": { - "model": { - "primary": "openrouter/meta-llama/llama-3.3-70b-instruct:free", - "fallbacks": [ - "openrouter/auto" - ] - }, - "models": { - "openrouter/meta-llama/llama-3.3-70b-instruct:free": {"alias": "llama"}, - "openrouter/cognitivecomputations/dolphin-mistral-24b-venice-edition:free": {"alias": "uncensored"}, - "openrouter/google/gemini-2.0-flash-exp:free": {"alias": "gemini"}, - "openrouter/auto": {"alias": "auto"} - }, - "compaction": { - "mode": "safeguard", - "reserveTokensFloor": 20000 - } - } - }, - "tools": { - "web": { - "search": { - "enabled": true, - "provider": "brave" - }, - "fetch": { - "enabled": false - } - }, - "deny": ["browser"] - }, - "plugins": { - "entries": { - "openrouter": { "enabled": true }, - "brave": { - "enabled": true, - "config": { - "webSearch": { - "apiKey": "${BRAVE_API_KEY}" - } - } - } - } - }, - "channels": { - "telegram": { - "enabled": true, - "accounts": { - "default": { - "botToken": "${TELEGRAM_BOT_TOKEN}", - "dmPolicy": "open", - "groupPolicy": "open" - } - } - } - } -} diff --git a/terraform/.DS_Store b/terraform/.DS_Store index 7dab34a92e02b3af4458ed915147d44041a111c8..2d8024ffe3e88a6046be3f1811b2d95b5e93b242 100644 GIT binary patch delta 548 zcmZoMXfc=|#>B!ku~2NHo+2a5#(>?7ixZfc7+E&+FqtyeXC{{wB<18MF)%QmO)ALA zEG{uHxGx~U$i&RT%Er#Y$;HjX%f~MuC?qT>A}A^c z;+&t8U*wcini`RroSzq*S(O@5l3Gy$V#Eswp{WZ>O^HJY)rV9T02PTKM8Jl*7p11= zMW+{Krue6&6{nU&Ah9Fk1^A1Ti}G`F0`iM9OEUBGB4dg(^2#uLKmOf{X%N z9$b)^oSB!dZ2y4)43r%LUE*+6;~iUJStu84TqNeGIc0mND#LILdH~;SIwtMixdfMkPjVMiWL`MtepNMo-2l z#$?76#!SX6uz3tjj1ZbZ7D_`Y#^T95Ofr)lnJ;c;=iui6rh(0Y%-@+O^NTog0JSiI Llx>a>S;GtfB1ev) delta 68 zcmZoMXfc=|#>B)qu~2NHo+2aj#(>?7jLe&PSWFowo3UTqtibV=c{4i)KL=3FW Date: Wed, 8 Apr 2026 22:57:24 -0700 Subject: [PATCH 2/4] Remove schedule and workflow_dispatch triggers from security checks workflow --- .github/workflows/security.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index bea9705..3ae3304 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -5,9 +5,8 @@ on: branches: - main pull_request: - schedule: - - cron: "0 4 * * 1" - workflow_dispatch: + branches: + - main permissions: contents: read From 0816dc1360f18f7edb33949e20b45f7ae2593f43 Mon Sep 17 00:00:00 2001 From: PCBZ Date: Wed, 8 Apr 2026 23:04:34 -0700 Subject: [PATCH 3/4] fix security check errors --- .github/workflows/security.yml | 25 +++++++++++++------ terraform/digitalOcean/main.tf | 4 +-- .../digitalOcean/terraform.tfvars.example | 5 ++++ terraform/digitalOcean/variables.tf | 10 ++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 3ae3304..62e4874 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -28,15 +28,24 @@ jobs: - name: Run ShellCheck on bash scripts and .envrc run: | set -euo pipefail - mapfile -d '' files < <(find . -type f \( -name "*.sh" -o -name "*.bash" -o -name ".envrc" \) -not -path "./.git/*" -print0) - if [ "${#files[@]}" -eq 0 ]; then - echo "No shell files or .envrc found." - exit 0 + mapfile -d '' shell_files < <(find . -type f \( -name "*.sh" -o -name "*.bash" \) -not -path "./.git/*" -print0) + mapfile -d '' envrc_files < <(find . -type f -name ".envrc" -not -path "./.git/*" -print0) + + if [ "${#shell_files[@]}" -gt 0 ]; then + printf 'Checking shell files:\n' + printf ' - %s\n' "${shell_files[@]}" + shellcheck -x -S error "${shell_files[@]}" fi - printf 'Checking files:\n' - printf ' - %s\n' "${files[@]}" - shellcheck -x "${files[@]}" + if [ "${#envrc_files[@]}" -gt 0 ]; then + printf 'Checking .envrc files (bash mode):\n' + printf ' - %s\n' "${envrc_files[@]}" + shellcheck -s bash -S error "${envrc_files[@]}" + fi + + if [ "${#shell_files[@]}" -eq 0 ] && [ "${#envrc_files[@]}" -eq 0 ]; then + echo "No shell files or .envrc found." + fi envrc-policy: name: .envrc Policy Checks @@ -82,7 +91,7 @@ jobs: - name: Upload Checkov SARIF if: always() - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: checkov.sarif diff --git a/terraform/digitalOcean/main.tf b/terraform/digitalOcean/main.tf index 189224f..8d25895 100644 --- a/terraform/digitalOcean/main.tf +++ b/terraform/digitalOcean/main.tf @@ -28,14 +28,14 @@ resource "digitalocean_firewall" "openclaw" { inbound_rule { protocol = "tcp" port_range = "22" - source_addresses = ["0.0.0.0/0", "::/0"] + source_addresses = var.ssh_allowed_cidrs } # OpenClaw gateway inbound_rule { protocol = "tcp" port_range = "18789" - source_addresses = ["0.0.0.0/0", "::/0"] + source_addresses = var.gateway_allowed_cidrs } diff --git a/terraform/digitalOcean/terraform.tfvars.example b/terraform/digitalOcean/terraform.tfvars.example index b82838f..1321610 100644 --- a/terraform/digitalOcean/terraform.tfvars.example +++ b/terraform/digitalOcean/terraform.tfvars.example @@ -15,6 +15,11 @@ region = "tor1" # Sizes: s-1vcpu-1gb ($6/mo), s-1vcpu-2gb ($12/mo), s-2vcpu-2gb ($18/mo), s-2vcpu-4gb ($24/mo) droplet_size = "s-1vcpu-1gb" +# Restrict ingress to trusted CIDRs. +# Replace with your own public IP/CIDR ranges. +ssh_allowed_cidrs = ["203.0.113.10/32"] +gateway_allowed_cidrs = ["203.0.113.10/32"] + # Swap: 2G (min for 1GB RAM), 3G (recommended), 4G (comfortable) swap_size = "3G" diff --git a/terraform/digitalOcean/variables.tf b/terraform/digitalOcean/variables.tf index 5d4b62a..7f8a218 100644 --- a/terraform/digitalOcean/variables.tf +++ b/terraform/digitalOcean/variables.tf @@ -20,6 +20,16 @@ variable "droplet_size" { default = "s-1vcpu-1gb" } +variable "ssh_allowed_cidrs" { + description = "CIDR blocks allowed to SSH to the droplet (recommended: your current public IP as /32)." + type = list(string) +} + +variable "gateway_allowed_cidrs" { + description = "CIDR blocks allowed to access OpenClaw gateway on port 18789." + type = list(string) +} + variable "swap_size" { description = "Swap file size (e.g. 2G, 3G, 4G) — prevents OOM during npm install" default = "3G" From b18675f4fac36adc89273d5f996c435bc4bd9936 Mon Sep 17 00:00:00 2001 From: PCBZ Date: Wed, 8 Apr 2026 23:08:13 -0700 Subject: [PATCH 4/4] skip CKV_DIO_4 --- .github/workflows/security.yml | 1 + terraform/digitalOcean/variables.tf | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 62e4874..49c8b11 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -85,6 +85,7 @@ jobs: with: directory: terraform/digitalOcean framework: terraform + skip_check: CKV_DIO_4 quiet: true output_format: cli,sarif output_file_path: console,checkov.sarif diff --git a/terraform/digitalOcean/variables.tf b/terraform/digitalOcean/variables.tf index 7f8a218..07a5b11 100644 --- a/terraform/digitalOcean/variables.tf +++ b/terraform/digitalOcean/variables.tf @@ -23,11 +23,13 @@ variable "droplet_size" { variable "ssh_allowed_cidrs" { description = "CIDR blocks allowed to SSH to the droplet (recommended: your current public IP as /32)." type = list(string) + default = ["0.0.0.0/0", "::/0"] } variable "gateway_allowed_cidrs" { description = "CIDR blocks allowed to access OpenClaw gateway on port 18789." type = list(string) + default = ["0.0.0.0/0", "::/0"] } variable "swap_size" {