Content
# 🛡️ GSC — Git Security Checker
[](https://github.com/marketplace/actions/gsc-security-audit)
[](https://github.com/hashgraph-online/hol-guard)
[](https://github.com/poliakarmai/gsc/actions/workflows/plugin-scan.yml)
[](LICENSE)
## English
**GSC is a self-learning AppSec platform that proves exploits, verifies fixes, and heals CI.**
```
detect → prove → fix → verify → heal → learn
```
Most scanners report matches. GSC **proves them**: every finding can be turned into a
runnable proof-of-concept, validated in a sandbox, then fixed and re-verified by
re-running the exploit.
**What makes it different:**
- **69 detectors** across SAST, SCA, secrets and IaC — plus a YAML rule DSL.
- **PoC auto-generation** with a safe-exploitation gate: a finding ships with a working exploit, not just a line number.
- **Proof-of-Fix** — a patch is only accepted after the exploit stops firing in a sandbox.
- **Self-learning** — detectors are re-scored nightly against a calibration network; noisy patterns are auto-deactivated at <30% TP. Federated feedback is privacy-first (`{tenant_hash, rule_id, tp, fp}` + DP noise).
- **Priority by exploitability, not CVSS** — EPSS + CISA KEV + ExploitDB.
- **BYO-LLM** — the engine, detectors and PoC logic are ours; LLM revalidation runs on *your* key (any OpenAI-compatible endpoint, including a local Ollama). No key → fast regex-only mode.
**Use it as a GitHub Action** (see below), from the **CLI / Docker image**, or as an
**MCP server** for AI coding agents — six tools (`scan_repo`, `scan_diff`,
`list_findings`, `get_finding`, `verify_finding`, `list_detectors`) over stdio or HTTP.
Read-only towards your repository: no patching, no PRs, no writes to the working tree.
(`verify_finding` does execute a PoC — see the safety notes in the MCP section.)
**Proven on real code:** [HALL_OF_FAME.md](HALL_OF_FAME.md) ·
first public case study: [CASE_STUDY_CYBERBRO.md](CASE_STUDY_CYBERBRO.md)
### Measured on 100 real GitHub projects
The same fixed corpus is re-scanned after detector changes — 100 real repositories
(90 clean + 10 known-vulnerable), pinned to specific commits, **regex-only, no LLM key**.
Same projects every run, so a delta is the fix and not a new dataset.
| | 2026-08-21 (baseline) | 2026-08-28 (after FP fixes) |
|---|---|---|
| Findings | 64,831 | 41,127 |
| CRITICAL | 4,302 | 414 |
| HIGH | 37,246 | 2,187 |
| Known-vulnerable projects flagged | 8 / 10 | **10 / 10** |
| Clean projects with ≥1 false CRITICAL | 48 / 90 | 41 / 90 |
CRITICAL precision on a labeled review of 434 findings: **~4–5% at baseline → 31.1%**
(TP = 135, FP = 299, 2026-08-26). That is still noisy. The remaining false-positive mass is
concentrated in GS001 (secrets), GS005 (SQLi), GS020 (XSS) and GS037 (path traversal) and is
worked down rule by rule — we publish the numbers we have, not the numbers we would like.
*Method note:* corpus, severity counting and per-rule aggregation are ours; the engine ships as
a closed image, so reproducing this means running `gsc scan --ci --json` over the same pinned
projects and aggregating the same way. No clean-room comparison against other vendors is implied.
**License:** this repo (Action, docs, marketing) is **Apache-2.0**. The engine ships as a
closed Docker image `ghcr.io/poliakarmai/gsc-scanner` under **BSL 1.1** (free to scan your own
repos; competing SaaS requires a commercial license; converts to Apache-2.0 on 2030-08-06).
### Case study: XSS in a 122★ OSINT platform (stars as of 2026-08-08)
First public proof — [`stanfrbd/cyberbro`](https://github.com/stanfrbd/cyberbro) (46,677 LOC, 281 files):
| | |
|---|---|
| Finding | **CWE-79** XSS via search highlight — `static/history.js:148`, `p.innerHTML = p.title.replace(...)` |
| Severity | HIGH (CVSS 7.5) |
| Detector | **GS020** (`gs020_xss_injection`) |
| Fix | 9 lines, 1 file — exploit re-run in sandbox confirms it no longer fires |
Full write-up → [CASE_STUDY_CYBERBRO.md](CASE_STUDY_CYBERBRO.md) ·
more findings in production OSS → [HALL_OF_FAME.md](HALL_OF_FAME.md)
---
**GSC — самообучающаяся AppSec-платформа полного цикла.**
```
detect → prove → fix → verify → heal → learn
```
## 🚀 Быстрый старт — GitHub Action
Проверьте свой репозиторий за 30 секунд. Добавьте файл `.github/workflows/gsc.yml`:
```yaml
name: GSC Audit
on:
pull_request:
branches: [main, master]
jobs:
audit:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: poliakarmai/gsc@v1 # для воспроизводимости — pin на commit SHA
with:
fail_on_critical: false # true = блокировать merge при CRITICAL
```
Откройте pull request — GSC отсканирует код, пришлёт комментарий с находками
(CRITICAL / HIGH) и поставит оценку безопасности. Ядро поставляется как
закрытый Docker-образ `ghcr.io/poliakarmai/gsc-scanner` — исходный код движка
не публикуется.
> **Воспроизводимость.** `@v1` и тег образа — плавающие ссылки: результат может
> измениться без изменения вашего workflow. Для аудита/CI фиксируйте
> `poliakarmai/gsc@<commit-sha>` и образ по digest
> (`ghcr.io/poliakarmai/gsc-scanner@sha256:<digest>`).
**Входные параметры:**
| Вход | По умолчанию | Что делает |
| --- | --- | --- |
| `path` | `.` | Что сканировать (корень репозитория) |
| `deep_scan` | `true` | Глубокий скан (Echelon 4, медленнее) |
| `fail_on_critical` | `false` | `true` — упасть при CRITICAL |
| `fail_on_score` | `0` | Упасть, если score ниже порога. `0` = выключено, диапазон 1–100 |
| `max_findings_to_comment` | `10` | Сколько строк показывать в комментарии на каждую секцию |
| `llm_api_key` | `''` | BYO-LLM ключ для ревалидации (без него — regex-only) |
| `llm_base_url` | `''` | Свой OpenAI-совместимый эндпоинт (DeepSeek/OpenRouter/Ollama) |
| `llm_model` | `''` | Имя модели для ревалидации |
| `sarif` | `false` | Дополнительно отдать SARIF для GitHub Code Scanning |
| `reachability` | `false` | Понизить находки в недостижимых файлах (import-graph) |
**Выходы:** `score` (0–100) и `grade` (A+ … F).
> Комментарий в PR считает находки **по локациям** (`file:line`), а не по
> срабатываниям детекторов: один секрет, пойманый четырьмя правилами, — это
> одна строка с перечислением правил, а не четыре. `Total` в таблице всегда
> равен сумме категорий.
LLM-ревалидация — на вашем ключе (BYO-LLM):
```yaml
- uses: poliakarmai/gsc@v1
with:
llm_api_key: ${{ secrets.DEEPSEEK_API_KEY }} # DeepSeek / OpenRouter / GMI / Ollama
```
Без ключа — быстрый regex-only скан (уязвимости находит; confirmed-вердикты — с ключом).
## Что умеет
| Слой | Возможности |
|---|---|
| **SAST** | 69 детекторов (SAST · SCA · Secrets · IaC), YAML rule DSL, LLM-триаж с confidence scoring |
| **Доказательство** | PoC auto-generation — рабочий эксплойт для находки *(движок; CLI/engine, не MCP)* |
| **Исправление** | Proof-of-Fix — патч верифицируется перезапуском эксплойта в sandbox; self-healing CI (авто-PR) *(CLI, требует явного флага)* |
| **Приоритизация** | EPSS + CISA KEV + ExploitDB (не сырой CVSS), БДУ ФСТЭК |
| **Recon** | passive reconnaissance: subdomain / tech / DNS / HTTP |
| **Supply chain** | SBOM (CycloneDX / SPDX) + VEX |
| **Compliance** | маппинг находок на ГОСТ Р 56939-2024, PCI DSS 4.0, SOC2, ISO 27001, CWE, OWASP — отчёт для ФСТЭК / КИИ / аудита |
| **Интеллект** | security archaeology, predictive forecasting, NL-policy, federated self-learning |
> **Где что доступно.** Возможности движка не равны возможностям Action/MCP:
>
> | Возможность | Action | MCP | CLI / engine image |
> |---|---|---|---|
> | Скан (SAST/SCA/Secrets/IaC) | ✅ | ✅ | ✅ |
> | PoC auto-generation | — | — | ✅ (`--with-poc`) |
> | Proof-of-Fix | — | — | ✅ (`pof generate`) |
> | Self-healing CI (авто-PR) | — | — | ✅ (`--create-pr`, human-approval) |
>
> В MCP **нет** деструктивных действий (auto-patch/PR) — осознанно, они остаются
> в CLI/human-лупе. `verify_finding` перезапускает PoC в sandbox, то есть по
> побочным эффектам это не «чисто read-only».
### Что уже внутри (код, а не план)
| Механика | Где | Что делает |
|---|---|---|
| **Мутационный re-attack PoF** | `gsc_cli/gsc_poc_mutator.py` → `gsc_proofoffix.py` | после фикса PoC перезапускается в мутированных формах (url-encode, double-encode, HTML-entities, case-swap, tab/space) — ловит «залатали симптом, а не причину». Детерминированно, без LLM |
| **Positive control + taint-recheck** | `gsc_pof_sandbox.py`, `tests/test_taint_recheck.py` | PoC обязан срабатывать на уязвимом варианте и молчать на исправленном |
| **Контейнерная изоляция hostile-PoC** | `gsc_pof_sandbox.py::_isolation_backend()` | docker/podman (`--network none`, read-only, cap-drop, non-root) + rlimit-fallback; уровень изоляции возвращается в каждом результате. **В публичном образе docker/podman нет** → движок fail-closed: PoC не исполняется вовсе, вердикт `unavailable` (это НЕ «не воспроизводится»); реальный прогон PoC — CLI на хосте с docker/podman. Проброс `docker.sock` — не изоляция, а выдача PoC хостового демона |
| **Quick-режим без LLM** | `gsc external-scan --scan-mode quick` | regex-only: находки без LLM-вердиктов, 0 токенов |
## 🎯 Наша фишка: BYO-LLM — движок наш, судья твой
GSC — это **движок + детекторы + PoC**, а не очередная обёртка над LLM.
- **От GSC:** 69 детекторов, V3-scoring, FP-фильтр, PoC/PoF, self-learning — закрытый IP в Docker-образе.
- **От вас:** LLM-ключ (любой OpenAI-совместимый — DeepSeek/OpenRouter/GMI/локальный Ollama).
Почему это выгодно вам:
- **Ноль расходов на чужие токены** — ревалидация на вашем ключе.
- **Никакой привязки к провайдеру** — хоть бесплатный локальный Ollama.
- **Вы платите за детекторы и логику**, а не за вызовы LLM.
## 🧠 Второй столп: Self-Learning — детекторы обновляются сами, каждую ночь
Помимо BYO-LLM у GSC есть **замкнутый контур обучения без LLM** (0 токенов, детерминированный):
```
скан → авто-разметка findings по calibration-сети (16 проектов: 9 clean + 7 vuln)
→ авто-деактивация шумных паттернов (<30% TP)
→ пополнение эталонов из security-фидов
→ federated feedback (приватно: только {tenant_hash, rule_id, tp, fp} + DP-шум)
```
Детекторы учатся на **реальных находках клиентов** через federated-контур — то,
чего мейнстрим сознательно избегает (риск дрейфа). GSC обходит это консервативным
self-learning: разметка по фиксированной сети + дискретные деактивации, без
переписывания весов — скорость ежедневного апдейта без катастрофического дрейфа.
| Вендор | Как обновляет правила | Self-learning |
|---|---|---|
| Semgrep | вручную (`semgrep-rules`) | ❌ |
| GitHub CodeQL | вручную (Security Lab) | ❌ |
| Snyk Code | офлайн-ML, «never customer data» | ❌ |
| SonarQube | вручную (SonarSource) | ❌ |
| **GSC** | **ежедневно · 0-LLM · federated** | ✅ |
**Никто не замыкает петлю обучения в проде — GSC закрывает этот зазор.**
Подробно, с пруф-базой (доки вендоров + research-статьи) →
[SELF_LEARNING.md](SELF_LEARNING.md).
> **Честная рамка.** GSC не заменяет Semgrep/CodeQL: у них шире покрытие языков и
> зрелее правила. GSC закрывает то, чего они не делают — доказывает находку PoC,
> верифицирует фикс перезапуском эксплойта, учится на TP/FP. Рабочая схема — вместе:
> зрелый сканер на массовый охват + GSC на закрытие конкретных находок.
## 🔌 Интеграции
### MCP — подключи GSC к Claude Code / Cursor / Codex
Движок отдаёт 6 инструментов по MCP (read-only по отношению к репозиторию — не патчит
и не делает PR; `verify_finding` исполняет PoC там, где есть docker/podman — см. границы ниже): `scan_repo`, `scan_diff`,
`list_findings`, `get_finding`, `verify_finding`, `list_detectors`.
Сервер уже внутри образа — `.mcp.json` в корне проекта (Claude Code):
```json
{
"mcpServers": {
"gsc": {
"command": "docker",
"args": ["run", "--rm", "-i",
"-v", "${PWD}:/repo:ro",
"-v", "gsc-state:/app/.hermes/state",
"ghcr.io/poliakarmai/gsc-scanner:v1", "mcp"],
"env": { "GSC_ALLOWED_ROOTS": "/repo" }
}
}
}
```
Cursor и любой другой MCP-клиент — та же форма (`command` + `args`).
По умолчанию транспорт `stdio`; всё не-протокольное идёт в stderr.
HTTP (общий сервер, токен обязателен — fail-closed):
```bash
docker run --rm -p 8001:8001 -e GSC_MCP_TOKEN=your-secret \
ghcr.io/poliakarmai/gsc-scanner:v1 mcp --transport http --host 0.0.0.0 --port 8001
```
> ⚠️ **На том конце — агент, и честно о границах:**
>
> - Деструктивных действий нет: ни auto-patch, ни PR — они в CLI/human-лупе.
> - `verify_finding` **не исполняет PoC в этом образе**. Гейты в коде реальные
> (DESTRUCTIVE-PoC и недетерминированный PoC отклоняются), а без OS-изоляции
> движок fail-closed: docker/podman внутри нет → PoC не запускается вовсе,
> тул отвечает `status: "unavailable"` + hint. Это **не** «не воспроизводится»:
> о самой находке такой ответ не говорит ничего. Реальный прогон — CLI на хосте
> с docker/podman. Проброс `docker.sock` — не изоляция, а выдача PoC хостового
> демона (эквивалент root): не делать.
> - `scan_repo` ограничен бюджетом: `GSC_SCAN_TIMEOUT` (default 300 с) на свип
> детекторов, `GSC_MAX_FILES` (default 50 000) на инвентарь. Упёрлись в лимит —
> в ответе `status: "partial"`, `truncated: true` и список детекторов, которые
> не запускались. Мало находок там **не значит** «чисто»; такой скан в БД не
> сохраняется.
> - `GSC_ALLOWED_ROOTS` ограничивает `scan_repo`/`scan_diff` смонтированными путями.
> - `scan_repo` сохраняет находки в БД (`persisted: true` в ответе), поэтому
> `list_findings` и `get_finding` их видят сразу. `get_finding` отвечает из БД
> (`source: "database"`), без пересканирования; ~30–60 с — только если ключа
> в БД нет и он пересобирает скан.
> - Нужен **writable** volume на `/app/.hermes/state` — там SQLite. Docker создаёт
> volume от root, а процесс идёт под uid 999, поэтому сначала отдайте права:
> `docker run --rm -v gsc-state:/s --user 0 <image> chown -R 999:999 /s`.
> Без этого `scan_repo` вернёт `persisted: false` (скан работает, БД — нет),
> а `--read-only` вообще не годится.
> - Без `llm_api_key`/`DEEPSEEK_API_KEY` работают только regex-детекторы.
### Paperclip — «найми GSC как сотрудника по безопасности»
[Paperclip](https://github.com/paperclipai/paperclip) (79K★, open-source оркестратор AI-агентов)
подключает GSC через MCP Tool Gateway — любой нанятый агент (Claude Code / Codex / Hermes)
получает GSC-инструменты и роль «Security Engineer».
> 📦 Интеграция идёт через MCP-сервер образа (см. раздел MCP выше). Гайд и skill
> `gsc-security-review` поставляются с коммерческим доступом (репозиторий
> `gsc-core`, `docs/integrations/paperclip/`) — в публичном репо их нет.
- **Транспорт:** `local_stdio` (subprocess) или `mcp_remote` (HTTP)
Подключение за минуты: зарегистрируй `ToolStdioCommandTemplate`, создай gateway — и GSC сканирует репозитории твоей Paperclip-компании.
## Лицензия и доступ
**Этот репозиторий (GitHub Action, документация, маркетинг) — Apache License 2.0.** Свободно используйте Action в своих репозиториях.
Движок GSC (детекторы, PoC/PoF, калибровочная сеть, LLM-слой) поставляется отдельно как закрытый Docker-образ `ghcr.io/poliakarmai/gsc-scanner` под **Business Source License 1.1 (BSL 1.1)**:
- **Свободное использование** — включая сканирование собственных репозиториев в production — разрешено всегда.
- **Коммерческий SaaS/SAST-сервис** для третьих лиц, конкурирующий с GSC, — требует коммерческой лицензии (после NDA).
- **Change Date 2030-08-06** → движок автоматически переходит на Apache 2.0.
Для демо, пилота или приобретения — свяжитесь с автором.
© 2026 Алексей Поляков.
Connection Info
You Might Also Like
No recommendations available