Skip to content

About

Agentic, scanner-grounded code review for the whole PR: app code, infrastructure (Kubernetes, Docker, Terraform, GitHub Actions) and AI/LLM/agent code (OWASP LLM Top 10, MCP, agent skills).

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

agentic-code-review-tool

ci code-review M8ven Score

Agentic, scanner-grounded code review for the whole pull request — application code, infrastructure, and the AI/LLM/agent code most review tools don't understand yet.

acr reviews only the lines a PR changes, runs high-precision built-in rules plus the open-source scanners you already trust, merges duplicates, and (optionally) hands every finding to an LLM agent that reads the surrounding code to confirm it, dismiss false positives and write the fix. The output is one PR comment, inline annotations, SARIF for GitHub code scanning, and an exit code that can gate the merge.

See a live AI review → A real pull request with deliberately insecure AI, Kubernetes and Docker code, reviewed by this tool's GitHub Action with Claude. The reviewer confirmed 11 of 12 findings, dismissed the one planted false positive, and wrote a fix for each. The PR stays open as a showcase and will not be merged.

$ acr review --base origin/main
## Agentic code review · ❌ Changes requested
🔴 1 critical · 🟠 3 high · 🟡 2 medium · 🔵 1 low
| 🔴 | critical | `agent.py:12`            | LLM output used as code, shell, SQL or HTML (LLM05)  | ACR-AI-002   |
| 🟠 | high     | `.github/workflows/x.yml:9` | Untrusted event data interpolated into a shell script | ACR-GHA-002 |
| 🟠 | high     | `k8s/trainer.yaml:14`     | Dangerous Linux capability added                      | ACR-K8S-004  |

Why another code reviewer?

  • The CI/CD attack surface as it is attacked. Secrets posted off GitHub from a workflow step (the GhostAction shape), the checkout token shipped inside a workflow artifact (ArtiPACKED), event data written into GITHUB_ENV, dependencies pulled from a moving git ref, actions and COPY --from images that are not pinned.
  • Lock files, not only manifests. Pinned versions in uv.lock, Poetry, Pipfile and npm locks and pip files are checked: a CA bundle that still trusts compromised roots, packages over plain HTTP or with TLS checks off, an extra index open to dependency confusion, git dependencies with no integrity hash or pinned to a branch.
  • Go as thoroughly as Python. SQL built with fmt.Sprintf, sh -c handed a built command, InsecureSkipVerify, redirects and file paths taken from the request, servers with no header timeout, world-writable files.
  • The bugs that ship in ML code. Model and dataset archives extracted without a path filter, temp files picked by name, HTTP calls that can wait forever, math/rand behind a token, a private key compared with big.Int.
  • The whole PR, not one language. Real PRs change Python and the Dockerfile, the Compose file, the Helm chart and a workflow. One review covers all of it.
  • AI/agent code is a first-class target. Rules mapped to the OWASP Top 10 for LLM Applications: prompt injection, LLM output reaching exec/SQL/HTML, trust_remote_code, unbounded token spend, provider keys in the browser — plus the new AI supply chain: unpinned or auto-approved MCP servers, tokens in MCP configs, agent skills that pipe scripts into a shell, read credentials or hide instructions, agent instruction files (AGENTS.md, CLAUDE.md, .cursorrules) carrying hidden instructions, agent plugins whose marketplace entry is not pinned to a commit or whose hooks fetch and run code, and coding agents (Claude Code, Codex, Gemini CLI) launched with their permission checks off.
  • Grounded, not guessed. Deterministic rules and real scanners decide what and where; the agent only verifies and explains. Every finding has an exact file and line.
  • Adoptable on legacy code. Only changed lines are reviewed, so turning it on doesn't drown every PR in old debt.
  • Works without any LLM. The deterministic layer is useful on its own; the agent is opt-in.

How it works

