security: harden secret hygiene and pre-commit scanning

This commit is contained in:
2026-02-08 10:27:23 +03:00
parent f609d2ce35
commit 0dbfe45353
5 changed files with 84 additions and 4 deletions

5
.githooks/pre-commit Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(git rev-parse --show-toplevel)"
"$repo_root/scripts/check-secrets.sh"

11
.gitignore vendored
View File

@@ -1,5 +1,16 @@
# QuoteForge
config.yaml
.env
.env.*
*.pem
*.key
*.p12
*.pfx
*.crt
id_rsa
id_rsa.*
secrets.yaml
secrets.yml
# Local SQLite database (contains encrypted credentials)
/data/*.db

View File

@@ -1,4 +1,4 @@
.PHONY: build build-release clean test run version
.PHONY: build build-release clean test run version install-hooks
# Get version from git
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
@@ -72,6 +72,12 @@ deps:
go mod download
go mod tidy
# Install local git hooks
install-hooks:
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit scripts/check-secrets.sh
@echo "Installed git hooks from .githooks/"
# Help
help:
@echo "QuoteForge Server (qfs) - Build Commands"
@@ -92,6 +98,7 @@ help:
@echo " run Run development server"
@echo " watch Run with auto-restart (requires entr)"
@echo " deps Install/update dependencies"
@echo " install-hooks Install local git hooks (secret scan on commit)"
@echo " help Show this help"
@echo ""
@echo "Current version: $(VERSION)"

View File

@@ -111,10 +111,10 @@ go run ./cmd/migrate_ops_projects -apply -yes
```sql
-- 1) Создать пользователя (если его ещё нет)
CREATE USER IF NOT EXISTS 'quote_user'@'%' IDENTIFIED BY 'DB_PASSWORD_PLACEHOLDER';
CREATE USER IF NOT EXISTS 'quote_user'@'%' IDENTIFIED BY '<DB_PASSWORD>';
-- 2) Если пользователь уже существовал, принудительно обновить пароль
ALTER USER 'quote_user'@'%' IDENTIFIED BY 'DB_PASSWORD_PLACEHOLDER';
ALTER USER 'quote_user'@'%' IDENTIFIED BY '<DB_PASSWORD>';
-- 3) (Опционально, но рекомендуется) удалить дубли пользователя с другими host,
-- чтобы не возникало конфликтов вида user@localhost vs user@'%'
@@ -144,7 +144,7 @@ SHOW CREATE USER 'quote_user'@'%';
Полный набор прав для пользователя квотаций:
```sql
GRANT USAGE ON *.* TO 'quote_user'@'%' IDENTIFIED BY 'DB_PASSWORD_PLACEHOLDER';
GRANT USAGE ON *.* TO 'quote_user'@'%' IDENTIFIED BY '<DB_PASSWORD>';
GRANT SELECT ON RFQ_LOG.lot TO 'quote_user'@'%';
GRANT SELECT ON RFQ_LOG.qt_lot_metadata TO 'quote_user'@'%';
GRANT SELECT ON RFQ_LOG.qt_categories TO 'quote_user'@'%';
@@ -187,6 +187,7 @@ make build-all # Сборка для всех платформ (Linux, mac
make build-windows # Только для Windows
make run # Запуск dev сервера
make test # Запуск тестов
make install-hooks # Установить git hooks (блокировка коммита с секретами)
make clean # Очистка bin/
make help # Показать все команды
```

56
scripts/check-secrets.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -euo pipefail
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Not inside a git repository."
exit 1
fi
if ! command -v rg >/dev/null 2>&1; then
echo "ripgrep (rg) is required for secret scanning."
exit 1
fi
staged_files=()
while IFS= read -r file; do
staged_files+=("$file")
done < <(git diff --cached --name-only --diff-filter=ACMRTUXB)
if [ "${#staged_files[@]}" -eq 0 ]; then
exit 0
fi
secret_pattern='AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}|AIza[0-9A-Za-z_-]{35}|-----BEGIN (RSA|OPENSSH|EC|DSA|PRIVATE) KEY-----|(?i)(password|passwd|pwd|secret|token|api[_-]?key|jwt_secret)\s*[:=]\s*["'"'"'][^"'"'"'\s]{8,}["'"'"']'
allow_pattern='CHANGE_ME|REDACTED|PLACEHOLDER|EXAMPLE|example|<[^>]+>'
found=0
for file in "${staged_files[@]}"; do
case "$file" in
dist/*|*.png|*.jpg|*.jpeg|*.gif|*.webp|*.pdf|*.zip|*.gz|*.exe|*.dll|*.so|*.dylib)
continue
;;
esac
if ! content="$(git show ":$file" 2>/dev/null)"; then
continue
fi
hits="$(printf '%s' "$content" | rg -n --no-heading -e "$secret_pattern" || true)"
if [ -n "$hits" ]; then
filtered="$(printf '%s\n' "$hits" | rg -v -e "$allow_pattern" || true)"
if [ -n "$filtered" ]; then
echo "Potential secret found in staged file: $file"
printf '%s\n' "$filtered"
found=1
fi
fi
done
if [ "$found" -ne 0 ]; then
echo
echo "Commit blocked: remove or redact secrets before committing."
exit 1
fi
exit 0