Add test and security baseline
- make quick/check/mutation from cj/security-baseline (Makefile unchanged, settings in baseline.mk), pre-commit, gitleaks, Semgrep rules, ESLint security rules, Forgejo workflow - tests/security: generic baseline tests plus app config and role tests against createApp() with an in-memory database - extract createApp() from src/server/index.ts; LB_DATABASE_PATH for tests - fix gaps found by the tests: reject unknown fields on project create, answer malformed JSON with 400 instead of 500, set nosniff on the API - npm audit fix (next 16.4.1 and others, no high/critical left) - clear ESLint errors, safeFileName without control-character regex - per-project ownership stays an open, documented gap (idorGap -> TODO) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
67476ea59b
commit
a7a1595cbf
38 changed files with 5852 additions and 442 deletions
117
Makefile
Normal file
117
Makefile
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Test- & Security-Baseline
|
||||
# Diese Datei unverändert aus cj/security-baseline übernehmen. App-Spezifisches gehört in
|
||||
# baseline.mk (wird hier eingelesen), damit Updates der Baseline einfach drüberkopiert werden können.
|
||||
#
|
||||
# Werkzeuge: Python-Tools im venv der App, Scanner (gitleaks, Semgrep, Trivy, hadolint, ZAP,
|
||||
# schemathesis) als Docker-Images, npm lokal oder im node-Container.
|
||||
|
||||
-include baseline.mk
|
||||
|
||||
PY_DIR ?= backend
|
||||
PY_SRC ?= app
|
||||
NODE_DIR ?= frontend
|
||||
SEMGREP_RULES ?= .semgrep
|
||||
SCRIPTS ?= scripts/security
|
||||
MUTATIONS ?= security-mutations.toml
|
||||
NODE_IMAGE ?= node:24
|
||||
OPENAPI_PATH ?= /openapi.json
|
||||
FUZZ_CHECKS ?= not_a_server_error
|
||||
ZAP_ARGS ?= -I
|
||||
|
||||
GITLEAKS_IMAGE ?= ghcr.io/gitleaks/gitleaks:v8.30.1
|
||||
SEMGREP_IMAGE ?= semgrep/semgrep:1.179.0
|
||||
TRIVY_IMAGE ?= aquasec/trivy:latest
|
||||
HADOLINT_IMAGE ?= hadolint/hadolint:latest
|
||||
ZAP_IMAGE ?= ghcr.io/zaproxy/zaproxy:stable
|
||||
SCHEMATHESIS_IMAGE ?= schemathesis/schemathesis:stable
|
||||
|
||||
HAS_PY := $(wildcard $(PY_DIR)/requirements.txt $(PY_DIR)/pyproject.toml)
|
||||
HAS_NODE := $(wildcard $(NODE_DIR)/package.json)
|
||||
VENV := $(PY_DIR)/.venv
|
||||
TOOLS := .venv-tools
|
||||
UID_GID := $(shell id -u):$(shell id -g)
|
||||
DOCKER := docker run --rm -u $(UID_GID) -e HOME=/tmp -v "$(CURDIR)":/src -w /src
|
||||
NPM ?= $(if $(shell command -v npm 2>/dev/null),npm --prefix $(NODE_DIR),docker run --rm -u $(UID_GID) -e HOME=/tmp -v "$(CURDIR)":/w -w /w/$(NODE_DIR) $(NODE_IMAGE) npm)
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
.PHONY: help setup quick check lint test secrets sast audit container zap fuzz mutation mutmut vet-deps
|
||||
|
||||
help: ## Diese Übersicht
|
||||
@grep -hE '^[a-z-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf " make %-12s %s\n", $$1, $$2}'
|
||||
|
||||
setup: ## venvs, npm-Pakete, pre-commit-Hook einrichten
|
||||
python3 -m venv $(TOOLS)
|
||||
$(TOOLS)/bin/pip install -q pre-commit==4.7.0
|
||||
ifneq ($(HAS_PY),)
|
||||
python3 -m venv $(VENV)
|
||||
$(VENV)/bin/pip install -q -r $(PY_DIR)/requirements-dev.txt
|
||||
endif
|
||||
ifneq ($(HAS_NODE),)
|
||||
$(NPM) ci --no-audit --no-fund
|
||||
endif
|
||||
$(TOOLS)/bin/pre-commit install
|
||||
@echo "Setup fertig. Weiter mit: make quick"
|
||||
|
||||
quick: lint test ## Lint + Tests (Sekunden, nach jeder Änderung)
|
||||
|
||||
check: secrets lint test sast audit ## Alles vor dem Push: Secrets, Lint, Tests, SAST, Dependency-Audit
|
||||
@echo "make check: alles grün"
|
||||
|
||||
lint: ## Ruff (Python), ESLint + Typecheck (Node, falls als npm-Skript vorhanden)
|
||||
ifneq ($(HAS_PY),)
|
||||
cd $(PY_DIR) && .venv/bin/ruff check . && .venv/bin/ruff format --check .
|
||||
endif
|
||||
ifneq ($(HAS_NODE),)
|
||||
$(NPM) run lint --if-present
|
||||
$(NPM) run typecheck --if-present
|
||||
endif
|
||||
|
||||
test: ## Unit-, Integrations- und Sicherheitstests
|
||||
ifneq ($(HAS_PY),)
|
||||
cd $(PY_DIR) && .venv/bin/python -m pytest -q
|
||||
endif
|
||||
ifneq ($(HAS_NODE),)
|
||||
$(NPM) test
|
||||
endif
|
||||
|
||||
secrets: ## gitleaks über die Git-Historie
|
||||
docker run --rm -u $(UID_GID) -v "$(CURDIR)":/repo $(GITLEAKS_IMAGE) git /repo --redact --no-banner $(if $(wildcard .gitleaks.toml),-c /repo/.gitleaks.toml)
|
||||
|
||||
sast: ## Semgrep (eigene Regeln) + Bandit
|
||||
$(DOCKER) $(SEMGREP_IMAGE) semgrep scan --config $(SEMGREP_RULES) --error --metrics=off --quiet
|
||||
ifneq ($(HAS_PY),)
|
||||
$(VENV)/bin/bandit -q -r $(PY_DIR)/$(PY_SRC)
|
||||
endif
|
||||
|
||||
audit: ## Bekannte Lücken in Abhängigkeiten (pip-audit, npm audit)
|
||||
ifneq ($(HAS_PY),)
|
||||
$(VENV)/bin/pip-audit -r $(PY_DIR)/requirements.txt
|
||||
endif
|
||||
ifneq ($(HAS_NODE),)
|
||||
$(NPM) audit --audit-level=high
|
||||
endif
|
||||
|
||||
container: ## Image + Dockerfile/Compose scannen: make container IMAGE=name:tag
|
||||
@test -n "$(IMAGE)" || (echo "IMAGE=name:tag angeben" && exit 2)
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $(TRIVY_IMAGE) image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed $(IMAGE)
|
||||
$(DOCKER) $(TRIVY_IMAGE) config --severity HIGH,CRITICAL --exit-code 1 /src
|
||||
for f in $$(ls Dockerfile* 2>/dev/null); do docker run --rm -i $(HADOLINT_IMAGE) < $$f || exit 1; done
|
||||
|
||||
zap: ## ZAP-Baseline (bricht nur bei FAIL ab, ZAP_ARGS= für strikt): make zap TARGET=https://...
|
||||
@test -n "$(TARGET)" || (echo "TARGET=url angeben" && exit 2)
|
||||
mkdir -p reports
|
||||
docker run --rm --network host -u $(UID_GID) -v "$(CURDIR)/reports":/zap/wrk $(ZAP_IMAGE) zap-baseline.py -t $(TARGET) -r zap-baseline.html $(ZAP_ARGS)
|
||||
|
||||
fuzz: ## API-Fuzzing (5xx-Suche; FUZZ_CHECKS=all für volle Spec-Prüfung): make fuzz TARGET=http://...
|
||||
@test -n "$(TARGET)" || (echo "TARGET=url angeben" && exit 2)
|
||||
docker run --rm --network host $(SCHEMATHESIS_IMAGE) run $(TARGET)$(OPENAPI_PATH) --checks $(FUZZ_CHECKS) $(FUZZ_ARGS)
|
||||
|
||||
mutation: ## Sicherheits-Mutationen: jede muss einen Test rot machen
|
||||
python3 $(SCRIPTS)/mutation_check.py $(MUTATIONS)
|
||||
|
||||
mutmut: ## Mutation-Testing des ganzen Python-Codes (langsam)
|
||||
cd $(PY_DIR) && .venv/bin/mutmut run && .venv/bin/mutmut results
|
||||
|
||||
vet-deps: ## Neue Pakete prüfen: make vet-deps PKGS="pypi:name npm:name"
|
||||
@test -n "$(PKGS)" || (echo 'PKGS="pypi:name npm:name" angeben' && exit 2)
|
||||
python3 $(SCRIPTS)/vet_deps.py $(PKGS)
|
||||
Loading…
Add table
Add a link
Reference in a new issue