flowchart LR
    PR[Pull request diff] --> D[Changed files and lines]
    D --> C{Classify}
    C -->|app code| R1[App rules]
    C -->|AI / agent code| R2[OWASP LLM + MCP + skill rules]
    C -->|K8s, Docker, Terraform, Actions| R3[Infra rules]
    D --> S[Optional scanners<br/>gitleaks · semgrep · trivy · checkov<br/>hadolint · actionlint · kube-linter]
    R1 & R2 & R3 & S --> M[Keep changed lines only<br/>merge cross-tool duplicates]
    M --> A[Optional AI agent<br/>confirm · dismiss · explain · fix]
    A --> O[PR comment · inline annotations · SARIF · exit code]
Loading

Quick start

pip install git+https://github.com/sunilmehta-si/agentic-code-review-tool
cd your-repo

acr init                           # write a starter .acr.yml
acr review                         # working tree vs HEAD
acr review --staged                # only what you are about to commit
acr review --base origin/main      # what a PR would change (merge-base)
acr review --all                   # audit every tracked file
acr review --format sarif -o acr.sarif   # for GitHub code scanning
acr review --format github         # annotations in a GitHub Actions log
acr review --format gitlab -o gl-code-quality-report.json   # GitLab merge request Code Quality
acr review --format junit -o acr.xml    # Jenkins, Azure DevOps, CircleCI, Bitbucket test reports
git diff origin/main... | acr review --diff-file -   # review any unified diff
acr rules                          # list built-in and custom rules (--format markdown|json)
acr classify Dockerfile k8s/app.yaml   # which file kinds and rules apply to a file
Option Default Meaning
--fail-on {critical,high,medium,low,never} high Exit 1 if a finding at or above this severity remains
--no-scanners off Built-in rules only
--scanners semgrep,trivy all installed Run a subset of external scanners
--exclude 'docs/*' — Skip paths (repeatable)
--include 'services/api/*' everything Only review matching paths (repeatable); include: in .acr.yml
--sarif, --json, --markdown PATH — Write extra report formats from the same run (no re-scan)
--baseline FILE .acr-baseline.json if present Suppress findings accepted with acr baseline
--min-severity medium show everything Leave out findings below this level; min_severity: in .acr.yml
--timings off Print how long the rules and each scanner took

Suppress a deliberate, reviewed line with an inline comment. acr:ignore silences every rule on that line; acr:ignore[ACR-APP-004, semgrep:*] silences only the listed rules (ids or globs), so anything else on the line is still reported. Markers work for built-in rules and external scanner findings alike. Add until=2026-12-31 to make a suppression lapse on that date; after it, the finding is reported again with a note that its exemption expired.

Configure once per repository

# .acr.yml  (command-line flags win over this file)
fail_on: high
exclude: ["docs/*", "*.generated.go"]
disable: ["ACR-AI-007"]          # rule ids or globs, e.g. "hadolint:*"
severity:
  ACR-K8S-009: medium            # per-rule severity overrides
  "hadolint:*": low              # globs work too; an exact id wins
scanners: [semgrep, trivy]
ai: claude                       # none | claude | openai

Unknown or invalid settings stop the run with a clear error instead of being silently ignored.

Custom rules

Encode your own conventions as line patterns. They run on changed lines like built-in rules and honour acr:ignore, disable, severity overrides and the baseline:

custom_rules:
  - id: ORG-001                    # your prefix; ACR- is reserved
    title: Internal service called over plain HTTP
    pattern: 'http://[a-z0-9-]+\.internal\b'
    severity: high                 # critical | high | medium | low | info (default medium)
    files: ["*.py", "services/*"]  # optional globs (default: every file)
    category: app-security         # optional, shapes the "By area" summary
    fix: Call the https:// endpoint through the service mesh.

acr rules lists them next to the built-in rules and acr explain ORG-001 shows the pattern and fix. A broken pattern or an unknown key stops the review with a message naming the rule.

Adopting on an existing codebase: run acr baseline once and commit .acr-baseline.json. Known findings are suppressed, matched by rule and line content so they survive code moving around, and only new problems fail pull requests. acr baseline --check fails when baselined findings have since been fixed, and acr baseline --prune removes those entries without accepting anything new, so the baseline only ever shrinks.

Demo

examples/insecure-app is a small project with deliberate mistakes in every area. Running

acr review --root examples/insecure-app --all --no-scanners --fail-on never

