shadowcat 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. agent/__init__.py +17 -0
  2. agent/benchmark/__init__.py +11 -0
  3. agent/benchmark/cli.py +179 -0
  4. agent/benchmark/config.py +15 -0
  5. agent/benchmark/docker.py +192 -0
  6. agent/benchmark/registry.py +99 -0
  7. agent/core/__init__.py +0 -0
  8. agent/core/agent.py +362 -0
  9. agent/core/backend.py +1667 -0
  10. agent/core/config.py +106 -0
  11. agent/core/controller.py +638 -0
  12. agent/core/events.py +177 -0
  13. agent/core/langfuse.py +320 -0
  14. agent/core/phantom.py +2327 -0
  15. agent/core/planner.py +493 -0
  16. agent/core/profiling.py +58 -0
  17. agent/core/sanitizer.py +104 -0
  18. agent/core/session.py +228 -0
  19. agent/core/tracer.py +137 -0
  20. agent/interface/__init__.py +0 -0
  21. agent/interface/components/__init__.py +0 -0
  22. agent/interface/components/activity_feed.py +202 -0
  23. agent/interface/components/renderers.py +149 -0
  24. agent/interface/components/splash.py +112 -0
  25. agent/interface/main.py +1126 -0
  26. agent/interface/styles.tcss +421 -0
  27. agent/interface/tui.py +508 -0
  28. agent/parsing/html_distiller.py +230 -0
  29. agent/parsing/tool_parser.py +115 -0
  30. agent/prompts/__init__.py +0 -0
  31. agent/prompts/pentesting.py +238 -0
  32. agent/rag_module/knowledge_base.py +116 -0
  33. agent/tests/benchmark_phantom.py +455 -0
  34. agent/tools/__init__.py +14 -0
  35. agent/tools/base.py +99 -0
  36. agent/tools/executor.py +345 -0
  37. agent/tools/registry.py +47 -0
  38. backend/README.md +244 -0
  39. backend/__init__.py +10 -0
  40. backend/api/__init__.py +1 -0
  41. backend/api/routes_scan.py +932 -0
  42. backend/authz.py +75 -0
  43. backend/cli.py +261 -0
  44. backend/compliance/__init__.py +1 -0
  45. backend/compliance/pdpa_mapping.py +16 -0
  46. backend/core/__init__.py +1 -0
  47. backend/core/coverage.py +93 -0
  48. backend/core/events.py +166 -0
  49. backend/core/llm_client.py +614 -0
  50. backend/core/orchestrator.py +402 -0
  51. backend/core/scan_memory.py +236 -0
  52. backend/crawler/__init__.py +1 -0
  53. backend/crawler/csrf.py +75 -0
  54. backend/crawler/headless.py +232 -0
  55. backend/crawler/js_analyzer.py +133 -0
  56. backend/crawler/spider.py +550 -0
  57. backend/crawler/subdomains.py +279 -0
  58. backend/daemon.py +252 -0
  59. backend/db/README.md +86 -0
  60. backend/db/__init__.py +17 -0
  61. backend/db/engine.py +87 -0
  62. backend/db/models.py +206 -0
  63. backend/db/repository.py +316 -0
  64. backend/db/schema.sql +247 -0
  65. backend/modes/__init__.py +5 -0
  66. backend/modes/base.py +178 -0
  67. backend/modes/ctf.py +39 -0
  68. backend/modes/enterprise.py +210 -0
  69. backend/modes/general.py +226 -0
  70. backend/modes/registry.py +34 -0
  71. backend/reporting/__init__.py +0 -0
  72. backend/reporting/generator.py +285 -0
  73. backend/schemas/__init__.py +1 -0
  74. backend/schemas/api.py +423 -0
  75. backend/tools/__init__.py +62 -0
  76. backend/tools/dirbrute_tool.py +304 -0
  77. backend/tools/general_report_tool.py +135 -0
  78. backend/tools/http_tool.py +351 -0
  79. backend/tools/nuclei_tool.py +20 -0
  80. backend/tools/report_tool.py +145 -0
  81. backend/tools/shell_tools.py +23 -0
  82. backend/verification/__init__.py +1 -0
  83. backend/verification/evidence_store.py +125 -0
  84. backend/verification/general_oracle.py +369 -0
  85. backend/verification/idor_oracle.py +131 -0
  86. backend/waf/__init__.py +0 -0
  87. backend/waf/detector.py +147 -0
  88. backend/waf/evasion.py +117 -0
  89. backend/webui/index.html +713 -0
  90. backend/workspace.py +182 -0
  91. shadowcat-2.0.0.dist-info/METADATA +360 -0
  92. shadowcat-2.0.0.dist-info/RECORD +95 -0
  93. shadowcat-2.0.0.dist-info/WHEEL +4 -0
  94. shadowcat-2.0.0.dist-info/entry_points.txt +4 -0
  95. shadowcat-2.0.0.dist-info/licenses/LICENSE.md +21 -0
