7c75133ef1
Universal: Auto Version Bump / Version Bump (push) Successful in 13s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Successful in 12s
Generic: Project CI / Lint & Validate (pull_request) Successful in 37s
Universal: PR Check / Secret Scan (pull_request) Successful in 1m20s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Implements the code analysis scanner module that detects insecure patterns across Go, PHP, Python, JavaScript, and TypeScript: - SQL injection (CWE-89): string concat in queries across 4 languages - XSS (CWE-79): innerHTML, document.write, unescaped output, dangerouslySetInnerHTML - Command injection (CWE-78): exec with variables, shell=True, os.system - Path traversal (CWE-22): unsanitized path joins, file open with user input - Insecure deserialization (CWE-502): unserialize(), yaml.load() - Hardcoded credentials (CWE-798): password assignments in source - Weak cryptography (CWE-327): MD5/SHA-1 usage 22 rules total, language-filtered by file extension. Wired into the existing scanner orchestrator via the CodeScanner config toggle. API updated to expose code_scanner in GET/PATCH security config. Claude-Session: https://claude.ai/code/session_011AAFzotGMf3ayvXhEmStCd
100 lines
2.7 KiB
Go
100 lines
2.7 KiB
Go
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package security
|
|
|
|
import (
|
|
"context"
|
|
|
|
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
|
|
security_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/security"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
|
|
)
|
|
|
|
// ScanPushForSecrets checks a commit for secrets and returns findings.
|
|
// Used by the pre-receive hook to block pushes containing secrets.
|
|
func ScanPushForSecrets(ctx context.Context, repoID int64, commit *git.Commit) []Finding {
|
|
cfg, err := security_model.GetScannerConfig(ctx, repoID)
|
|
if err != nil {
|
|
log.Error("ScanPushForSecrets: GetScannerConfig: %v", err)
|
|
return nil
|
|
}
|
|
if !cfg.Enabled || !cfg.BlockOnPush || !cfg.SecretScanner {
|
|
return nil
|
|
}
|
|
|
|
scanner := NewSecretScanner()
|
|
findings, err := scanner.ScanCommit(commit)
|
|
if err != nil {
|
|
log.Error("ScanPushForSecrets: ScanCommit: %v", err)
|
|
return nil
|
|
}
|
|
return findings
|
|
}
|
|
|
|
// ScanOnPush runs enabled scanners against a commit pushed to the default branch.
|
|
// Called from services/repository/push.go on default branch pushes.
|
|
func ScanOnPush(ctx context.Context, repo *repo_model.Repository, commit *git.Commit) {
|
|
if commit == nil {
|
|
return
|
|
}
|
|
|
|
cfg, err := security_model.GetScannerConfig(ctx, repo.ID)
|
|
if err != nil {
|
|
log.Error("SecurityScan: GetScannerConfig for %s: %v", repo.FullName(), err)
|
|
return
|
|
}
|
|
if !cfg.Enabled {
|
|
return
|
|
}
|
|
|
|
var scanners []Scanner
|
|
if cfg.SecretScanner {
|
|
scanners = append(scanners, NewSecretScanner())
|
|
}
|
|
if cfg.DependScanner {
|
|
scanners = append(scanners, NewDependencyScanner())
|
|
}
|
|
if cfg.CodeScanner {
|
|
scanners = append(scanners, NewCodeScanner())
|
|
}
|
|
|
|
if len(scanners) == 0 {
|
|
return
|
|
}
|
|
|
|
totalFindings := 0
|
|
for _, s := range scanners {
|
|
findings, err := s.ScanTree(commit)
|
|
if err != nil {
|
|
log.Error("SecurityScan: %s scanner for %s: %v", s.Type(), repo.FullName(), err)
|
|
continue
|
|
}
|
|
|
|
for _, f := range findings {
|
|
alert := &security_model.SecurityAlert{
|
|
RepoID: repo.ID,
|
|
Scanner: f.Scanner,
|
|
Severity: f.Severity,
|
|
RuleID: f.RuleID,
|
|
Title: f.Title,
|
|
Description: f.Description,
|
|
FilePath: f.FilePath,
|
|
LineNumber: f.LineNumber,
|
|
CommitSHA: f.CommitSHA,
|
|
Fingerprint: f.Fingerprint,
|
|
Metadata: f.Metadata,
|
|
}
|
|
if err := security_model.CreateOrUpdateAlert(ctx, alert); err != nil {
|
|
log.Error("SecurityScan: CreateOrUpdateAlert: %v", err)
|
|
}
|
|
totalFindings++
|
|
}
|
|
}
|
|
|
|
if totalFindings > 0 {
|
|
log.Warn("SecurityScan: %d findings in %s", totalFindings, repo.FullName())
|
|
}
|
|
}
|