Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0f26941
Add Lint & format workflows.
Einswilli Sep 6, 2025
40e02aa
Merge branch 'AllDotPy:master' into master
Einswilli Sep 6, 2025
b9913ca
Add Code of Conduct.
Einswilli Sep 6, 2025
b6bd262
Add Contributions guide.
Einswilli Sep 6, 2025
f9dfa45
Merge branch 'master' of https://github.com/Einswilli/Valkyrie
Einswilli Sep 6, 2025
1afc3a0
Update CONTRUBUTING.md and Pyproject.toml files.
Einswilli Sep 6, 2025
30d578c
Update CONTRUBUTING.md and Pyproject.toml files.
Einswilli Sep 6, 2025
f1b4428
remove main.py file form the root dir.
Einswilli Sep 6, 2025
850e5d7
Merge branch 'AllDotPy:master' into master
Einswilli Sep 6, 2025
d6e7800
valkyrie.core: Add Scanner engine and types modules.
Einswilli Sep 6, 2025
dbaee48
feat(core): Add Scanner Configuration types and Scanner Engine.
Einswilli Sep 6, 2025
7df00ad
Merge branch 'AllDotPy:master' into master
Einswilli Sep 6, 2025
6c125cf
valkyrie.plugins: Add Security Rules Base class Secrets detector Plugin.
Einswilli Sep 7, 2025
b6c7d6c
__ # Merge branch 'master' of https://github.com/Einswilli/Valkyrie i…
Einswilli Sep 7, 2025
1ba0352
valkyrie.plugins: Add Plugin manager.
Einswilli Sep 7, 2025
d023343
valkyrie.plugins: Add Plugin manager.
Einswilli Sep 7, 2025
a2fef8b
valkyrie.plugins: Add Plugin manager.
Einswilli Sep 7, 2025
e90ba68
Merge branch 'AllDotPy:master' into master
Einswilli Sep 7, 2025
73474ef
valkyrie.plugins: Add Plugin manager.
Einswilli Sep 7, 2025
e1238c4
valkyrie.plugins: Add Plugin manager.
Einswilli Sep 7, 2025
4bfa0fa
Merge branch 'AllDotPy:master' into master
Einswilli Sep 7, 2025
e3b808a
Merge branch 'AllDotPy:master' into feat.plugins
Einswilli Sep 7, 2025
ae14c1d
Feat (plugins): Add Plugin manager
Einswilli Sep 7, 2025
f0310b4
refractor: valkyrie.plugins.secrets.
Einswilli Sep 8, 2025
ebb3a38
Merge branch 'AllDotPy:master' into master
Einswilli Sep 8, 2025
d9677d4
Merge branch 'AllDotPy:master' into feat.plugins
Einswilli Sep 8, 2025
a49198d
Merge branch 'master' into feat.plugins
Einswilli Sep 8, 2025
cf596f8
Merge branch into feat.plugins
Einswilli Sep 8, 2025
e071c5f
Merge branch 'master' into feat.plugins
Einswilli Sep 8, 2025
ce522fa
Refractor: Refractor secrets plugin to make it more cleanner.
Einswilli Sep 8, 2025
d716401
Merge branch 'AllDotPy:master' into master
Einswilli Sep 8, 2025
a35a54e
Merge branch 'AllDotPy:master' into master
Einswilli Sep 11, 2025
a97b666
Merge branch 'AllDotPy:master' into master
Einswilli Sep 13, 2025
312124c
Merge branch 'AllDotPy:master' into master
Einswilli Sep 13, 2025
ed533d7
Merge branch 'AllDotPy:master' into master
Einswilli Sep 13, 2025
90844a4
Merge branch 'AllDotPy:master' into master
Einswilli Sep 14, 2025
c291594
Merge branch 'AllDotPy:master' into master
Einswilli Sep 14, 2025
e7e95e6
Merge branch 'AllDotPy:master' into master
Einswilli Sep 14, 2025
5626179
Merge branch 'AllDotPy:master' into master
Einswilli Sep 17, 2025
1c9a9e4
valkyrie,plugins: add vulnera vulnerablity scanner plugin
Einswilli Sep 11, 2025
8ecc47e
stqrt removing plugin system and refractoring the project
Einswilli Sep 17, 2025
1752f0a
refractoring part 1
Einswilli Nov 19, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,4 @@ docs/*
rules/*
tests/*
valkyrie/repositories/*
output.json
299 changes: 299 additions & 0 deletions output.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ keywords = [
"pipelines", "iam", "secrets"
]
dependencies = [
"aiohttp>=3.12.15",
"pydantic>=2.11.9",
"toml>=0.10.2",
"tomli>=2.2.1",
"yamllib>=0.0.1",
]

Expand All @@ -32,6 +32,9 @@ dev = [
"mkdocs-static-i18n>=1.3.0",
]

[project.scripts]
valkyrie = "valkyrie.__main__:main"

[project.urls]
# Homepage = "https://alldotpy.github.io/FletX"
Repository = "https://github.com/AllDotPy/Valkyrie"
Expand Down
152 changes: 152 additions & 0 deletions valkyrie.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Core scanner settings
scanner:
# Target directory to scan (relative to config file)
target_path: "."

# File inclusion patterns (glob patterns)
include_patterns:
- "**/*.py"
- "**/*.js"
- "**/*.ts"
- "**/*.java"
- "**/*.go"
- "**/*.rs"
- "**/*.yaml"
- "**/*.yml"
- "**/*.json"
- "**/*.tf"
- "**/*.hcl"

