name: Security Check on: push: branches: [main] pull_request: branches: [main] permissions: contents: read jobs: security: name: Security Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check for dangerous patterns run: | echo "## Security Pattern Scan" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY FOUND=0 # Check for unauthorized network libraries # Allowed: ureq (used for opt-in cloud sync, updates, error reports) # Allowed: std::net::TcpListener (used for local dashboard server) # Blocked: reqwest, hyper (heavy HTTP clients not needed) if grep -rn 'reqwest::' rust/src/ 2>/dev/null; then echo "::warning::Found reqwest usage — use ureq instead" echo "- ⚠️ Found reqwest usage (use ureq)" >> $GITHUB_STEP_SUMMARY FOUND=1 fi if grep -rn 'hyper::' rust/src/ 2>/dev/null; then echo "::warning::Found hyper usage — use ureq instead" echo "- ⚠️ Found hyper usage (use ureq)" >> $GITHUB_STEP_SUMMARY FOUND=1 fi # Check for unsafe code UNSAFE_COUNT=$(grep -rn 'unsafe {' rust/src/ 2>/dev/null | wc -l) if [ "$UNSAFE_COUNT" -gt 0 ]; then echo "::warning::Found $UNSAFE_COUNT unsafe blocks" echo "- ⚠️ Found $UNSAFE_COUNT unsafe blocks" >> $GITHUB_STEP_SUMMARY grep -rn 'unsafe {' rust/src/ >> $GITHUB_STEP_SUMMARY FOUND=1 fi # Check for environment manipulation if grep -rn '\.env("LD_PRELOAD")' rust/src/ 2>/dev/null; then echo "::error::Found LD_PRELOAD manipulation — potential library hijacking" echo "- ❌ Found LD_PRELOAD manipulation" >> $GITHUB_STEP_SUMMARY FOUND=1 fi if grep -rn '\.env("DYLD_' rust/src/ 2>/dev/null; then echo "::error::Found DYLD manipulation — potential library hijacking" echo "- ❌ Found DYLD manipulation" >> $GITHUB_STEP_SUMMARY FOUND=1 fi # Check for hardcoded secrets patterns if grep -rn 'sk_live_\|sk_test_\|AKIA[0-9A-Z]\|ghp_[a-zA-Z0-9]' rust/src/ 2>/dev/null; then echo "::error::Found potential hardcoded secrets" echo "- ❌ Found potential hardcoded secrets" >> $GITHUB_STEP_SUMMARY FOUND=1 fi # Check for shell injection vectors SHELL_INJECT=$(grep -rn 'Command::new("sh")\.arg("-c")\.arg(format!' rust/src/ 2>/dev/null | wc -l) if [ "$SHELL_INJECT" -gt 0 ]; then echo "::warning::Found $SHELL_INJECT potential shell injection vectors" echo "- ⚠️ Found $SHELL_INJECT shell injection patterns" >> $GITHUB_STEP_SUMMARY FOUND=1 fi # Check for unwrap() in production code (excluding tests) UNWRAP_COUNT=$(grep -rn '\.unwrap()' rust/src/ 2>/dev/null | grep -v '#\[test\]' | grep -v 'mod tests' | wc -l) echo "- ℹ️ Found $UNWRAP_COUNT .unwrap() calls in src/" >> $GITHUB_STEP_SUMMARY if [ "$FOUND" -eq 0 ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "✅ No dangerous patterns detected" >> $GITHUB_STEP_SUMMARY fi - name: Proprietary code guardrail run: | echo "## Proprietary Code Guard" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY LEAK=0 # Keep in sync with .github-ignore. Business/monetization dirs are # gitignored locally; listing them here is server-side defense-in-depth # in case the local pre-push hook is not installed. PRIVATE_PATHS="cloud/ docker-compose.yml .gitlab-ci.yml deploy.sh DEVELOPMENT.md Makefile.deploy docs/business/ memory-bank/ discord-bot/ n8n-workflows/ lab/ server.md" for path in $PRIVATE_PATHS; do if [ -e "$path" ]; then echo "::error::PROPRIETARY CODE DETECTED: $path exists in the GitHub repository!" echo "- **$path** — must not be on GitHub" >> $GITHUB_STEP_SUMMARY LEAK=1 fi done if [ "$LEAK" -eq 1 ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "These paths belong on GitLab only. See .github-ignore." >> $GITHUB_STEP_SUMMARY exit 1 fi echo "No proprietary code found." >> $GITHUB_STEP_SUMMARY - name: Commercial-plane guard run: | echo "## Commercial-plane Guard" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY LEAK=0 # Billing/licensing logic lives in the private lean-ctx-cloud repo # (oss-plane-separation-v1). core/billing/ is partially OPEN (metering, # plans, mod), so we name the specific commercial files rather than the # whole directory — the path guard above can't blanket-block them. COMMERCIAL_PATHS="rust/src/core/license rust/src/core/licensing/keygen.rs rust/src/cli/license_cmd.rs rust/src/core/billing/success_fee.rs rust/src/core/billing/stripe_invoice.rs docs/contracts/license-v1.md docs/contracts/success-fee-invoice-v1.md" for path in $COMMERCIAL_PATHS; do if [ -e "$path" ]; then echo "::error::COMMERCIAL CODE DETECTED: $path belongs in lean-ctx-cloud, not the open engine!" echo "- **$path** — implement in lean-ctx-cloud" >> $GITHUB_STEP_SUMMARY LEAK=1 fi done if [ "$LEAK" -eq 1 ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "The open engine bills nothing and issues no licenses; it only emits the signed savings ledger. See .github-ignore." >> $GITHUB_STEP_SUMMARY exit 1 fi echo "No commercial-plane code found." >> $GITHUB_STEP_SUMMARY - name: Critical files check if: github.event_name == 'pull_request' run: | echo "## Critical Files Modified" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY CRITICAL_FILES="rust/src/shell.rs rust/src/server.rs rust/src/hooks.rs rust/src/core/cache.rs rust/Cargo.toml .github/workflows" FOUND_CRITICAL=0 for file in $CRITICAL_FILES; do if git diff --name-only origin/main...HEAD | grep -q "$file"; then echo "- ⚠️ **$file** modified (requires security review)" >> $GITHUB_STEP_SUMMARY FOUND_CRITICAL=1 fi done if [ "$FOUND_CRITICAL" -eq 0 ]; then echo "✅ No critical files modified" >> $GITHUB_STEP_SUMMARY fi - name: Dependency audit shell: bash run: | set -o pipefail cargo install cargo-audit cd rust && cargo audit 2>&1 | tee audit-output.txt AUDIT_EXIT=${PIPESTATUS[0]} echo "" >> $GITHUB_STEP_SUMMARY echo "## Dependency Audit" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY cat audit-output.txt >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY exit $AUDIT_EXIT