Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/RULESET_BASELINE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# cliproxyapi-plusplus Ruleset Baseline

This repository now has a checked-in baseline that matches the repaired remote `Main` ruleset.

## Enforced Branch Protection Baseline

- require pull requests before merge on the default branch
- no branch deletion
- no force push / non-fast-forward updates
- require at least 1 approval
- dismiss stale approvals on new push
- require resolved review threads before merge
- allow merge methods: `merge`, `squash`
- enable GitHub `code_quality`
- enable GitHub `copilot_code_review`

## Repo-Local Governance Gates

The repo-local workflow set remains the main CI and policy contract:

- `policy-gate`
- `pr-path-guard`
- `pr-test-build`
- `required-check-names-guard`
- `quality-gate`
- `security-guard`
- `codeql`
- `sast-quick`
- `sast-full`

Current required check manifests:

- `.github/required-checks.txt`
- `.github/release-required-checks.txt`

Those manifests should drive the next remote ruleset wave once the stable job names are re-verified
against live workflow output.
Comment on lines +39 to +46
Copy link
Copy Markdown

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:

#!/bin/bash
# Description: Verify manifest files exist and check their contents

echo "=== Checking for manifest files ==="
for manifest in ".github/required-checks.txt" ".github/release-required-checks.txt"; do
  if [[ -f "$manifest" ]]; then
    echo -e "\n✓ Found: $manifest"
    echo "Contents:"
    cat "$manifest"
  else
    echo -e "\n✗ Missing: $manifest"
  fi
done

echo -e "\n=== Cross-checking documented workflows against manifests ==="
documented_workflows=("policy-gate" "pr-path-guard" "pr-test-build" "required-check-names-guard" "quality-gate" "security-guard" "codeql" "sast-quick" "sast-full")

for workflow in "${documented_workflows[@]}"; do
  if grep -q "$workflow" .github/required-checks.txt 2>/dev/null || grep -q "$workflow" .github/release-required-checks.txt 2>/dev/null; then
    echo "$workflow found in manifests"
  else
    echo "$workflow not found in manifests"
  fi
done

Repository: KooshaPari/cliproxyapi-plusplus

Length of output: 1151


Manifest files exist but are incomplete—most documented workflows are missing.

Both .github/required-checks.txt and .github/release-required-checks.txt exist, but the manifest contents significantly diverge from the documented workflow names (lines 21-29). The manifests currently list only pr-test-build and pr-path-guard, while 7 documented workflows are absent: policy-gate, required-check-names-guard, quality-gate, security-guard, codeql, sast-quick, and sast-full. These manifests must be updated to align with the documented workflows before they can reliably drive the next ruleset wave.

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

In @.github/RULESET_BASELINE.md around lines 31 - 37, The manifests
`.github/required-checks.txt` and `.github/release-required-checks.txt` only
list `pr-test-build` and `pr-path-guard` but are missing the documented workflow
names; update both manifest files to include the full set of documented checks
(`policy-gate`, `required-check-names-guard`, `quality-gate`, `security-guard`,
`codeql`, `sast-quick`, `sast-full`, plus the existing `pr-test-build` and
`pr-path-guard`) so the manifests match the workflows listed in lines 21-29 and
can reliably drive the next ruleset wave. Ensure the names exactly match the
workflow job names used in the repository (case-sensitive) and save both
`.github/required-checks.txt` and `.github/release-required-checks.txt`.


## Exception Policy

- only documented billing or quota failures may be excluded from blocking CI evaluation
- review threads and blocking comments must be resolved before merge
- PRs must not rely on local `--no-verify` bypasses instead of server-side checks
Comment thread
coderabbitai[bot] marked this conversation as resolved.
41 changes: 41 additions & 0 deletions .github/rulesets/main.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "Main",
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"include": ["~DEFAULT_BRANCH"],
"exclude": []
}
},
"bypass_actors": [],
"rules": [
{ "type": "deletion" },
{ "type": "non_fast_forward" },
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 1,
"dismiss_stale_reviews_on_push": true,
"required_reviewers": [],
"require_code_owner_review": false,
"require_last_push_approval": false,
"required_review_thread_resolution": true,
"allowed_merge_methods": ["merge", "squash"]
}
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{
"type": "code_quality",
"parameters": {
"severity": "errors"
}
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
{
"type": "copilot_code_review",
"parameters": {
"review_on_push": true,
"review_draft_pull_requests": true
}
}
]
}
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ jobs:
- name: Refresh models catalog
run: |
git fetch --depth 1 https://github.com/router-for-me/models.git main
git show FETCH_HEAD:models.json > internal/registry/models/models.json
mkdir -p pkg/llmproxy/registry/models
git show FETCH_HEAD:models.json > pkg/llmproxy/registry/models/models.json
Comment on lines 14 to +16
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This workflow now writes models.json to pkg/llmproxy/registry/models/models.json, but other CI workflows still reference internal/registry/models/models.json (a path that doesn’t exist in this repo). Consider aligning all workflows on the embedded path so required checks/build pipelines don’t diverge or fail due to missing directories.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +16
Copy link
Copy Markdown

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:

#!/bin/bash
# Verify all workflow files using the models.json path

echo "=== Checking all workflows for models.json path references ==="
rg -n "models\.json" .github/workflows/

echo ""
echo "=== Checking go:embed directives for expected path ==="
rg -n "go:embed.*models" --type=go

Repository: KooshaPari/cliproxyapi-plusplus

Length of output: 851


Critical: Three other workflows still use the old models path and will fail.

This CI workflow correctly writes to pkg/llmproxy/registry/models/models.json to match the go:embed directive in pkg/llmproxy/registry/model_updater.go (line 27). However, three other workflow files still use the old path internal/registry/models/models.json:

  • .github/workflows/release.yaml (line 19)
  • .github/workflows/pr-test-build.yml (line 20)
  • .github/workflows/docker-image.yml (lines 19, 54)

These inconsistencies will cause build failures in release, PR test, and Docker image workflows because the embedded file won't exist at the expected path.

Required fixes for other workflows

Apply the same path update to all three files:

mkdir -p pkg/llmproxy/registry/models
-git show FETCH_HEAD:models.json > internal/registry/models/models.json
+git show FETCH_HEAD:models.json > pkg/llmproxy/registry/models/models.json
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 15 - 16, Update every CI workflow that
still writes or reads the old embedded models JSON path so it uses the new path
pkg/llmproxy/registry/models/models.json; specifically change any occurrences of
internal/registry/models/models.json in the workflows (release.yaml,
pr-test-build.yml, docker-image.yml) to pkg/llmproxy/registry/models/models.json
and ensure the step that extracts the file uses git show FETCH_HEAD:models.json
> pkg/llmproxy/registry/models/models.json to match the go:embed directive in
pkg/llmproxy/registry/model_updater.go.

Comment on lines +15 to +16
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This workflow now writes the models catalog to pkg/llmproxy/registry/models/models.json, but other workflows (e.g. docker-image, pr-test-build, release) still write to internal/registry/models/models.json. Since the Go code embeds pkg/llmproxy/registry/models/models.json, consider updating the other workflows as well (or writing to both locations) to avoid builds/releases using a stale or missing embedded catalog.

Suggested change
mkdir -p pkg/llmproxy/registry/models
git show FETCH_HEAD:models.json > pkg/llmproxy/registry/models/models.json
mkdir -p pkg/llmproxy/registry/models internal/registry/models
git show FETCH_HEAD:models.json | tee pkg/llmproxy/registry/models/models.json > internal/registry/models/models.json

Copilot uses AI. Check for mistakes.
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
Expand Down
89 changes: 89 additions & 0 deletions .github/workflows/sast-full.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: SAST Full Analysis

on:
schedule:
- cron: "0 2 * * *"
workflow_dispatch:

permissions:
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

github/codeql-action/* typically requires actions: read permission (the existing codeql.yml includes it). sast-full.yml sets only contents: read and security-events: write, which may cause the CodeQL steps to fail with insufficient permissions in some repo/org settings.

Suggested change
permissions:
permissions:
actions: read

Copilot uses AI. Check for mistakes.
contents: read
security-events: write

jobs:
codeql:
name: CodeQL Analysis
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
language: [go, javascript]
steps:
- uses: actions/checkout@v4
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: CodeQL matrix missing Go language.

The matrix lists [python, cpp, javascript] but this is primarily a Go codebase (per cargo clippy in sast-quick.yml, the AGENTS.md build instructions, and the codebase structure). Without go in the matrix, CodeQL will not analyze the core Go code, making the full SAST scan incomplete for this repository.

Suggested change
- uses: actions/checkout@v4
language: [go, python, javascript]

Note: also removed cpp since this doesn't appear to be a C++ project. Adjust if there is C++ code present.


- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4

Comment on lines +23 to +30
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This workflow uses CodeQL action v3 (github/codeql-action/*@v3), but the existing .github/workflows/codeql.yml uses v4 (see .github/workflows/codeql.yml:24-36). Aligning on a single major version reduces maintenance overhead and avoids behavioral differences across workflows.

Copilot uses AI. Check for mistakes.
trivy-repo:
name: Trivy Repository Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Using @master branch reference for trivy-action.

Pinning to a mutable branch (@master) introduces supply-chain risk and non-reproducible builds. If the upstream action is compromised or introduces breaking changes, your CI will silently adopt them.

Recommend pinning to a specific version tag or commit SHA:

      - uses: aquasecurity/trivy-action@v0.28.0

- uses: aquasecurity/trivy-action@v0.35.0
with:
scan-type: fs
scan-ref: .
format: sarif
output: trivy-results.sarif
- name: Upload Trivy SARIF
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: trivy-results.sarif
category: trivy
Comment thread
coderabbitai[bot] marked this conversation as resolved.

full-semgrep:
name: Full Semgrep Analysis
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Semgrep
run: python -m pip install --disable-pip-version-check semgrep==1.157.0
- name: Run Semgrep
run: |
semgrep scan \
--config p/security-audit \
--config p/owasp-top-ten \
--config p/cwe-top-25 \
--error \
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Same as in sast-quick: running Semgrep with --error will fail the scheduled full scan on any finding, including low-signal rules. If this workflow is intended to be informational (nightly signal) rather than gating, consider removing --error or filtering by severity / excluding the in-repo custom rules until noise is reduced.

Suggested change
--error \

Copilot uses AI. Check for mistakes.
--sarif \
--output semgrep.sarif \
.

- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: semgrep.sarif
category: semgrep-full

full-secrets:
name: Full Secret Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: trufflesecurity/trufflehog@v3.94.2
with:
path: ./
extra_args: --only-verified
91 changes: 91 additions & 0 deletions .github/workflows/sast-quick.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: SAST Quick Check

on:
pull_request:
push:
branches: [main]

permissions:
contents: read
security-events: write

jobs:
semgrep:
name: Semgrep Scan
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Semgrep
run: python -m pip install --disable-pip-version-check semgrep==1.157.0
- name: Run Semgrep
run: |
semgrep scan \
--config p/security-audit \
--config p/owasp-top-ten \
--config p/cwe-top-25 \
--error \
--sarif \
--output semgrep.sarif \
.

- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: semgrep.sarif
category: semgrep

secrets:
name: Secret Scanning
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: trufflesecurity/trufflehog@v3.94.2
with:
path: ./
extra_args: --only-verified

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Using @main branch reference for trufflehog.

Pinning to @main introduces supply-chain risk and non-reproducible builds. Pin to a specific release tag or commit SHA for security:

      - uses: trufflesecurity/trufflehog@v3.82.12

go-quality:
name: Go Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Enforce gofmt
run: |
files=$(git ls-files '*.go')
if [ -z "$files" ]; then
exit 0
fi
unformatted=$(gofmt -l $files)
if [ -n "$unformatted" ]; then
echo "$unformatted"
exit 1
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Run go vet
run: go vet ./...
Comment thread
coderabbitai[bot] marked this conversation as resolved.

license-check:
name: License Compliance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Capture dependency inventory
run: |
go list -m -f '{{if not .Main}}{{.Path}} {{.Version}}{{end}}' all | sort > license-inventory.txt
test -s license-inventory.txt
19 changes: 14 additions & 5 deletions .github/workflows/security-guard.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
name: security-guard
on: [workflow_dispatch]
name: Security Guard

on:
workflow_call:
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

security-guard.yml is now callable as a reusable workflow (workflow_call), but it relies on secrets.GITGUARDIAN_API_KEY. Reusable workflows only receive secrets that are explicitly declared under on.workflow_call.secrets and passed by the caller; otherwise this will be empty and the scan will fail unexpectedly.

Suggested change
workflow_call:
workflow_call:
secrets:
GITGUARDIAN_API_KEY:
required: true

Copilot uses AI. Check for mistakes.
workflow_dispatch:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This workflow is listed as a required check (security-guard.yml|ggshield-scan), but it only triggers via workflow_dispatch/workflow_call and is not invoked by any other workflow. As a result, PRs/branch updates won't automatically produce the required status check, potentially blocking merges unless run manually. Consider adding pull_request/push triggers (or wiring a caller workflow) or removing it from the required-check manifest if it should remain manual-only.

Suggested change
workflow_dispatch:
workflow_dispatch:
push:
pull_request:

Copilot uses AI. Check for mistakes.

jobs:
audit:
ggshield-scan:
runs-on: ubuntu-latest
steps:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- uses: actions/checkout@v4
- name: Run security audit
run: echo "Security audit placeholder - no script available yet"
- uses: actions/setup-python@v5
- name: Install ggshield
run: pip install ggshield
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

pip install ggshield is unpinned and actions/setup-python doesn’t specify a python-version, which makes this check non-reproducible (and can break on future releases). Pin the ggshield version and set an explicit Python version, consistent with the Semgrep workflows.

Suggested change
- name: Install ggshield
run: pip install ggshield
with:
python-version: '3.11'
- name: Install ggshield
run: pip install ggshield==1.25.3

Copilot uses AI. Check for mistakes.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Unpinned pip install ggshield — supply-chain risk

No version is specified, so every CI run pulls the latest release. A compromised upstream release would immediately affect all pipelines. Pin to a specific version (e.g., pip install ggshield==25.1.0).

- name: Run ggshield secret scan
env:
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
run: ggshield secret scan path . --recursive
28 changes: 28 additions & 0 deletions .semgrep-rules/architecture-violations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
rules:
- id: no-dot-imports
pattern: import . "$PKG"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Literal $PKG won't match real Go imports

The pattern import . "$PKG" treats $PKG as a literal string, not a Semgrep metavariable. This rule will only match code that imports a package literally named $PKG. Use pattern-regex or a metavariable to match arbitrary package paths.

message: Dot imports hide call sites and make ownership harder to trace. Use explicit package names.
languages: [go]
severity: MEDIUM

- id: no-blank-imports-outside-entrypoints
patterns:
- pattern: import _ "$PKG"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Same literal $PKG issue — won't match real blank imports

Same as no-dot-imports: import _ "$PKG" matches only the literal string $PKG.

message: Blank imports belong in explicit wiring points only. Move them out of library packages.
languages: [go]
severity: MEDIUM
paths:
exclude:
- "cmd/**"
- "**/*_test.go"

- id: getenv-in-http-handler
patterns:
- pattern-inside: |
func $HANDLER($W http.ResponseWriter, $R *http.Request) {
...
}
- pattern: os.Getenv(...)
message: Avoid reading process environment directly inside request handlers. Inject configuration instead.
languages: [go]
severity: LOW
40 changes: 40 additions & 0 deletions .semgrep-rules/secrets-detection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
rules:
- id: hardcoded-aws-key
pattern-regex: AKIA[0-9A-Z]{16}
message: Potential AWS Access Key detected. Use environment variables instead.
languages: [generic]
severity: CRITICAL

- id: hardcoded-api-key
pattern-regex: (?i)(api[_-]?key|token|secret)\s*(?:[:=])\s*["'][^"'\\n]{8,}["']
message: Hardcoded API key detected. Use environment variables or secrets management.
languages: [generic]
severity: HIGH
Comment on lines +8 to +12
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The character class uses \\n which (after YAML parsing) typically excludes a literal backslash and the letter n, not an actual newline. If the goal is to avoid matching across lines, use \n (newline escape) in the regex (and consider \r as well). As written, this can increase false positives by allowing matches that span newlines.

Copilot uses AI. Check for mistakes.
paths:
exclude:
- "**/*_test.go"
- "examples/**"
- "test/**"

Comment on lines +2 to +18
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

These secret-detection rules appear to use regex syntax inside pattern, but Semgrep won’t treat pattern as a regex (so strings like AKIA[0-9A-Z]{16} and "..." will match literally and likely never trigger). Consider switching to pattern-regex (or using metavariables) so the rules actually detect real secrets.

Copilot uses AI. Check for mistakes.
- id: hardcoded-password
pattern-regex: (?i)(password|passwd|pwd)\s*(?:[:=])\s*["'][^"'\\n]{8,}["']
message: Hardcoded password detected. Use environment variables or secrets management.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
languages: [generic]
severity: CRITICAL
Comment on lines +19 to +23
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Same newline-escape issue as the API key rule: \\n inside the negated character class is unlikely to exclude actual newline characters. Using \n (and possibly \r) would better prevent cross-line matches and reduce false positives.

Copilot uses AI. Check for mistakes.
paths:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Missing third_party/** exclusion for secret detection

The hardcoded-password rule excludes **/*_test.go, examples/**, and test/**, but not third_party/**. Vendored or third-party code may contain password-like strings in config examples or documentation, causing false positives.

exclude:
- "**/*_test.go"
- "examples/**"
- "test/**"

- id: hardcoded-slack-webhook
pattern-regex: https://hooks\.slack\.com/services/[A-Za-z0-9/_-]+
message: Slack webhook URL detected. This should be in environment variables.
languages: [generic]
severity: HIGH

- id: hardcoded-github-token
pattern-regex: gh[pousr]_[A-Za-z0-9_]{36,255}
message: GitHub token detected. Never commit tokens to code.
languages: [generic]
severity: CRITICAL
26 changes: 26 additions & 0 deletions .semgrep-rules/unsafe-patterns.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
rules:
- id: shell-command-with-shell
patterns:
- pattern-either:
- pattern: exec.Command("sh", "-c", ...)
- pattern: exec.Command("bash", "-c", ...)
message: Avoid shell evaluation in exec.Command. Pass explicit argv slices instead.
languages: [go]
severity: CRITICAL

- id: sql-query-built-with-sprintf
patterns:
- pattern: fmt.Sprintf($QUERY, ...)
- metavariable-regex:
metavariable: $QUERY
regex: (?i).*(select|insert|update|delete|from|where).*
message: SQL assembled with fmt.Sprintf is injection-prone. Use parameter binding instead.
languages: [go]
severity: CRITICAL

- id: direct-http-get-without-timeout
patterns:
- pattern: http.Get(...)
message: http.Get uses the default client without an explicit timeout. Prefer a configured http.Client.
languages: [go]
severity: LOW
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep custom rules target Rust, not Go

Medium Severity

All custom semgrep rules in unsafe-patterns.yml and architecture-violations.yml specify languages: [rust] with Rust-specific patterns (unwrap(), format!(), use crate::, etc.). This is a Go repository with no Rust code, so none of these rules will ever match anything. The entire custom rule suite is inert.

Additional Locations (1)
Fix in Cursor Fix in Web

Comment on lines +1 to +26
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Custom rules not loaded by SAST workflows.

These Go-focused rules are well-designed, but neither sast-quick.yml nor sast-full.yml includes --config .semgrep-rules/ in the Semgrep scan command. The workflows only use the upstream packs (p/security-audit, p/owasp-top-ten, p/cwe-top-25).

To activate these custom rules, add the config flag to both workflow files:

  semgrep scan \
    --config p/security-audit \
    --config p/owasp-top-ten \
    --config p/cwe-top-25 \
+   --config .semgrep-rules/ \
    --error \

Alternatively, if the intent is to gate CI only on upstream packs initially (as mentioned in 04_IMPLEMENTATION_STRATEGY.md), consider documenting this explicitly so future maintainers know these rules exist but are intentionally not enforced yet.

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

In @.semgrep-rules/unsafe-patterns.yml around lines 1 - 26, The Semgrep custom
rules defined in .semgrep-rules/unsafe-patterns.yml are not being loaded because
the Semgrep scan steps in the CI workflows do not pass the --config
.semgrep-rules/ flag; update the Semgrep invocation in both sast-quick.yml and
sast-full.yml to include --config .semgrep-rules/ so these rules (ids
shell-command-with-shell, sql-query-built-with-sprintf,
direct-http-get-without-timeout) are applied, or alternatively add a short note
in 04_IMPLEMENTATION_STRATEGY.md indicating the intentional omission if you want
to keep CI gated only on upstream packs.

Loading
Loading