# File exclusion patterns
exclude_patterns:
- "**/.git/**"
- "**/.vscode/**"
- "**/node_modules/**"
- "**/__pycache__/**"
- "**/target/**"
- "**/build/**"
- "**/dist/**"
- "**/*.min.js"
- "**/*.map"
- ".venv/**"

# Maximum file size to scan (in bytes)
max_file_size: 10485760 # 10MB

# Number of parallel scanning workers
parallel_workers: 4

# Minimum severity level to report
severity_threshold: "low" # critical, high, medium, low, info

# Whether to fail the build on security findings
fail_on_findings: true

# Scan only changed files in CI (if supported)
diff_only: false

# Rule configuration
rules:
# Remote rule repository (GitHub, GitLab, etc.)
repository:
type: "github"
url: "AllDotPy/valkyrie-community-rules"
branch: "master"
token_env: "GITHUB_TOKEN" # Environment variable for authentication

# Local rules directory
local_rules_dir: "./rules"

# Rule filters (empty = all rules enabled)
include_rules: []

# Disabled rules
exclude_rules: []

# Custom rule categories to enable/disable
categories:
secrets: true
dependencies: true
iam_config: true
code_quality: false
infrastructure: true

# Plugin configuration
plugins:
# Built-in plugins
secrets_detector:
enabled: true
config:
# Custom entropy threshold for secrets detection
entropy_threshold: 3.5
# Additional secret patterns (regex)
custom_patterns:
- name: "Custom API Key"
pattern: "CUSTOM_[A-Z0-9]{32}"
keywords: ["custom", "api"]

dependency_scanner:
enabled: true
config:
# Vulnerability database sources
databases:
- "osv.dev"
- "nvd.nist.gov"
# Cache duration for vulnerability data (hours)
cache_duration: 24
# Check dev dependencies
include_dev_deps: true

iam_scanner:
enabled: true
config:
# Cloud providers to check
providers: ["aws", "gcp", "azure"]
# Custom IAM policy patterns
custom_patterns:
- name: "Wildcard Principal"
pattern: '"Principal":\s*"\*"'
severity: "critical"

# Output configuration
output:
# Default output format
format: "json" # json, sarif, html

# Output file (optional)
file: "output.json"

# Verbose logging
verbose: false

# Include successful scans in output
include_success: false

# CI/CD Integration settings
ci_integration:
# GitHub Actions
- github:
# Post results as check runs
create_check_runs: true
# Comment on Pull Requests
comment_on_pr: true
# Create annotations for findings
create_annotations: true
# Maximum annotations to create
max_annotations: 50

# GitLab CI
- gitlab:
# Post merge request notes
post_mr_notes: true
# Create commit statuses
create_commit_status: true
# Generate SAST reports
generate_sast_report: true

# Generic CI settings
- generic:
# Exit codes
success_exit_code: 0
findings_exit_code: 1
failure_exit_code: 2
30 changes: 30 additions & 0 deletions valkyrie/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-

""" MAIN ENTRY POINT FOR Valkyrie CLI
This module serves as the main entry point for the Valkyrie CLI. It handles command-line
arguments, initializes the command registry, and executes the specified command.
"""

import sys
import asyncio
from valkyrie.cli import (
ValkyrieCLI
)

import tracemalloc
tracemalloc.start()

async def main():
"""
Main function to handle command-line arguments and execute commands.
This function checks if any command is provided, retrieves the command class
from the command registry, and executes the command with the provided arguments.
If no command is provided, it lists all available commands.
"""

cli = ValkyrieCLI()
exit_code = await cli.run()
sys.exit(exit_code)

if __name__ == "__main__":
asyncio.run(main())
178 changes: 178 additions & 0 deletions valkyrie/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/usr/bin/env python3
"""
Valkyrie CLI - A command-line tool.
"""

import argparse
from typing import List
from pathlib import Path

import yaml