agent/core/config.py ADDED
@@ -0,0 +1,106 @@
1
+ """Configuration management for ShadowCat using Pydantic."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Literal
5
+
6
+ from pydantic import AliasChoices, Field
7
+ from pydantic_settings import BaseSettings, SettingsConfigDict
8
+
9
+ # User-global config written by ``shadowcat config``. Used as the lowest-priority
10
+ # fallback so a pip-installed CLI works from any directory without a local .env.
11
+ _USER_ENV = str(Path.home() / ".shadowcat" / ".env")
12
+
13
+
14
+ class ShadowCatConfig(BaseSettings):
15
+ """Main configuration for ShadowCat."""
16
+
17
+ model_config = SettingsConfigDict(
18
+ # Read several files; later entries override earlier ones. So precedence
19
+ # (highest first) is: real env vars > project `.env.auth` > project `.env`
20
+ # > user-global `~/.shadowcat/.env`. The global file is the fallback for
21
+ # the pip-installed CLI; project files override it for local dev.
22
+ env_file=(_USER_ENV, ".env", ".env.auth"),
23
+ env_file_encoding="utf-8",
24
+ case_sensitive=False,
25
+ extra="ignore",
26
+ populate_by_name=True,
27
+ )
28
+
29
+ # LLM Configuration
30
+ llm_model: str = Field(
31
+ default="",
32
+ validation_alias=AliasChoices("MODEL", "LLM_MODEL"),
33
+ description="Model identifier for OpenRouter (e.g. anthropic/claude-3-5-sonnet)",
34
+ )
35
+
36
+ openrouter_api_key: str | None = Field(
37
+ default=None,
38
+ validation_alias=AliasChoices("OPENROUTER_API_KEY"),
39
+ description="OpenRouter API key (https://openrouter.ai/keys)",
40
+ )
41
+
42
+ # Agent Configuration
43
+ max_iterations: int = Field(default=300, description="Maximum iterations for the agent")
44
+
45
+ working_directory: Path = Field(
46
+ default_factory=lambda: Path.cwd() / "workspace",
47
+ description="Working directory for agent operations",
48
+ )
49
+
50
+ # Target Configuration
51
+ target: str = Field(
52
+ ..., # Required
53
+ description="Target for penetration testing (URL, IP, domain, or path)",
54
+ )
55
+
56
+ custom_instruction: str | None = Field(
57
+ default=None, description="Optional custom instructions for the agent"
58
+ )
59
+
60
+ # Interface Configuration
61
+ interface_mode: Literal["tui", "cli"] = Field(
62
+ default="tui", description="Interface mode: TUI (interactive) or CLI (headless)"
63
+ )
64
+
65
+ verbose: bool = Field(default=True, description="Enable verbose output")
66
+
67
+ def __init__(self, **data: Any) -> None:
68
+ """Initialize configuration."""
69
+ super().__init__(**data)
70
+
71
+ # Create working directory if it doesn't exist
72
+ # Ignore permission errors if directory already exists
73
+ try:
74
+ self.working_directory.mkdir(parents=True, exist_ok=True)
75
+ except (PermissionError, OSError):
76
+ # Directory already exists or we don't have permission to create it
77
+ # This is fine if the directory is already available
78
+ if not self.working_directory.exists():
79
+ raise
80
+
81
+ @property
82
+ def system_prompt_path(self) -> Path:
83
+ """Get path to system prompt file."""
84
+ return Path(__file__).parent.parent / "prompts" / "pentesting.py"
85
+
86
+ @classmethod
87
+ def from_env(cls, **overrides: object) -> "ShadowCatConfig":
88
+ """Create config from environment variables with optional overrides."""
89
+ return cls(**overrides)
90
+
91
+
92
+ def load_config(**overrides: object) -> ShadowCatConfig:
93
+ """
94
+ Load configuration from environment with optional overrides.
95
+
96
+ Args:
97
+ **overrides: Keyword arguments to override config values
98
+
99
+ Returns:
100
+ ShadowCatConfig instance
101
+
102
+ Example:
103
+ >>> config = load_config(target="example.com", verbose=True)
104
+ """
105
+ # Create config with overrides
106
+ return ShadowCatConfig.from_env(**overrides)