reports 88 findings across 17 files (8 critical, 40 high, 35 medium, 5 low). One finding from each rule family:

Severity Location Issue Rule
🔴 critical .github/workflows/triage.yml:12 Privileged workflow checks out untrusted PR code ACR-GHA-001
🔴 critical .mcp.json:6 Credential stored in plain text in an MCP config ACR-MCP-002
🔴 critical agent.py:24 LLM output used as code, shell, SQL or HTML (LLM05 Improper Output Handling) ACR-AI-002
🔴 critical infra/main.tf:7 Sensitive port open to the whole internet ACR-TF-001
🔴 critical k8s/trainer.yaml:18 Privileged container or privilege escalation allowed ACR-K8S-001
🔴 critical skills/deploy-helper/SKILL.md:8 Agent skill or rules file reads credentials or sends data out ACR-SKILL-002
🟠 high .claude/settings.json:3 Coding agent run with its permission checks or sandbox turned off (LLM06 Excessive Agency) ACR-AI-010
🟠 high Dockerfile:2 Secret baked into the image via ENV or ARG ACR-DOCKER-005
🟠 high agent.py:24 Dynamic code execution ACR-APP-003
🟠 high app.py:6 Hardcoded password or token ACR-SEC-002

The full run is checked in CI by tests/test_examples.py, so a rule that stops firing fails the build.

In a container

docker build -t acr .
docker run --rm -v "$PWD:/src" acr review --base origin/main

The image runs as a non-root user and pins its base image by digest.

As a pre-commit hook

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/sunilmehta-si/agentic-code-review-tool
    rev: v0.5.0
    hooks:
      - id: acr

The hook runs the built-in rules only (fast, offline) with --staged, so it reviews exactly what is being committed and ignores unstaged edits. CI can run the full review with scanners and the AI agent.

Use it in GitHub Actions

# .github/workflows/code-review.yml
name: code-review
on: pull_request
permissions:
  contents: read
  pull-requests: write     # inline review comments
  security-events: write   # SARIF upload to code scanning
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: sunilmehta-si/agentic-code-review-tool@v0.5.0 # or pin the release commit SHA
        with:
          fail-on: high
          ai: claude                                        # or: none, openai
          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
      - uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
        if: always()
        with:
          sarif_file: acr.sarif

The action writes the summary to the job page, posts inline comments on the PR, shows findings as annotations on the changed files, uploads SARIF to the Security tab, and fails the check only after all of that is published. Annotations need no write permission, so pull requests from forks still get line-level feedback (annotations: "false" turns them off). Re-runs on new pushes don't repeat inline comments that were already posted, and transient GitHub API errors are retried.

Input Default Meaning
fail-on high Severity that fails the check (never to report only)
ai, model none claude or openai to verify findings with an agent
scanners all installed Comma-separated subset, or none for built-in rules only
post-review, annotations true PR review comment with inline comments; diff annotations
sarif-file acr.sarif SARIF path for code scanning (empty to skip)

Outputs: findings, blocking (counts) and report-file (the JSON report, which includes the gate decision). Use fetch-depth: 0 so the PR diff is exact; on a shallow clone acr falls back to a direct diff and says so.

AI review

Live example: the demo pull request. Every inline comment there was written by the Claude reviewer.

With --ai, an LLM agent verifies every deterministic finding before you see it. It reads the surrounding code with three read-only, repository-confined tools (read_file, search_repo, list_changed_files), then marks each finding confirmed, false positive or uncertain, explains it in plain language and writes a concrete fix. It may add up to five issues of its own, but only on lines the PR changes.

pip install "agentic-code-review-tool[claude] @ git+https://github.com/sunilmehta-si/agentic-code-review-tool"
export ANTHROPIC_API_KEY=...            # or: ant auth login
acr review --base origin/main --ai claude