from valkyrie.core import (
ValkyrieConfig, ValkyrieScanner,
ScanStatus, get_formatter
)
from valkyrie.rules.repositories import (
LocalRuleRepository, GitHubRuleRepository
)
from valkyrie.utils import (
get_context,
get_logger
)


####
## VALKYRIE CLI ENTRY POINT
#####
class ValkyrieCLI:
"""Command line interface for Valkyrie scanner"""

def __init__(self):

self.logger = get_logger('Valkyrie.CLI')
self.context = get_context()
# self.ci_integrations = [
# GitHubActionsIntegration(),
# GitLabCIIntegration()
# ]
# self.formatters = {
# "json": JSONFormatter(),
# "sarif": SARIFFormatter(),
# "html": HTMLFormatter()
# }
...

def create_parser(self) -> argparse.ArgumentParser:
"""Create CLI argument parser"""
parser = argparse.ArgumentParser(
description="Valkyrie - Security scanner for CI/CD pipelines",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
valkyrie scan # Scan current directory
valkyrie scan --target <TARGET_DIR> # Target directoory to scan
valkyrie scan --config-file <CONFIG_FILE> # Valyrie config file
"""
)

subparsers = parser.add_subparsers(dest="command", help="Available commands")

# Scan command
scan_parser = subparsers.add_parser("scan", help="Run security scan")
scan_parser.add_argument("target", nargs="?", default=".", help="Target path to scan")
scan_parser.add_argument("--config-file", "-f", nargs="?", default="valkyrie.yml", help="Valkyrie configuration file path")
# scan_parser.add_argument("--format", choices=["json", "sarif", "html"], default="json", help="Output format")
# scan_parser.add_argument("--output", "-o", type=Path, help="Output file path")
# scan_parser.add_argument("--severity", choices=["critical", "high", "medium", "low", "info"], default="low", help="Minimum severity level")
# scan_parser.add_argument("--rules-repo", default="valkyrie-community/rules", help="Rules repository")
# scan_parser.add_argument("--no-fail", action="store_true", help="Don't fail on findings")
# scan_parser.add_argument("--include", action="append", help="Include patterns")
# scan_parser.add_argument("--exclude", action="append", help="Exclude patterns")
# scan_parser.add_argument("--workers", type=int, default=4, help="Number of parallel workers")
# scan_parser.add_argument("--diff-only", action="store_true", help="Only scan changed files")
scan_parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")

# Version command
subparsers.add_parser("version", help="Show version information")

return parser

async def run(self, args: List[str] = None) -> int:
"""Run CLI with given arguments"""

parser = self.create_parser()
parsed_args = parser.parse_args(args)

if parsed_args.command == "version":
print("Valkyrie Security Scanner v1.0.0")
return 0

elif parsed_args.command == "scan":
return await self._run_scan(parsed_args)

else:
parser.print_help()
return 1

async def _run_scan(self, args) -> int:
"""Execute security scan"""

# Load Config file
file = Path(args.config_file)

print(file)

# Create configuration
config = ValkyrieConfig.from_json(
yaml.safe_load(file.read_text())
)

# Add cmd args to the global context
self.context.set_data('cmd_args', args)

# Detect and register configured plugins
# PluginManager.load_from_config(config.plugins)


# Detect CI environment
# active_ci = None
# for ci_integration in self.ci_integrations:
# if ci_integration.detect_environment():
# active_ci = ci_integration
# break

# if active_ci and args.verbose:
# print(f"Detected CI environment: {active_ci.__class__.__name__}")

# # Filter files if diff-only mode
# if args.diff_only and active_ci:
# changed_files = active_ci.get_changed_files()
# if changed_files:
# # Convert to include patterns
# config.scanner.include_patterns = [str(f) for f in changed_files]
# if args.verbose:
# print(f"Scanning {len(changed_files)} changed files")

# Set up scanner


# Init GH repository with config options
gh_repo = GitHubRuleRepository(
config = config.rules.repository
)
# local_repo = LocalRuleRepository(Path("rules")) # In practice, use GitHub repo
scanner = ValkyrieScanner(
rule_repository = gh_repo,
config = config.scanner
)

# Run scan
if args.verbose:
print(f"Starting security scan of {config.scanner.target_path}")

result = await scanner.scan()

# Format results
formatter = get_formatter(config.output.format)
formatted_output = formatter().format(result)

# Output results
if config.output.file:
Path(config.output.file).write_text(formatted_output, encoding='utf-8')
print(f"Results saved to: {args.output}")
else:
print(formatted_output)

# Post to CI if in CI environment
# if active_ci:
# await active_ci.post_results(result, {})

# Determine exit code
if result.status == ScanStatus.FAILED:
return 2 # Scan failure
elif config.scanner.fail_on_findings and result.has_blocking_issues:
return 1 # Security issues found
else:
return 0 # Success

Loading
Loading