Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ jobs:
- name: Install development dependencies
run: python -m pip install -e ".[dev]"

- name: Run tests
run: python -m pytest -q
- name: Run tests with branch coverage
run: |
python -m coverage run -m pytest -q
python -m coverage report

static-analysis:
name: Static analysis
Expand Down Expand Up @@ -92,6 +94,9 @@ jobs:
reports/sample-app/static-analysis.json
python -m pytest tests/test_sample_app_security_demo.py -q

- name: Validate whole-project self-analysis
run: python -m tools.generate_self_analysis_report --check

- name: Verify static analysis reports
if: ${{ !cancelled() }}
shell: bash
Expand All @@ -100,6 +105,7 @@ jobs:
reports/ci/static-analysis-src.json
reports/ci/static-analysis-tools.json
reports/ci/static-analysis-sample-app.json
reports/project/static-analysis.json
)

for report in "${reports[@]}"; do
Expand All @@ -118,6 +124,7 @@ jobs:
reports/ci/static-analysis-src.json
reports/ci/static-analysis-tools.json
reports/ci/static-analysis-sample-app.json
reports/project/static-analysis.json
if-no-files-found: error
retention-days: 14

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Statik kod analiz aracının ve bağımlılık tarayıcısının test edileceği
- [Proje Kapsamı](docs/scope.md)
- [Beş Haftalık Proje Planı](docs/project-plan.md)
- [GitHub Actions CI](docs/ci.md)
- [Whole-Project Self-Analysis ve Test Coverage](docs/self-analysis.md)

### Bileşen Dokümanları

Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Bu klasörde projenin genel dokümanları ve üç ana bileşene ait dokümanlar
- [Proje Kapsamı](scope.md)
- [Beş Haftalık Proje Planı](project-plan.md)
- [GitHub Actions CI](ci.md)
- [Whole-Project Self-Analysis ve Test Coverage](self-analysis.md)

## Bileşen Dokümanları

Expand Down
38 changes: 27 additions & 11 deletions docs/ci.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# GitHub Actions CI

Bu doküman Backlog 5.1, 5.2, 5.3 ve 5.4 kapsamındaki test, statik analiz,
Bu doküman Backlog 5.1, 5.2, 5.3, 5.4 ve 5.5 kapsamındaki test, statik analiz,
bağımlılık tarama ve rapor artifact pipeline'ının gereksinimlerini, güvenlik
sınırlarını ve çalışma sırasını açıklar.

Expand All @@ -14,7 +14,7 @@ saklama workflow'u tamamlanmıştır:
```

Workflow Pull Request değişikliklerinde ve `main` branch push olaylarında
Python 3.11 test paketini çalıştırır. Test gate'i geçtikten sonra proje
Python 3.11 test paketini branch coverage ile çalıştırır. Test gate'i geçtikten sonra proje
kaynaklarını ve kontrollü demo uygulamasını ayrı bir static-analysis job'unda
tarar. Buna paralel dependency-scan job'u, checked-in OSV fixture ile kritik
güvenlik açığı gate'ini çalıştırır. İki güvenlik job'u ürettikleri doğrulanmış
Expand Down Expand Up @@ -76,11 +76,16 @@ Job sırası:
3. `pyproject.toml` anahtarına göre pip download cache'ini geri yükle.
4. Pip'i güncelle.
5. Projeyi `.[dev]` extra bağımlılıklarıyla editable kur.
6. `python -m pytest -q` komutunu çalıştır.
6. `python -m coverage run -m pytest -q` ile testleri ve branch coverage'ı ölç.
7. `python -m coverage report` ile `%97` minimum kapsam gate'ini uygula.

Install veya test komutlarından herhangi biri non-zero exit code üretirse job
ve workflow başarısız olur.

`sample_app/analyzer_demo.py` çalıştırılmaması gereken kontrollü analiz girdisi
olduğu için runtime coverage paydasından çıkarılır; static-analysis ve demo
integration kontrollerinde tam olarak doğrulanmaya devam eder.

## Statik Analiz Job Akışı

`static-analysis` job'u test job'una `needs: test` ile bağlıdır. Başarılı test
Expand All @@ -92,6 +97,7 @@ Job aşağıdaki raporları üretir:
reports/ci/static-analysis-src.json
reports/ci/static-analysis-tools.json
reports/ci/static-analysis-sample-app.json
reports/project/static-analysis.json
```

`src` ve `tools` taramalarında herhangi bir bulgu CLI exit code `1` ürettiği
Expand All @@ -106,6 +112,10 @@ modeli `INFO`, `WARNING` ve `ERROR` seviyelerini kullandığından `HIGH` ve
karşılaştırılır; ardından kontrollü demo entegrasyon testleri çalıştırılır.
Exit code veya baseline değişirse job başarısız olur.

`python -m tools.generate_self_analysis_report --check` bütün repository'yi
yeniden analiz eder ve canonical project raporuyla karşılaştırır. Demo dışındaki
beklenmeyen bir bulgu veya report drift'i static-analysis job'unu başarısız yapar.

## Bağımlılık Tarama Job Akışı

`dependency-scan` job'u test job'una bağlıdır ve statik analiz job'uyla
Expand Down Expand Up @@ -149,7 +159,7 @@ Her workflow attempt'i aşağıdaki iki artifact'ı oluşturur:

| Artifact | İçerik |
|---|---|
| `static-analysis-reports-${{ github.run_attempt }}` | `static-analysis-src.json`, `static-analysis-tools.json`, `static-analysis-sample-app.json` |
| `static-analysis-reports-${{ github.run_attempt }}` | Üç CI static raporu ve `reports/project/static-analysis.json` canonical öz-analiz raporu |
| `dependency-scan-report-${{ github.run_attempt }}` | `dependency-scan.json` |

Artifact adından `github.run_attempt` kullanılması, aynı workflow run'ı yeniden
Expand All @@ -174,7 +184,8 @@ CI test adımını yerelde doğrulamak için:
```powershell
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
python -m pytest -q
python -m coverage run -m pytest -q
python -m coverage report
```

Statik analiz adımlarını yerelde doğrulamak için:
Expand All @@ -188,6 +199,7 @@ securecode-analyzer tools --format json `
securecode-analyzer sample_app --format json `
> reports/ci/static-analysis-sample-app.json
python -m pytest tests/test_sample_app_security_demo.py -q
python -m tools.generate_self_analysis_report --check
```

Demo komutunun beklenen exit code değeri `1` olmalıdır. Üretilen demo JSON'u
Expand Down Expand Up @@ -229,11 +241,13 @@ python -m pytest tests/test_python_compatibility.py -q
- Concurrency cancellation
- Üç action için tam 40 karakterli SHA ve release etiketi
- Python 3.11 ve pip cache yapılandırması
- Pip upgrade, dev install ve pytest komut sırası
- Pip upgrade, dev install, coverage test ve coverage gate komut sırası
- Branch coverage ve `%97` minimum coverage floor'u
- Ubuntu runner ve 10 dakikalık timeout
- Test job'una bağlı statik analiz job'u
- `src`, `tools` ve `sample_app` JSON rapor yolları
- Kontrollü demo exit code ve baseline doğrulaması
- Whole-project canonical self-analysis drift kontrolü
- Test job'una bağlı offline dependency-scan job'u
- Açık requirements, fixture, output ve `critical` eşik değerleri
- Dependency baseline ve entegrasyon testi doğrulaması
Expand All @@ -249,18 +263,20 @@ geçen Python 3.12+ söz dizimi değişiklikleri CI'a ulaşmadan tespit edilir.
Doğrulanan mevcut sonuç:

```text
CI workflow contract tests: 16 passed
Offline dependency CI tests: 6 passed
CI workflow contract tests: 18 passed
Offline dependency CI tests: 21 passed
Python 3.11 compatibility tests: 1 passed
Complete test suite: 1000 passed
Complete test suite: 1044 passed
Combined statement/branch coverage: 98.6% (97.0% required)
Whole-project self-analysis check: passed (5 intentional findings)
Workflow YAML parse check: passed
```

## Sonraki Güvenlik Job'ları

Backlog 5.1, 5.2, 5.3 ve 5.4 tamamlanmıştır. Sonraki aşama:
Backlog 5.1, 5.2, 5.3, 5.4 ve 5.5 tamamlanmıştır. Sonraki aşama:

1. Backlog 5.5 kapsamında eksik test ve self-analysis kapsamını tamamlama
1. Backlog 5.6 kapsamında README ve kullanım dokümantasyonunu tamamlama

Bu ayrım her güvenlik gate'inin davranışını bağımsız olarak incelemeyi sağlar.

Expand Down
6 changes: 5 additions & 1 deletion docs/project-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,10 @@ Sub-task’ler:
* Bilinen false positive sonuçları belgeye ekle.
* Son tarama raporunu sakla.

**Durum:** Tamamlandı. Branch-aware test coverage gate'i, whole-project
self-analysis generator'ı, canonical JSON raporu ve bulgu sınıflandırması
[`docs/self-analysis.md`](self-analysis.md) içinde belgelenmiştir.

## Backlog 5.6 — README ve kullanım dokümantasyonu

**Öncelik:** P0
Expand Down Expand Up @@ -1617,4 +1621,4 @@ Proje sonunda aşağıdaki sorulara olumlu cevap verilebilmelidir:

- [Proje dokümantasyonuna dön](README.md)
- [Tüm bileşenlere git](components/README.md)
- [Projenin ana sayfasına dön](../README.md)
- [Projenin ana sayfasına dön](../README.md)
123 changes: 123 additions & 0 deletions docs/self-analysis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Whole-Project Self-Analysis and Test Coverage

Bu belge Backlog 5.5 kapsamındaki eksik test denetimini ve statik analiz
aracının kendi repository'si üzerinde çalıştırılmasının sonuçlarını kaydeder.

## Sonuç

Production static analyzer `src`, `sample_app`, `tools` ve `tests` dahil bütün
Python kaynaklarında çalıştırılmıştır. Son canonical rapor:

```text
reports/project/static-analysis.json
```

Rapor yalnızca `sample_app/analyzer_demo.py` içindeki beş kontrollü örneği
içerir. Çalışan Flask uygulaması bu modülü import etmez; bulgular aracın demo
çıktısını göstermek için bilinçli olarak tutulan gerçek pozitiflerdir.

| Rule | Konum | Sınıflandırma |
|---|---|---|
| `SA005` | `analyzer_demo.py:8` | Kontrollü hardcoded-secret örneği |
| `SA001` | `analyzer_demo.py:11` | Kontrollü long-function örneği |
| `SA006` | `analyzer_demo.py:11` | Kontrollü naming örneği |
| `SA003` | `analyzer_demo.py:14` | Kontrollü TODO örneği |
| `SA004` | `analyzer_demo.py:54` | Kontrollü empty-except örneği |

Final raporda bilinen false positive yoktur. Beş bulgunun tümü beklenen ve
testlerle tam konumuna kadar sabitlenmiş true positive demo fixture'larıdır.

## İlk Tarama ve Düzeltmeler

İlk repository taraması 10 bulgu üretti. Beş demo bulgusuna ek olarak dört
test fonksiyonu `SA001` sınırını aşıyor, bir hardcoded-secret kural testi de
test verisini kendi kaynak kodunda literal olarak tuttuğu için `SA005`
üretiyordu.

Uygulanan düzeltmeler:

- Uzun subprocess kurulum kodu küçük ve isimlendirilmiş helper'lara ayrıldı.
- Büyük OSV payload'ları test fonksiyonlarından module-level fixture
sabitlerine taşındı.
- Demo finding beklentisi tek bir okunabilir sabitte toplandı.
- Secret redaction testi aynı değeri runtime'da parçalardan kuracak şekilde
değiştirildi; üretim analyzer'ına verilen kaynak hâlâ literal secret
assignment içerdiğinden kural davranışı korunuyor.

Bu değişikliklerden sonra uygulama, araç ve test kaynaklarında beklenmeyen
bulgu kalmadı.

## Test Kapsamı

Coverage ölçümü statement ve branch kapsamını birlikte hesaplar:

```toml
[tool.coverage.run]
branch = true
source = ["src", "sample_app", "tools"]
omit = ["*/sample_app/analyzer_demo.py"]
```

`analyzer_demo.py` bilerek güvenli olmayan kaynak örnekleri içerdiği ve hiçbir
zaman import edilmemesi gerektiği için runtime coverage paydasından çıkarılır.
Dosya static-analysis ve integration test kapsamından çıkarılmaz.

İlk ölçümde demo hariç birleşik kapsam yaklaşık `%95,4` idi. Eksik dallara
eklenen testlerden sonra doğrulanan sonuç:

```text
Tests: 1044 passed
Combined statement/branch coverage: 98.6%
Required CI floor: 97.0%
```

Eklenen veya tamamlanan sözleşmeler:

- OSV direct network error, timeout, status ve response-body hataları
- Offline fixture JSON, metadata, query ve parser hataları
- Dependency model type doğrulaması
- CVSS privilege/scope ağırlıklarının bütün dalları
- CLI operational exit code `2` ve report normalization hataları
- JSON report missing, stale, current ve write modları
- Hardcoded-secret deduplication ve unsupported AST target davranışı
- Whole-project rapor üretimi, drift kontrolü ve portable yollar
- Kontrollü demo bulgularının tam rule, dosya, satır ve severity eşleşmesi

Kapsam dışında kalan az sayıdaki satır; abstract base guard'ları, argparse
choices sonrasındaki erişilemeyen defensive error'lar, Flask/Werkzeug'ün tip
garantisi verdiği form dalları ve yalnızca module entrypoint süreçlerinde
çalışan `__main__` guard'larıdır. Bunlar public davranış yerine interpreter veya
framework sözleşmesini tekrar eden yapay testler gerektirdiği için coverage
hedefi `%100` olarak belirlenmemiştir.

## Yeniden Üretim

PowerShell üzerinde tam test ve coverage gate'i:

```powershell
python -m coverage run -m pytest -q
python -m coverage report
```

Canonical self-analysis raporunu üretmek için:

```powershell
python -m tools.generate_self_analysis_report
```

Dosya yazmadan drift kontrolü yapmak için:

```powershell
python -m tools.generate_self_analysis_report --check
```

`--check`, rapor eksik veya güncel değilse exit code `1`; exact match için
exit code `0` döndürür. CI hem `%97` coverage floor'unu hem de canonical
self-analysis raporunu her Pull Request'te doğrular.

## Navigation

- [GitHub Actions CI](ci.md)
- [Beş Haftalık Proje Planı](project-plan.md)
- [Proje dokümantasyonuna dön](README.md)
- [Projenin ana sayfasına dön](../README.md)
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies = []

[project.optional-dependencies]
dev = [
"coverage>=7.10,<8.0",
"Flask>=3.1.3,<4.0",
"pytest>=9.0,<10.0",
]
Expand All @@ -23,6 +24,18 @@ where = ["src"]

[tool.pytest.ini_options]
testpaths = ["tests"]

[tool.coverage.run]
branch = true
source = ["src", "sample_app", "tools"]
omit = ["*/sample_app/analyzer_demo.py"]

[tool.coverage.report]
fail_under = 97
precision = 1
show_missing = true
skip_covered = true

[project.scripts]
securecode-analyzer = "static_analyzer.runner:main"
securecode-dependency-scan = "dependency_scanner.runner:main"
47 changes: 47 additions & 0 deletions reports/project/static-analysis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"findings": [
{
"rule_id": "SA005",
"message": "Possible hardcoded secret found.",
"file_path": "sample_app/analyzer_demo.py",
"line_number": 8,
"severity": "warning",
"column_number": 1
},
{
"rule_id": "SA001",
"message": "Function 'buildDemoChecklist' has 65 lines, exceeding the limit of 50.",
"file_path": "sample_app/analyzer_demo.py",
"line_number": 11,
"severity": "warning",
"column_number": 0
},
{
"rule_id": "SA006",
"message": "Function name should use snake_case.",
"file_path": "sample_app/analyzer_demo.py",
"line_number": 11,
"severity": "info",
"column_number": 1
},
{
"rule_id": "SA003",
"message": "TODO comment found.",
"file_path": "sample_app/analyzer_demo.py",
"line_number": 14,
"severity": "info",
"column_number": 7
},
{
"rule_id": "SA004",
"message": "Empty except block found.",
"file_path": "sample_app/analyzer_demo.py",
"line_number": 54,
"severity": "warning",
"column_number": 5
}
],
"summary": {
"total": 5
}
}
Loading