# Any OpenAI-compatible endpoint: OpenAI, vLLM, Ollama, LM Studio, LiteLLM
export ACR_OPENAI_BASE_URL=http://localhost:11434/v1 ACR_MODEL=qwen2.5-coder:32b
acr review --base origin/main --ai openai
Setting Default Notes
--ai claude model claude-opus-5-5, effort high Official Anthropic SDK; cached system prompt; structured JSON verdicts; server-side fallback on safety refusals (ACR_CLAUDE_FALLBACKS=0 to disable)
--ai openai ACR_MODEL required Standard-library HTTP only, so it works air-gapped with a local model
--model, ACR_MODEL, ACR_EFFORT — Override model and effort
--max-steps 12 Upper bound on agent tool calls
--ai-max-findings 50 Only the most severe findings are sent to the model, bounding cost on large changes
--ai-dry-run — Print the redacted request the model would receive, without calling it

The agent is treated as untrusted too. Repository content is passed as data, the prompt tells the model not to follow instructions found in code, the tools cannot write, execute or leave the repository, and new findings off the changed lines are discarded. Credentials never reach the model provider: the tools refuse files such as .env, private keys and *.tfstate, and provider keys, private-key blocks and hardcoded passwords in the diff or tool output are replaced with [REDACTED]. If the AI step fails for any reason (no key, rate limit, refusal), the deterministic review is still published and the report says why.

Built-in rules

Every rule is run over real repositories before it ships (Argo CD, Kubeflow Pipelines, KServe, MLflow, flytekit and others, with scripts/sweep.py), and the false positives that turn up are fixed first: tests and fixtures are not deployments, the name of a secret is not the secret, a pull request's base branch is not attacker input. The changelog says how each sweep moved the counts.

127 rules, generated from the code (acr rules; acr explain <id> for details):

