← back to julianshen__rubichan

Function bodies 513 total

All specs Real LLM only Function bodies
output.severityToLevel function · go · L107-L116 (10 LOC)
internal/security/output/sarif.go
func severityToLevel(s security.Severity) string {
	switch s {
	case security.SeverityCritical, security.SeverityHigh:
		return "error"
	case security.SeverityMedium:
		return "warning"
	default:
		return "note"
	}
}
output.buildRules function · go · L119-L135 (17 LOC)
internal/security/output/sarif.go
func buildRules(findings []security.Finding) []sarifRule {
	seen := make(map[string]bool)
	var rules []sarifRule

	for _, f := range findings {
		if f.CWE == "" || seen[f.CWE] {
			continue
		}
		seen[f.CWE] = true
		rules = append(rules, sarifRule{
			ID:               f.CWE,
			ShortDescription: sarifMessageStr{Text: f.Title},
		})
	}

	return rules
}
output.buildResults function · go · L138-L162 (25 LOC)
internal/security/output/sarif.go
func buildResults(findings []security.Finding) []sarifResult {
	results := make([]sarifResult, 0, len(findings))

	for _, f := range findings {
		result := sarifResult{
			RuleID:  f.CWE,
			Level:   severityToLevel(f.Severity),
			Message: sarifMessageStr{Text: f.Title},
			Locations: []sarifLocation{
				{
					PhysicalLocation: sarifPhysicalLocation{
						ArtifactLocation: sarifArtifactLocation{URI: f.Location.File},
						Region: sarifRegion{
							StartLine: f.Location.StartLine,
							EndLine:   f.Location.EndLine,
						},
					},
				},
			},
		}
		results = append(results, result)
	}

	return results
}
output.WikiFormatter.Format method · go · L32-L40 (9 LOC)
internal/security/output/wiki.go
func (f *WikiFormatter) Format(report *security.Report) ([]byte, error) {
	wiki := WikiOutput{
		Overview:     buildOverviewPage(report),
		Findings:     buildFindingsPage(report),
		AttackChains: buildAttackChainsPage(report),
	}

	return json.MarshalIndent(wiki, "", "  ")
}
output.buildOverviewPage function · go · L43-L67 (25 LOC)
internal/security/output/wiki.go
func buildOverviewPage(report *security.Report) string {
	summary := report.Summary()

	var b strings.Builder
	b.WriteString("# Security Overview\n\n")
	b.WriteString("## Scan Statistics\n\n")
	b.WriteString(fmt.Sprintf("- **Duration:** %dms\n", report.Stats.Duration.Milliseconds()))
	b.WriteString(fmt.Sprintf("- **Files scanned:** %d\n", report.Stats.FilesScanned))
	b.WriteString(fmt.Sprintf("- **Chunks analyzed:** %d\n", report.Stats.ChunksAnalyzed))
	b.WriteString("\n")

	b.WriteString("## Findings Summary\n\n")
	b.WriteString("| Severity | Count |\n")
	b.WriteString("|----------|-------|\n")
	b.WriteString(fmt.Sprintf("| Critical | %d |\n", summary.Critical))
	b.WriteString(fmt.Sprintf("| High | %d |\n", summary.High))
	b.WriteString(fmt.Sprintf("| Medium | %d |\n", summary.Medium))
	b.WriteString(fmt.Sprintf("| Low | %d |\n", summary.Low))
	b.WriteString(fmt.Sprintf("| Info | %d |\n", summary.Info))
	b.WriteString(fmt.Sprintf("| **Total** | **%d** |\n", summary.Total))
	b.WriteStr
output.buildFindingsPage function · go · L70-L119 (50 LOC)
internal/security/output/wiki.go
func buildFindingsPage(report *security.Report) string {
	var b strings.Builder
	b.WriteString("# Security Findings\n\n")

	if len(report.Findings) == 0 {
		b.WriteString("No findings detected.\n")
		return b.String()
	}

	// Group by category
	byCategory := make(map[security.Category][]security.Finding)
	var categoryOrder []security.Category
	for _, f := range report.Findings {
		if _, exists := byCategory[f.Category]; !exists {
			categoryOrder = append(categoryOrder, f.Category)
		}
		byCategory[f.Category] = append(byCategory[f.Category], f)
	}

	for _, cat := range categoryOrder {
		findings := byCategory[cat]
		b.WriteString(fmt.Sprintf("## %s\n\n", string(cat)))

		for _, f := range findings {
			b.WriteString(fmt.Sprintf("### [%s] %s\n\n", f.ID, f.Title))
			b.WriteString(fmt.Sprintf("- **Severity:** %s\n", string(f.Severity)))
			b.WriteString(fmt.Sprintf("- **Confidence:** %s\n", string(f.Confidence)))
			loc := fmt.Sprintf("%s:%d", f.Location.File, f.Location.StartLine)
			i
output.buildAttackChainsPage function · go · L122-L151 (30 LOC)
internal/security/output/wiki.go
func buildAttackChainsPage(report *security.Report) string {
	var b strings.Builder
	b.WriteString("# Attack Chains\n\n")

	if len(report.AttackChains) == 0 {
		b.WriteString("No attack chains detected.\n")
		return b.String()
	}

	for _, chain := range report.AttackChains {
		b.WriteString(fmt.Sprintf("## [%s] %s\n\n", chain.ID, chain.Title))
		b.WriteString(fmt.Sprintf("- **Severity:** %s\n", string(chain.Severity)))
		if chain.Impact != "" {
			b.WriteString(fmt.Sprintf("- **Impact:** %s\n", chain.Impact))
		}
		if chain.Likelihood != "" {
			b.WriteString(fmt.Sprintf("- **Likelihood:** %s\n", chain.Likelihood))
		}

		if len(chain.Steps) > 0 {
			b.WriteString("\n### Steps\n\n")
			for i, step := range chain.Steps {
				b.WriteString(fmt.Sprintf("%d. [%s] %s\n", i+1, step.ID, step.Title))
			}
		}
		b.WriteString("\n")
	}

	return b.String()
}
Repobility · code-quality intelligence · https://repobility.com
security.Prioritizer.Prioritize method · go · L59-L102 (44 LOC)
internal/security/prioritizer.go
func (p *Prioritizer) Prioritize(ctx context.Context, target ScanTarget, staticFindings []Finding) ([]AnalysisChunk, error) {
	if err := ctx.Err(); err != nil {
		return nil, fmt.Errorf("prioritizer cancelled: %w", err)
	}

	files, err := CollectFiles(target, nil)
	if err != nil {
		return nil, fmt.Errorf("collecting files: %w", err)
	}

	flaggedFiles := buildFlaggedFileSet(staticFindings)
	codeParser := parser.NewParser()

	var chunks []AnalysisChunk
	for _, relPath := range files {
		if err := ctx.Err(); err != nil {
			return nil, fmt.Errorf("prioritizer cancelled: %w", err)
		}

		absPath := filepath.Join(target.RootDir, relPath)
		data, err := os.ReadFile(absPath)
		if err != nil {
			continue // skip unreadable files
		}

		score := p.scoreFile(string(data))
		if flaggedFiles[relPath] {
			score += staticFindingBoost
		}

		language := extensionToLanguage(relPath)
		fileChunks := p.splitIntoChunks(codeParser, relPath, data, score, language)
		chunks = append(chunks, fileChunks...
security.Prioritizer.scoreFile method · go · L105-L113 (9 LOC)
internal/security/prioritizer.go
func (p *Prioritizer) scoreFile(content string) int {
	score := 0
	for _, signal := range riskSignals {
		if signal.pattern.MatchString(content) {
			score += signal.score
		}
	}
	return score
}
security.Prioritizer.splitIntoChunks method · go · L117-L152 (36 LOC)
internal/security/prioritizer.go
func (p *Prioritizer) splitIntoChunks(codeParser *parser.Parser, relPath string, data []byte, score int, language string) []AnalysisChunk {
	tree, err := codeParser.Parse(relPath, data)
	if err != nil {
		return []AnalysisChunk{p.wholeFileChunk(relPath, data, score, language)}
	}
	defer tree.Close()

	funcs := tree.Functions()
	if len(funcs) == 0 {
		return []AnalysisChunk{p.wholeFileChunk(relPath, data, score, language)}
	}

	lines := strings.Split(string(data), "\n")
	var chunks []AnalysisChunk
	for _, fn := range funcs {
		start := fn.StartLine
		end := fn.EndLine
		if start < 1 {
			start = 1
		}
		if end > len(lines) {
			end = len(lines)
		}

		content := strings.Join(lines[start-1:end], "\n")
		chunks = append(chunks, AnalysisChunk{
			File:      relPath,
			StartLine: start,
			EndLine:   end,
			Content:   content,
			Language:  language,
			RiskScore: score,
		})
	}
	return chunks
}
security.Prioritizer.wholeFileChunk method · go · L155-L165 (11 LOC)
internal/security/prioritizer.go
func (p *Prioritizer) wholeFileChunk(relPath string, data []byte, score int, language string) AnalysisChunk {
	lineCount := strings.Count(string(data), "\n") + 1
	return AnalysisChunk{
		File:      relPath,
		StartLine: 1,
		EndLine:   lineCount,
		Content:   string(data),
		Language:  language,
		RiskScore: score,
	}
}
security.Prioritizer.filterByMinScore method · go · L168-L179 (12 LOC)
internal/security/prioritizer.go
func (p *Prioritizer) filterByMinScore(chunks []AnalysisChunk) []AnalysisChunk {
	if p.config.MinRiskScore <= 0 {
		return chunks
	}
	var filtered []AnalysisChunk
	for _, c := range chunks {
		if c.RiskScore >= p.config.MinRiskScore {
			filtered = append(filtered, c)
		}
	}
	return filtered
}
security.Prioritizer.capChunks method · go · L182-L187 (6 LOC)
internal/security/prioritizer.go
func (p *Prioritizer) capChunks(chunks []AnalysisChunk) []AnalysisChunk {
	if p.config.MaxChunks > 0 && len(chunks) > p.config.MaxChunks {
		return chunks[:p.config.MaxChunks]
	}
	return chunks
}
security.buildFlaggedFileSet function · go · L190-L198 (9 LOC)
internal/security/prioritizer.go
func buildFlaggedFileSet(findings []Finding) map[string]bool {
	flagged := make(map[string]bool, len(findings))
	for _, f := range findings {
		if f.Location.File != "" {
			flagged[f.Location.File] = true
		}
	}
	return flagged
}
security.extensionToLanguage function · go · L201-L229 (29 LOC)
internal/security/prioritizer.go
func extensionToLanguage(path string) string {
	ext := filepath.Ext(path)
	switch ext {
	case ".go":
		return "go"
	case ".py":
		return "python"
	case ".js":
		return "javascript"
	case ".ts":
		return "typescript"
	case ".tsx":
		return "typescript"
	case ".jsx":
		return "javascript"
	case ".java":
		return "java"
	case ".rs":
		return "rust"
	case ".rb":
		return "ruby"
	case ".c", ".h":
		return "c"
	case ".cc", ".cpp":
		return "cpp"
	default:
		return ""
	}
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
security.LoadProjectConfig function · go · L42-L76 (35 LOC)
internal/security/projectconfig.go
func LoadProjectConfig(dir string) (*ProjectSecurityConfig, error) {
	data, err := os.ReadFile(filepath.Join(dir, ".security.yaml"))
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("reading .security.yaml: %w", err)
	}

	if strings.TrimSpace(string(data)) == "" {
		return nil, nil
	}

	var cfg ProjectSecurityConfig
	if err := yaml.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("parsing .security.yaml: %w", err)
	}

	// Validate severity strings against known values.
	for i, r := range cfg.Rules {
		if r.Severity != "" && SeverityRank(Severity(r.Severity)) == 0 {
			return nil, fmt.Errorf(".security.yaml: rule %q has invalid severity %q (must be critical, high, medium, low, or info)", r.ID, r.Severity)
		}
		if r.ID == "" {
			return nil, fmt.Errorf(".security.yaml: rule at index %d is missing required id field", i)
		}
	}
	for _, o := range cfg.Overrides {
		if o.Severity != "" && SeverityRank(Severity(o.Severity)) == 0 {
			retu
security.ApplyOverrides function · go · L80-L97 (18 LOC)
internal/security/projectconfig.go
func ApplyOverrides(findings []Finding, overrides []Override) int {
	if len(findings) == 0 || len(overrides) == 0 {
		return 0
	}
	overrideMap := make(map[string]Override, len(overrides))
	for _, o := range overrides {
		overrideMap[o.FindingID] = o
	}

	count := 0
	for i := range findings {
		if o, ok := overrideMap[findings[i].ID]; ok {
			findings[i].Severity = Severity(o.Severity)
			count++
		}
	}
	return count
}
scanner.AppleScanner.Scan method · go · L35-L95 (61 LOC)
internal/security/scanner/apple.go
func (s *AppleScanner) Scan(ctx context.Context, target security.ScanTarget) ([]security.Finding, error) {
	if err := ctx.Err(); err != nil {
		return nil, fmt.Errorf("apple scanner cancelled: %w", err)
	}

	files, err := s.collectFiles(target)
	if err != nil {
		return nil, fmt.Errorf("collecting files: %w", err)
	}

	var findings []security.Finding

	var plistFiles []string
	var entitlementFiles []string
	var swiftFiles []string

	for _, relPath := range files {
		base := filepath.Base(relPath)
		ext := filepath.Ext(relPath)

		switch {
		case base == "Info.plist" || strings.HasSuffix(relPath, "Info.plist"):
			plistFiles = append(plistFiles, relPath)
		case ext == ".entitlements":
			entitlementFiles = append(entitlementFiles, relPath)
		case ext == ".swift":
			swiftFiles = append(swiftFiles, relPath)
		}
	}

	// No Apple files found at all: return empty.
	if len(plistFiles) == 0 && len(entitlementFiles) == 0 && len(swiftFiles) == 0 {
		return nil, nil
	}

	for _, relPath := range 
scanner.AppleScanner.checkPlist method · go · L111-L139 (29 LOC)
internal/security/scanner/apple.go
func (s *AppleScanner) checkPlist(absPath, relPath string) []security.Finding {
	data, err := os.ReadFile(absPath)
	if err != nil {
		return nil
	}

	dict, err := parsePlistXML(data)
	if err != nil {
		return nil
	}

	var findings []security.Finding

	// Check for ATS bypass: NSAllowsArbitraryLoads = true
	for i, key := range dict.Keys {
		if key == "NSAllowsArbitraryLoads" && i < len(dict.Values) && dict.Values[i] == "true" {
			findings = append(findings, s.newFinding(
				"App Transport Security bypass enabled",
				"NSAllowsArbitraryLoads is set to true, which disables ATS and allows insecure HTTP connections",
				security.SeverityHigh,
				security.CategoryMisconfiguration,
				"",
				relPath,
			))
		}
	}

	return findings
}
scanner.parsePlistXML function · go · L143-L211 (69 LOC)
internal/security/scanner/apple.go
func parsePlistXML(data []byte) (*plistDict, error) {
	decoder := xml.NewDecoder(strings.NewReader(string(data)))
	decoder.Strict = false

	dict := &plistDict{}
	var inDict bool
	var expectValue bool
	var currentKey string

	for {
		tok, err := decoder.Token()
		if err != nil {
			break
		}

		switch t := tok.(type) {
		case xml.StartElement:
			switch t.Name.Local {
			case "dict":
				inDict = true
			case "key":
				if inDict {
					var key string
					if err := decoder.DecodeElement(&key, &t); err == nil {
						currentKey = key
						expectValue = true
					}
				}
			case "true":
				if expectValue {
					dict.Keys = append(dict.Keys, currentKey)
					dict.Values = append(dict.Values, "true")
					expectValue = false
				}
			case "false":
				if expectValue {
					dict.Keys = append(dict.Keys, currentKey)
					dict.Values = append(dict.Values, "false")
					expectValue = false
				}
			case "string":
				if expectValue {
					var val string
					if err := decoder.DecodeElement(&
scanner.AppleScanner.checkEntitlements method · go · L230-L260 (31 LOC)
internal/security/scanner/apple.go
func (s *AppleScanner) checkEntitlements(absPath, relPath string) []security.Finding {
	data, err := os.ReadFile(absPath)
	if err != nil {
		return nil
	}

	dict, err := parsePlistXML(data)
	if err != nil {
		return nil
	}

	var findings []security.Finding
	for i, key := range dict.Keys {
		ent, ok := dangerousEntitlements[key]
		if !ok {
			continue
		}
		if i < len(dict.Values) && dict.Values[i] == "true" {
			findings = append(findings, s.newFinding(
				ent.title,
				fmt.Sprintf("Entitlement %s is enabled", key),
				ent.severity,
				security.CategoryMisconfiguration,
				"",
				relPath,
			))
		}
	}

	return findings
}
scanner.AppleScanner.checkSwiftFile method · go · L268-L289 (22 LOC)
internal/security/scanner/apple.go
func (s *AppleScanner) checkSwiftFile(absPath, relPath string) []security.Finding {
	data, err := os.ReadFile(absPath)
	if err != nil {
		return nil
	}

	var findings []security.Finding
	content := string(data)

	if userDefaultsSensitivePat.MatchString(content) {
		findings = append(findings, s.newFinding(
			"Sensitive data stored in UserDefaults",
			"UserDefaults is not encrypted; use Keychain for sensitive data like passwords and tokens",
			security.SeverityMedium,
			security.CategoryDataExposure,
			"",
			relPath,
		))
	}

	return findings
}
scanner.AppleScanner.newFinding method · go · L293-L312 (20 LOC)
internal/security/scanner/apple.go
func (s *AppleScanner) newFinding(title, description string, severity security.Severity, category security.Category, cwe, file string) security.Finding {
	s.mu.Lock()
	s.findingCounter++
	id := fmt.Sprintf("APPLE-%04d", s.findingCounter)
	s.mu.Unlock()

	return security.Finding{
		ID:          id,
		Scanner:     "apple-platform",
		Severity:    severity,
		Category:    category,
		Title:       title,
		Description: description,
		Location: security.Location{
			File: file,
		},
		CWE:        cwe,
		Confidence: security.ConfidenceHigh,
	}
}
Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
scanner.ConfigScanner.Scan method · go · L35-L57 (23 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) Scan(ctx context.Context, target security.ScanTarget) ([]security.Finding, error) {
	if err := ctx.Err(); err != nil {
		return nil, fmt.Errorf("config scanner cancelled: %w", err)
	}

	files, err := security.CollectFiles(target, nil)
	if err != nil {
		return nil, fmt.Errorf("collecting files: %w", err)
	}

	var findings []security.Finding
	for _, relPath := range files {
		if err := ctx.Err(); err != nil {
			return nil, fmt.Errorf("config scanner cancelled: %w", err)
		}

		absPath := filepath.Join(target.RootDir, relPath)
		fileFindings := s.scanFile(absPath, relPath)
		findings = append(findings, fileFindings...)
	}

	return findings, nil
}
scanner.ConfigScanner.scanFile method · go · L60-L91 (32 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) scanFile(absPath, relPath string) []security.Finding {
	data, err := os.ReadFile(absPath)
	if err != nil {
		return nil
	}

	var findings []security.Finding

	baseName := filepath.Base(relPath)

	// Dockerfile checks
	if strings.HasPrefix(baseName, "Dockerfile") {
		findings = append(findings, s.checkDockerfile(data, relPath)...)
	}

	// Kubernetes YAML checks
	if isKubernetesYAML(data, relPath) {
		findings = append(findings, s.checkKubernetes(data, relPath)...)
	}

	// CI config checks
	if isCIConfig(relPath) {
		findings = append(findings, s.checkCIConfig(data, relPath)...)
	}

	// General config checks (YAML, TOML, env, JSON, properties, INI)
	if isConfigFile(relPath) {
		findings = append(findings, s.checkGeneralConfig(data, relPath)...)
	}

	return findings
}
scanner.ConfigScanner.checkDockerfile method · go · L101-L142 (42 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) checkDockerfile(data []byte, relPath string) []security.Finding {
	var findings []security.Finding
	content := string(data)

	// Check for USER root
	if dockerUserRootPat.MatchString(content) {
		line := findLineNumber(content, dockerUserRootPat)
		findings = append(findings, s.newFinding(
			"Container runs as root user",
			"Dockerfile explicitly sets USER root, which violates least privilege",
			security.SeverityMedium,
			security.CategoryMisconfiguration,
			"CWE-250",
			relPath, line,
		))
	} else if !dockerUserPat.MatchString(content) {
		// No USER directive at all
		findings = append(findings, s.newFinding(
			"Container runs as root user",
			"Dockerfile has no USER directive; container will run as root by default",
			security.SeverityMedium,
			security.CategoryMisconfiguration,
			"CWE-250",
			relPath, 1,
		))
	}

	// Check for ADD with URL
	if dockerAddURLPat.MatchString(content) {
		line := findLineNumber(content, dockerAddURLPat)
		findings = 
scanner.isKubernetesYAML function · go · L153-L160 (8 LOC)
internal/security/scanner/config.go
func isKubernetesYAML(data []byte, relPath string) bool {
	ext := filepath.Ext(relPath)
	if ext != ".yaml" && ext != ".yml" {
		return false
	}
	content := string(data)
	return strings.Contains(content, "apiVersion:") || strings.Contains(content, "kind:")
}
scanner.ConfigScanner.checkKubernetes method · go · L162-L215 (54 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) checkKubernetes(data []byte, relPath string) []security.Finding {
	var findings []security.Finding
	content := string(data)

	if k8sPrivilegedPat.MatchString(content) {
		line := findLineNumber(content, k8sPrivilegedPat)
		findings = append(findings, s.newFinding(
			"Kubernetes container running in privileged mode",
			"privileged: true grants the container nearly all host capabilities",
			security.SeverityHigh,
			security.CategoryMisconfiguration,
			"CWE-250",
			relPath, line,
		))
	}

	if k8sHostNetworkPat.MatchString(content) {
		line := findLineNumber(content, k8sHostNetworkPat)
		findings = append(findings, s.newFinding(
			"Kubernetes pod uses host network",
			"hostNetwork: true exposes the pod to the host network stack",
			security.SeverityMedium,
			security.CategoryMisconfiguration,
			"",
			relPath, line,
		))
	}

	if k8sHostPIDPat.MatchString(content) {
		line := findLineNumber(content, k8sHostPIDPat)
		findings = append(findings, s.newFinding
scanner.isCIConfig function · go · L225-L237 (13 LOC)
internal/security/scanner/config.go
func isCIConfig(relPath string) bool {
	normalized := filepath.ToSlash(relPath)
	if strings.HasPrefix(normalized, ".github/workflows/") && strings.HasSuffix(normalized, ".yml") {
		return true
	}
	if normalized == ".gitlab-ci.yml" {
		return true
	}
	if normalized == ".circleci/config.yml" {
		return true
	}
	return false
}
scanner.ConfigScanner.checkCIConfig method · go · L239-L265 (27 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) checkCIConfig(data []byte, relPath string) []security.Finding {
	var findings []security.Finding

	scanner := bufio.NewScanner(bytes.NewReader(data))
	lineNum := 0
	for scanner.Scan() {
		lineNum++
		line := scanner.Text()

		if ciSecretPat.MatchString(line) {
			// Extract the value part to check if it's a variable reference.
			value := extractConfigValue(line)
			if value != "" && !ciSecretExcludePat.MatchString(value) {
				findings = append(findings, s.newFinding(
					"Potential secret in CI configuration",
					fmt.Sprintf("Plain text secret/token/password found in CI config at line %d", lineNum),
					security.SeverityHigh,
					security.CategorySecretsExposure,
					"CWE-798",
					relPath, lineNum,
				))
			}
		}
	}

	return findings
}
scanner.extractConfigValue function · go · L268-L286 (19 LOC)
internal/security/scanner/config.go
func extractConfigValue(line string) string {
	line = strings.TrimSpace(line)

	// Try key: value
	if idx := strings.Index(line, ":"); idx >= 0 {
		val := strings.TrimSpace(line[idx+1:])
		val = strings.Trim(val, "\"'")
		return val
	}

	// Try key=value
	if idx := strings.Index(line, "="); idx >= 0 {
		val := strings.TrimSpace(line[idx+1:])
		val = strings.Trim(val, "\"'")
		return val
	}

	return ""
}
About: code-quality intelligence by Repobility · https://repobility.com
scanner.isConfigFile function · go · L295-L306 (12 LOC)
internal/security/scanner/config.go
func isConfigFile(relPath string) bool {
	ext := filepath.Ext(relPath)
	switch ext {
	case ".yaml", ".yml", ".toml", ".json", ".env", ".ini", ".conf", ".cfg", ".properties":
		return true
	}
	baseName := filepath.Base(relPath)
	if strings.HasPrefix(baseName, ".env") {
		return true
	}
	return false
}
scanner.ConfigScanner.checkGeneralConfig method · go · L308-L337 (30 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) checkGeneralConfig(data []byte, relPath string) []security.Finding {
	var findings []security.Finding
	content := string(data)

	if debugModePat.MatchString(content) {
		line := findLineNumber(content, debugModePat)
		findings = append(findings, s.newFinding(
			"Debug mode enabled in configuration",
			"Debug mode may expose sensitive information in production",
			security.SeverityLow,
			security.CategoryMisconfiguration,
			"",
			relPath, line,
		))
	}

	if permissiveCORS.MatchString(content) {
		line := findLineNumber(content, permissiveCORS)
		findings = append(findings, s.newFinding(
			"Permissive CORS configuration",
			"Access-Control-Allow-Origin: * allows any domain to make requests",
			security.SeverityMedium,
			security.CategoryMisconfiguration,
			"",
			relPath, line,
		))
	}

	return findings
}
scanner.findLineNumber function · go · L342-L348 (7 LOC)
internal/security/scanner/config.go
func findLineNumber(content string, pat *regexp.Regexp) int {
	loc := pat.FindStringIndex(content)
	if loc == nil {
		return 1
	}
	return strings.Count(content[:loc[0]], "\n") + 1
}
scanner.ConfigScanner.newFinding method · go · L350-L371 (22 LOC)
internal/security/scanner/config.go
func (s *ConfigScanner) newFinding(title, description string, severity security.Severity, category security.Category, cwe, file string, line int) security.Finding {
	s.mu.Lock()
	s.findingCounter++
	id := fmt.Sprintf("CFG-%04d", s.findingCounter)
	s.mu.Unlock()

	return security.Finding{
		ID:          id,
		Scanner:     "config",
		Severity:    severity,
		Category:    category,
		Title:       title,
		Description: description,
		Location: security.Location{
			File:      file,
			StartLine: line,
			EndLine:   line,
		},
		CWE:        cwe,
		Confidence: security.ConfidenceHigh,
	}
}
scanner.NewCustomRuleScanner function · go · L28-L38 (11 LOC)
internal/security/scanner/custom.go
func NewCustomRuleScanner(rules []security.CustomRule) *CustomRuleScanner {
	var compiled []compiledCustomRule
	for _, r := range rules {
		re, err := regexp.Compile(r.Pattern)
		if err != nil {
			continue
		}
		compiled = append(compiled, compiledCustomRule{rule: r, re: re})
	}
	return &CustomRuleScanner{rules: compiled}
}
scanner.CustomRuleScanner.Scan method · go · L44-L68 (25 LOC)
internal/security/scanner/custom.go
func (s *CustomRuleScanner) Scan(ctx context.Context, target security.ScanTarget) ([]security.Finding, error) {
	if len(s.rules) == 0 {
		return nil, nil
	}

	files, err := security.CollectFiles(target, nil)
	if err != nil {
		return nil, fmt.Errorf("collecting files: %w", err)
	}

	var findings []security.Finding
	for _, relPath := range files {
		if ctx.Err() != nil {
			return findings, ctx.Err()
		}

		absPath := filepath.Join(target.RootDir, relPath)
		fileFindings, scanErr := s.scanFile(absPath, relPath)
		if scanErr != nil {
			continue
		}
		findings = append(findings, fileFindings...)
	}
	return findings, nil
}
scanner.CustomRuleScanner.scanFile method · go · L70-L103 (34 LOC)
internal/security/scanner/custom.go
func (s *CustomRuleScanner) scanFile(absPath, relPath string) ([]security.Finding, error) {
	f, err := os.Open(absPath)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var findings []security.Finding
	scanner := bufio.NewScanner(f)
	lineNum := 0
	for scanner.Scan() {
		lineNum++
		line := scanner.Text()
		for _, cr := range s.rules {
			if cr.re.MatchString(line) {
				findings = append(findings, security.Finding{
					ID:       cr.rule.ID,
					Scanner:  "custom-rules",
					Severity: security.Severity(cr.rule.Severity),
					Category: security.Category(cr.rule.Category),
					Title:    cr.rule.Title,
					Location: security.Location{
						File:      relPath,
						StartLine: lineNum,
						EndLine:   lineNum,
					},
					Evidence:   line,
					Confidence: security.ConfidenceHigh,
				})
			}
		}
	}
	return findings, scanner.Err()
}
scanner.NewDepScanner function · go · L45-L59 (15 LOC)
internal/security/scanner/deps.go
func NewDepScanner(client *http.Client) *DepScanner {
	s := &DepScanner{
		client:     client,
		OSVBaseURL: defaultOSVBaseURL,
	}
	s.parsers = []lockfileParser{
		{filename: "go.sum", ecosystem: "Go", parse: parseGoSum},
		{filename: "package-lock.json", ecosystem: "npm", parse: parsePackageLock},
		{filename: "requirements.txt", ecosystem: "PyPI", parse: parseRequirementsTxt},
		{filename: "Gemfile.lock", ecosystem: "RubyGems", parse: parseGemfileLock},
		{filename: "Cargo.lock", ecosystem: "crates.io", parse: parseCargoLock},
		{filename: "Podfile.lock", ecosystem: "CocoaPods", parse: parsePodfileLock},
	}
	return s
}
Repobility · code-quality intelligence · https://repobility.com
scanner.DepScanner.Scan method · go · L68-L115 (48 LOC)
internal/security/scanner/deps.go
func (s *DepScanner) Scan(ctx context.Context, target security.ScanTarget) ([]security.Finding, error) {
	if err := ctx.Err(); err != nil {
		return nil, fmt.Errorf("dependency auditor cancelled: %w", err)
	}

	var findings []security.Finding

	for _, parser := range s.parsers {
		if err := ctx.Err(); err != nil {
			return nil, fmt.Errorf("dependency auditor cancelled: %w", err)
		}

		lockfilePath := filepath.Join(target.RootDir, parser.filename)
		data, err := os.ReadFile(lockfilePath)
		if err != nil {
			continue // lockfile not present — skip silently
		}

		deps, err := parser.parse(data)
		if err != nil {
			continue // parse error — skip silently
		}

		if s.client == nil {
			continue // no HTTP client — skip OSV queries
		}

		for _, dep := range deps {
			if err := ctx.Err(); err != nil {
				return nil, fmt.Errorf("dependency auditor cancelled: %w", err)
			}

			vulnFindings, err := s.queryOSV(ctx, dep, parser.ecosystem, parser.filename)
			if err != nil {
				// OSV unav
scanner.DepScanner.queryOSV method · go · L118-L160 (43 LOC)
internal/security/scanner/deps.go
func (s *DepScanner) queryOSV(ctx context.Context, dep dependency, ecosystem, lockfile string) ([]security.Finding, error) {
	reqBody := osvQueryRequest{
		Package: osvPackage{
			Name:      dep.Name,
			Ecosystem: ecosystem,
		},
		Version: dep.Version,
	}

	bodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("marshaling OSV request: %w", err)
	}

	url := s.OSVBaseURL + "/v1/query"
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(bodyBytes))
	if err != nil {
		return nil, fmt.Errorf("creating OSV request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := s.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("OSV API request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("OSV API returned status %d", resp.StatusCode)
	}

	var osvResp osvQueryResponse
	if err := json.NewDecoder(resp.Body).Decode(&osvResp); err != nil {
		retur
scanner.DepScanner.newVulnFinding method · go · L163-L195 (33 LOC)
internal/security/scanner/deps.go
func (s *DepScanner) newVulnFinding(dep dependency, vuln osvVuln, sev security.Severity, lockfile string) security.Finding {
	s.mu.Lock()
	s.findingCounter++
	id := fmt.Sprintf("DEP-%04d", s.findingCounter)
	s.mu.Unlock()

	var refs []string
	for _, r := range vuln.References {
		refs = append(refs, r.URL)
	}

	return security.Finding{
		ID:          id,
		Scanner:     "dependency-audit",
		Severity:    sev,
		Category:    security.CategoryVulnerableDep,
		Title:       fmt.Sprintf("Vulnerable dependency: %s@%s (%s)", dep.Name, dep.Version, vuln.ID),
		Description: vuln.Summary,
		Location: security.Location{
			File: lockfile,
		},
		CWE:        "CWE-1035",
		Evidence:   fmt.Sprintf("Package %s@%s has known vulnerability %s", dep.Name, dep.Version, vuln.ID),
		Confidence: security.ConfidenceHigh,
		References: refs,
		Metadata: map[string]string{
			"vuln_id":   vuln.ID,
			"package":   dep.Name,
			"version":   dep.Version,
			"ecosystem": lockfile,
		},
	}
}
scanner.DepScanner.newInfoFinding method · go · L198-L217 (20 LOC)
internal/security/scanner/deps.go
func (s *DepScanner) newInfoFinding(title, description, lockfile string) security.Finding {
	s.mu.Lock()
	s.findingCounter++
	id := fmt.Sprintf("DEP-%04d", s.findingCounter)
	s.mu.Unlock()

	return security.Finding{
		ID:          id,
		Scanner:     "dependency-audit",
		Severity:    security.SeverityInfo,
		Category:    security.CategoryVulnerableDep,
		Title:       title,
		Description: description,
		Location: security.Location{
			File: lockfile,
		},
		CWE:        "CWE-1035",
		Confidence: security.ConfidenceLow,
	}
}
scanner.classifyOSVSeverity function · go · L220-L238 (19 LOC)
internal/security/scanner/deps.go
func classifyOSVSeverity(vuln osvVuln) security.Severity {
	for _, sev := range vuln.Severity {
		if sev.Type == "CVSS_V3" {
			score := parseCVSSScore(sev.Score)
			switch {
			case score >= 9.0:
				return security.SeverityCritical
			case score >= 7.0:
				return security.SeverityHigh
			case score >= 4.0:
				return security.SeverityMedium
			default:
				return security.SeverityLow
			}
		}
	}
	// No CVSS score available — default to Medium.
	return security.SeverityMedium
}
scanner.parseGoSum function · go · L306-L342 (37 LOC)
internal/security/scanner/deps.go
func parseGoSum(data []byte) ([]dependency, error) {
	seen := make(map[string]bool)
	var deps []dependency

	scanner := bufio.NewScanner(bytes.NewReader(data))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}

		parts := strings.Fields(line)
		if len(parts) < 2 {
			continue
		}

		name := parts[0]
		version := parts[1]

		// Skip /go.mod hash lines.
		if strings.HasSuffix(version, "/go.mod") {
			continue
		}

		// Remove the h1: hash suffix from version if present.
		// go.sum format: module version h1:hash
		// version may have a /go.mod suffix (already handled above).
		key := name + "@" + version
		if seen[key] {
			continue
		}
		seen[key] = true

		deps = append(deps, dependency{Name: name, Version: strings.TrimPrefix(version, "v")})
	}
	return deps, scanner.Err()
}
scanner.parsePackageLock function · go · L346-L385 (40 LOC)
internal/security/scanner/deps.go
func parsePackageLock(data []byte) ([]dependency, error) {
	var lockfile struct {
		Packages     map[string]packageLockEntry `json:"packages"`
		Dependencies map[string]packageLockEntry `json:"dependencies"`
	}

	if err := json.Unmarshal(data, &lockfile); err != nil {
		return nil, fmt.Errorf("parsing package-lock.json: %w", err)
	}

	var deps []dependency

	// lockfileVersion 2/3: uses "packages" with "node_modules/" prefixes.
	for key, entry := range lockfile.Packages {
		if entry.Version == "" {
			continue
		}
		// Extract package name from "node_modules/name" path.
		name := key
		if idx := strings.LastIndex(key, "node_modules/"); idx >= 0 {
			name = key[idx+len("node_modules/"):]
		}
		if name == "" {
			continue
		}
		deps = append(deps, dependency{Name: name, Version: entry.Version})
	}

	// lockfileVersion 1: uses "dependencies" with flat names.
	if len(deps) == 0 {
		for name, entry := range lockfile.Dependencies {
			if entry.Version == "" {
				continue
			}
			deps = appe
scanner.parseRequirementsTxt function · go · L393-L410 (18 LOC)
internal/security/scanner/deps.go
func parseRequirementsTxt(data []byte) ([]dependency, error) {
	var deps []dependency
	re := regexp.MustCompile(`^([a-zA-Z0-9._-]+)==([^\s#]+)`)

	scanner := bufio.NewScanner(bytes.NewReader(data))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}

		matches := re.FindStringSubmatch(line)
		if matches != nil {
			deps = append(deps, dependency{Name: matches[1], Version: matches[2]})
		}
	}
	return deps, scanner.Err()
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
scanner.parseGemfileLock function · go · L413-L441 (29 LOC)
internal/security/scanner/deps.go
func parseGemfileLock(data []byte) ([]dependency, error) {
	var deps []dependency
	re := regexp.MustCompile(`^\s{4}(\S+)\s+\(([^)]+)\)`)

	inSpecs := false
	scanner := bufio.NewScanner(bytes.NewReader(data))
	for scanner.Scan() {
		line := scanner.Text()

		if strings.TrimSpace(line) == "specs:" {
			inSpecs = true
			continue
		}

		// End of specs section when we hit a non-indented line (except blank).
		if inSpecs && len(line) > 0 && line[0] != ' ' {
			inSpecs = false
			continue
		}

		if inSpecs {
			matches := re.FindStringSubmatch(line)
			if matches != nil {
				deps = append(deps, dependency{Name: matches[1], Version: matches[2]})
			}
		}
	}
	return deps, scanner.Err()
}
scanner.parseCargoLock function · go · L444-L474 (31 LOC)
internal/security/scanner/deps.go
func parseCargoLock(data []byte) ([]dependency, error) {
	var deps []dependency
	var currentName, currentVersion string

	scanner := bufio.NewScanner(bytes.NewReader(data))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		if line == "[[package]]" {
			if currentName != "" && currentVersion != "" {
				deps = append(deps, dependency{Name: currentName, Version: currentVersion})
			}
			currentName = ""
			currentVersion = ""
			continue
		}

		if strings.HasPrefix(line, "name = ") {
			currentName = unquoteTOML(strings.TrimPrefix(line, "name = "))
		} else if strings.HasPrefix(line, "version = ") {
			currentVersion = unquoteTOML(strings.TrimPrefix(line, "version = "))
		}
	}

	// Don't forget the last package block.
	if currentName != "" && currentVersion != "" {
		deps = append(deps, dependency{Name: currentName, Version: currentVersion})
	}

	return deps, scanner.Err()
}
scanner.parsePodfileLock function · go · L477-L504 (28 LOC)
internal/security/scanner/deps.go
func parsePodfileLock(data []byte) ([]dependency, error) {
	var deps []dependency
	re := regexp.MustCompile(`^\s+-\s+(\S+)\s+\(([^)]+)\)`)

	inPods := false
	scanner := bufio.NewScanner(bytes.NewReader(data))
	for scanner.Scan() {
		line := scanner.Text()

		if strings.TrimSpace(line) == "PODS:" {
			inPods = true
			continue
		}

		// End of PODS section at next top-level key.
		if inPods && len(line) > 0 && line[0] != ' ' {
			break
		}

		if inPods {
			matches := re.FindStringSubmatch(line)
			if matches != nil {
				deps = append(deps, dependency{Name: matches[1], Version: matches[2]})
			}
		}
	}
	return deps, scanner.Err()
}
‹ prevpage 4 / 11next ›