Area Rule Severity What it catches
Secrets ACR-K8S-011 high Kubernetes Secret with real values committed to git
Secrets ACR-K8S-018 high Credential stored in a ConfigMap
Secrets ACR-MCP-002 critical Credential stored in plain text in an MCP config
Secrets ACR-SEC-001 critical Provider credential committed to source
Secrets ACR-SEC-002 high Hardcoded password or token
Application code ACR-APP-001 high SQL built with string formatting
Application code ACR-APP-002 high Shell command built from a string
Application code ACR-APP-003 high Dynamic code execution
Application code ACR-APP-004 high Unsafe deserialisation
Application code ACR-APP-005 medium TLS certificate verification disabled
Application code ACR-APP-006 medium Debug mode enabled in application code
Application code ACR-APP-007 low Weak hash used for security
Application code ACR-APP-008 critical JWT accepted without verifying its signature or expiry
Application code ACR-APP-009 high CORS allows any origin together with credentials
Application code ACR-APP-010 medium Predictable random numbers used for a secret value
Application code ACR-APP-011 high XML parser resolves external entities (XXE)
Application code ACR-APP-012 medium Redirect to a URL taken straight from the request (open redirect)
Application code ACR-APP-013 high File path taken straight from the request (path traversal)
Application code ACR-APP-014 medium Deprecated SSL/TLS protocol version allowed
Application code ACR-APP-015 medium Session or auth cookie without Secure or HttpOnly
Application code ACR-APP-016 medium Regular expression built from request input (ReDoS)
Application code ACR-APP-017 medium Django accepts any Host header (ALLOWED_HOSTS wildcard)
Application code ACR-APP-018 medium CSRF protection turned off
Application code ACR-APP-019 medium ECDSA private key handled through big.Int arithmetic on its D field
Application code ACR-APP-020 low Go HTTP request sent without a timeout
Application code ACR-APP-021 low Python HTTP request sent without a timeout
Application code ACR-APP-022 medium Archive extracted without a path filter (zip slip)
Application code ACR-APP-023 medium Temporary file created by name, open to a race (mktemp)
Application code ACR-APP-024 medium Go HTTP server with no request timeouts
Application code ACR-APP-025 medium File or directory created world-writable
Application code ACR-APP-026 high Authorisation checked with assert
AI / LLM / agent code ACR-AI-001 high User input concatenated into a system prompt (LLM01 Prompt Injection)
AI / LLM / agent code ACR-AI-002 critical LLM output used as code, shell, SQL or HTML (LLM05 Improper Output Handling)
AI / LLM / agent code ACR-AI-003 high Agent given dangerous tools without guardrails (LLM06 Excessive Agency)
AI / LLM / agent code ACR-AI-004 high Untrusted model code or weights loaded (LLM03 Supply Chain)
AI / LLM / agent code ACR-AI-005 medium LLM call without an output-token limit (LLM10 Unbounded Consumption)
AI / LLM / agent code ACR-AI-006 critical Provider API key exposed to the browser (LLM02 Sensitive Information Disclosure)
AI / LLM / agent code ACR-AI-007 low Full prompts or model responses written to logs (LLM02 Sensitive Information Disclosure)
AI / LLM / agent code ACR-AI-008 high Secret or credential placed in a system prompt (LLM07 System Prompt Leakage)
AI / LLM / agent code ACR-AI-009 medium Agent loop has no step or iteration limit (LLM10 Unbounded Consumption)
AI / LLM / agent code ACR-AI-010 high Coding agent run with its permission checks or sandbox turned off (LLM06 Excessive Agency)
AI / LLM / agent code ACR-AI-011 high Agent settings pre-approve any shell command or risky ones (LLM06 Excessive Agency)
AI / LLM / agent code ACR-AI-012 high Model server started with remote code execution enabled (LLM03 Supply Chain)
AI / LLM / agent code ACR-AI-013 medium Model demo published on a public share link
AI / LLM / agent code ACR-AI-014 medium Agent settings auto-start every MCP server in the repository
AI / LLM / agent code ACR-AI-015 high Agent settings open the whole disk or home directory to the agent
AI / LLM / agent code ACR-AI-016 high Agent plugin marketplace entry not pinned to a commit (LLM03 Supply Chain)
AI / LLM / agent code ACR-AI-017 critical Agent plugin hook runs a remote script or reads credentials (LLM03 Supply Chain)
AI / LLM / agent code ACR-MCP-001 high MCP server installed from an unpinned package
AI / LLM / agent code ACR-MCP-003 high MCP server over plain HTTP or with broad host access
AI / LLM / agent code ACR-MCP-004 medium MCP tools run without asking the user
AI / LLM / agent code ACR-SKILL-001 high Agent skill or rules file tells the agent to run a remote script
AI / LLM / agent code ACR-SKILL-002 critical Agent skill or rules file reads credentials or sends data out
AI / LLM / agent code ACR-SKILL-003 high Agent skill or rules file contains hidden or override instructions
AI / LLM / agent code ACR-SKILL-004 medium Agent skill pre-approves unrestricted shell access
Kubernetes ACR-K8S-001 critical Privileged container or privilege escalation allowed
Kubernetes ACR-K8S-002 high Pod shares the host's network, PID or IPC namespace
Kubernetes ACR-K8S-003 high hostPath volume mounts the node's filesystem
Kubernetes ACR-K8S-004 high Dangerous Linux capability added
Kubernetes ACR-K8S-005 medium Container image not pinned (latest or no tag)
Kubernetes ACR-K8S-006 high Container runs as root (UID 0)
Kubernetes ACR-K8S-007 medium Container has no CPU/memory limits
Kubernetes ACR-K8S-008 medium GPU requested without a matching limit
Kubernetes ACR-K8S-009 low Pod does not require a non-root user
Kubernetes ACR-K8S-010 high RBAC grants wildcard permissions or cluster-admin
Kubernetes ACR-K8S-012 high Seccomp or AppArmor confinement turned off
Kubernetes ACR-K8S-013 medium Container binds a port directly on the node (hostPort)
Kubernetes ACR-K8S-014 high Container sees the host's unmasked /proc (procMount: Unmasked)
Kubernetes ACR-K8S-015 medium Ingress injects raw NGINX configuration through a snippet annotation
Kubernetes ACR-K8S-016 medium Namespace switches Pod Security Admission to privileged
Kubernetes ACR-K8S-017 high Unauthenticated service exposed outside the cluster
Kubernetes ACR-K8S-019 medium NetworkPolicy allows all ingress traffic
Kubernetes ACR-K8S-020 high RBAC grants a privilege-escalation path
Kubernetes ACR-K8S-021 low Container keeps its default capabilities or may escalate privileges
Containers (Dockerfile, Compose) ACR-COMPOSE-001 critical Compose service runs privileged or shares a host namespace
Containers (Dockerfile, Compose) ACR-COMPOSE-002 high Compose service mounts the Docker socket or a sensitive host path
Containers (Dockerfile, Compose) ACR-COMPOSE-003 medium Compose image not pinned (latest or no tag)
Containers (Dockerfile, Compose) ACR-COMPOSE-004 high Compose publishes a database or unauthenticated port on all interfaces
Containers (Dockerfile, Compose) ACR-DOCKER-001 medium Base image not pinned (latest or no tag)
Containers (Dockerfile, Compose) ACR-DOCKER-002 medium Image runs as root (no USER instruction)
Containers (Dockerfile, Compose) ACR-DOCKER-003 high Remote script piped straight into a shell
Containers (Dockerfile, Compose) ACR-DOCKER-004 low ADD fetches a remote URL
Containers (Dockerfile, Compose) ACR-DOCKER-005 high Secret baked into the image via ENV or ARG
Containers (Dockerfile, Compose) ACR-DOCKER-006 low Package manager cache or sudo left in the image
Containers (Dockerfile, Compose) ACR-DOCKER-007 medium World-writable permissions set in the image
Containers (Dockerfile, Compose) ACR-DOCKER-008 high TLS or package signature checks disabled during the build
Containers (Dockerfile, Compose) ACR-DOCKER-009 high Credential file copied into the image
Containers (Dockerfile, Compose) ACR-DOCKER-010 medium SSH server installed or exposed in the image
Containers (Dockerfile, Compose) ACR-DOCKER-011 medium Stage copies from an external image not pinned (latest or no tag)
Containers (Dockerfile, Compose) ACR-DOCKER-012 medium Package installed into the image at whatever version is latest
GitHub Actions ACR-GHA-001 critical Privileged workflow checks out untrusted PR code
GitHub Actions ACR-GHA-002 high Untrusted event data interpolated into a shell script
GitHub Actions ACR-GHA-003 medium Third-party action not pinned to a commit SHA
GitHub Actions ACR-GHA-004 medium Workflow token has broad or default permissions
GitHub Actions ACR-GHA-005 high Secret printed to the workflow log
GitHub Actions ACR-GHA-006 low Deprecated workflow command
GitHub Actions ACR-GHA-007 medium Cloud OIDC token granted to every job in the workflow
GitHub Actions ACR-GHA-008 medium Every repository secret handed to an external reusable workflow
GitHub Actions ACR-GHA-009 medium Self-hosted runner used by a pull-request workflow
GitHub Actions ACR-GHA-010 high Insecure workflow commands re-enabled (ACTIONS_ALLOW_UNSECURE_COMMANDS)
GitHub Actions ACR-GHA-011 high Every secret serialised into one value with toJSON(secrets)
GitHub Actions ACR-GHA-012 high Workflow pipes a remote script straight into a shell
GitHub Actions ACR-GHA-013 medium Container action not pinned to an image digest
GitHub Actions ACR-GHA-014 critical Secret sent to an external host from a workflow step
GitHub Actions ACR-GHA-015 high Untrusted event data written into GITHUB_ENV or GITHUB_PATH
GitHub Actions ACR-GHA-017 high Checkout credentials uploaded in a workflow artifact
GitHub Actions ACR-GHA-018 high Action from an owner that looks like a well-known one (typosquat)
Terraform ACR-TF-001 critical Sensitive port open to the whole internet
Terraform ACR-TF-002 high Storage or data service exposed publicly
Terraform ACR-TF-003 high Encryption or TLS weakened
Terraform ACR-TF-004 high Wildcard or owner-level IAM permission
Terraform ACR-TF-005 medium Kubernetes control plane reachable from the internet or legacy auth on
Terraform ACR-TF-006 low Module source not pinned to a version
Terraform ACR-TF-007 medium Database can be destroyed without protection or a final backup
Terraform ACR-TF-008 medium Instance metadata reachable without session tokens (credential theft via SSRF)
Terraform ACR-TF-009 high Resource policy allows any principal ("*") without conditions
Terraform ACR-TF-010 medium Encryption key rotation turned off
Terraform ACR-TF-011 medium Cloud audit logging turned off
Terraform ACR-TF-012 low Bucket uses per-object ACLs instead of uniform access
Terraform ACR-TF-013 high Serverless function exposed on a public URL without authentication
Terraform ACR-TF-014 medium Secrets and keys can be permanently deleted at once
Dependencies ACR-DEP-001 high certifi pinned before 2026.10.18, which still trusts the compromised emSign ECC root
Dependencies ACR-DEP-002 high Packages fetched over plain HTTP or from a host exempted from TLS checks
Dependencies ACR-DEP-003 medium Extra package index next to PyPI, open to dependency confusion
Dependencies ACR-DEP-004 low npm lock installs a package from git with no integrity hash
Dependencies ACR-DEP-005 medium pip requirement installed from a moving git ref
Dependencies ACR-GHA-016 medium Dependency installed from a moving git ref in a workflow

Optional scanners

Installed scanners run automatically on the file types they understand; missing ones are skipped and listed in the report.

Scanner Covers
Gitleaks Secrets in any file
Semgrep SAST for application code (ACR_SEMGREP_CONFIG, default p/default)
Trivy Vulnerable dependencies and IaC misconfiguration
Checkov Terraform, Kubernetes, Dockerfile, GitHub Actions
hadolint Dockerfiles
actionlint GitHub Actions workflows
kube-linter Kubernetes manifests

When two tools report the same issue on the same line, the report shows it once and credits both.

Status

Part State
Diff-aware engine, 109 built-in rules, 7 scanner adapters (run in parallel) ✅ Done, unit-tested
Markdown / JSON / SARIF reports, CLI with severity gate ✅ Done, unit-tested
AI review agent (Claude + OpenAI-compatible) with read-only tools ✅ Done, unit-tested with a fake model
Inline PR comments and composite GitHub Action (single run) ✅ Done, unit-tested; first live run pending
.acr.yml config, baseline, acr explain, pre-commit hook, container image ✅ Done (v0.2.0)
Scoped suppressions, --staged, GitHub annotations, acr init, coding-agent rules ✅ Done (v0.3.0)
Custom rules, --include, acr classify, SARIF fingerprints, secret redaction for the agent ✅ Done (v0.4.0)
GitLab and JUnit reports, --diff-file, expiring suppressions, baseline check/prune, Compose and agent-instruction files ✅ Done (v0.5.0)

Design notes

How the pipeline is ordered and why: docs/architecture.md. Setups for GitLab, Jenkins, Azure DevOps, CircleCI, Bitbucket and other systems: docs/ci-integrations.md.

Inspired by the hybrid "deterministic pipeline + agent" approach popularised by Open Code Review; this project is an independent implementation focused on security, infrastructure and AI/agent code, with no code shared.

Related projects

Other open-source infrastructure work by Sunil Mehta:

  • k8s-inference-routing-benchmark: How much the router in front of LLM servers matters, measured: a Kubernetes Service against the llm-d Router's scorers on identical chat and RAG traces, with the picker's estimate of each pod's cache against the pods' real contents.
  • kubernetes-secure-mlops-pipeline: A model's path from training to serving with every artifact signed, attested and admitted by policy, drilled in CI; reviewed by this tool on every pull request.
  • k8s-gpu-scheduler-benchmark: Benchmarks Kubernetes GPU schedulers (default, Kueue, Volcano, KAI) in simulation and on real clusters.
  • ai-devsecops-cicd: Reference DevSecOps pipeline for LLM and AI-agent services: AI security tests, SBOM/AI-BOM, signing, admission policy.
  • llm-inference-platform: GPU-backed LLM serving with a streaming gateway, monitoring and reproducible benchmarks.
  • jev-inference-router: Observable decision routing for local GPU inference, evaluated against rule-based and classifier baselines.

License

MIT © Sunil Mehta

About

Agentic, scanner-grounded code review for the whole PR: app code, infrastructure (Kubernetes, Docker, Terraform, GitHub Actions) and AI/LLM/agent code (OWASP LLM Top 10, MCP, agent skills).

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages