From 69cb22cc2f75f3e2ca210c6b927ef5cd80fe1ede Mon Sep 17 00:00:00 2001 From: Andrei Zavgorodnii Date: Wed, 12 Nov 2025 18:01:59 +0000 Subject: [PATCH] feat: better taxonomy --- v1/entities.yml | 855 +++++++++++++++++++++-- v1/go/entities/entities.go | 312 ++++++++- v1/go/entities/validators.go | 147 +++- v1/python/pentagi_taxonomy/edges.py | 113 ++- v1/python/pentagi_taxonomy/entity_map.py | 76 +- v1/python/pentagi_taxonomy/nodes.py | 180 ++++- v1/python/tests/test_generated_code.py | 47 +- v1/typescript/src/schemas.ts | 544 +++++++++++++- 8 files changed, 2126 insertions(+), 148 deletions(-) diff --git a/v1/entities.yml b/v1/entities.yml index ef14be5..54519fb 100644 --- a/v1/entities.yml +++ b/v1/entities.yml @@ -3,90 +3,865 @@ version: 1 nodes: Target: - description: "A target system being assessed during penetration testing" + description: "Network endpoint, service, application, or host being assessed. Should include version information, technology stack, and network details (IP, port, protocol). Examples: 'phpMyAdmin 4.4.15.6 on 172.22.0.7:80', 'Apache 2.4.29 web server'" fields: version: type: int - description: "Taxonomy schema version (auto-injected by Graphiti fork)" + description: "Taxonomy schema version" entity_uuid: type: string description: "Unique identifier" + identifier: + type: string + description: "Primary identifier (hostname, IP, URL)" + target_type: + type: string + enum: [host, service, web_application, api_endpoint, network_range, container] + description: "Type of target" hostname: type: string - description: "DNS hostname if known" + description: "DNS hostname if applicable" ip_address: type: string - description: "IP address of the target" + description: "IP address if applicable" regex: "^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$" - target_type: + port: + type: int + description: "Port number if service-specific" + min: 1 + max: 65535 + protocol: + type: string + description: "Protocol (HTTP, HTTPS, SSH, etc.)" + technology_stack: + type: string[] + description: "Technologies detected (PHP, Apache, MySQL, etc.)" + status: + type: string + enum: [discovered, active, compromised, analyzed, unreachable] + description: "Current assessment status" + + Vulnerability: + description: "Security weakness or attack vector with CVE identifier, vulnerability class, or technical description. Should include severity assessment, exploitability status, version linkage, and test confirmation. Examples: 'CVE-2016-10134 SQLi in jsrpc.php profileIdx', 'XML External Entity (XXE) injection in document parser'" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + vulnerability_name: type: string - description: "Classification of target" - enum: [host, web_service, api] - risk_score: + description: "Vulnerability name or title" + vulnerability_class: + type: string + enum: [sql_injection, rce, xss, xxe, ssrf, lfi, rfi, csrf, auth_bypass, file_upload, command_injection, buffer_overflow, directory_traversal, privilege_escalation, information_disclosure, denial_of_service, deserialization, path_traversal, session_hijacking, other] + description: "OWASP/CWE category of vulnerability" + cve_id: + type: string + description: "CVE identifier if applicable" + regex: "^CVE-\\d{4}-\\d{4,7}$" + cvss_score: type: float - description: "Calculated risk score" + description: "CVSS score if available" min: 0.0 max: 10.0 + severity: + type: string + enum: [critical, high, medium, low, info] + description: "Severity assessment" + exploitability: + type: string + enum: [confirmed_exploitable, likely_exploitable, theoretical, not_exploitable, unknown] + description: "Whether vulnerability can be exploited" + description: + type: string + description: "Technical description of the vulnerability" + exploitation_techniques_tested: + type: string[] + description: "List of exploitation techniques attempted (e.g., error-based SQLi, time-based SQLi, XXE file read)" + successful_techniques: + type: string[] + description: "Techniques that successfully exploited this vulnerability" + failed_techniques: + type: string[] + description: "Techniques that failed to exploit this vulnerability" + xxe_parser_type: + type: string + description: "XML parser type if XXE vulnerability (lxml, libxml2, Xerces, etc.)" + xxe_protocol_handlers: + type: string[] + description: "Available protocol handlers for XXE (file, http, ftp, expect, php, jar)" + xxe_oob_confirmed: + type: boolean + description: "Whether out-of-band XXE interaction was confirmed" + + Tool: + description: "Executable scanner, testing tool, or exploitation framework. Extract when tool produces actionable results; note success/failure status. Examples: 'sqlmap', 'nmap', 'metasploit', 'Burp Suite'" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + tool_name: + type: string + description: "Tool name (nmap, sqlmap, metasploit, etc.)" + tool_category: + type: string + enum: [scanner, exploitation_framework, fuzzer, reconnaissance, enumeration, post_exploitation, password_cracker, web_proxy, network_tool, custom_script] + description: "Category of tool" + version_used: + type: string + description: "Version of the tool used" + purpose: + type: string + description: "What the tool was used for in this context" + + TechnicalFinding: + description: "Specific security observation or test result. Summarize concisely (max 500 chars), include confidence level, prioritize findings that advance the assessment narrative. Examples: '113 DB tables enumerated via error-based SQLi', '/etc/passwd accessed via XXE: 48 users listed', 'phpMyAdmin version 4.4.15.6 disclosed in HTTP headers'" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + finding_type: + type: string + enum: [version_disclosure, open_port, exposed_endpoint, configuration_issue, credential, sensitive_data, exploit_success, reconnaissance_data, vulnerability_confirmation, patch_status, service_banner, database_enumeration, authentication_result] + description: "Type of finding" + title: + type: string + description: "Brief title of the finding" + content: + type: string + description: "Detailed finding content (sanitized and summarized)" + confidence: + type: float + description: "Confidence in the finding" + min: 0.0 + max: 1.0 + severity: + type: string + enum: [critical, high, medium, low, info] + description: "Severity of the finding" + evidence: + type: string + description: "Key evidence supporting the finding (truncated)" + extraction_technique: + type: string + description: "How data was extracted (e.g., error-based SQLi, time-based, manual)" + data_type: + type: string + enum: [database_schema, user_info, configuration, privileges, file_content, command_output, network_data, session_info, other] + description: "Type of data in this finding" + + AttackTechnique: + description: "Specific exploitation method with technical details and payload information. Should map to MITRE ATT&CK taxonomy when applicable, record success/failure, and include actual payloads used. Examples: 'Error-based SQLi via updatexml()', 'Time-based blind SQLi with sleep()', 'Out-of-band XXE data exfiltration'" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + attack_technique_name: + type: string + description: "Name of the attack technique" + technique_category: + type: string + enum: [initial_access, execution, persistence, privilege_escalation, defense_evasion, credential_access, discovery, lateral_movement, collection, exfiltration, impact] + description: "MITRE ATT&CK category" + description: + type: string + description: "Description of how the technique works" + payload: + type: string + description: "Actual payload or command used (sanitized)" + success_indicator: + type: string + description: "What indicates successful execution" + + TestPhase: + description: "A phase or stage of the penetration testing engagement" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + test_phase_name: + type: string + enum: [reconnaissance, scanning, enumeration, vulnerability_analysis, exploitation, post_exploitation, reporting, cleanup] + description: "Name of the test phase" + objective: + type: string + description: "Objective of this phase" status: type: string - description: "Current status" - enum: [active, inactive] + enum: [not_started, in_progress, completed, blocked, skipped] + description: "Status of the phase" + start_timestamp: + type: timestamp + description: "When phase started" + end_timestamp: + type: timestamp + description: "When phase completed" - Port: - description: "A network port on a target system" + Credential: + description: "Actual authentication credentials with values (ALWAYS extract, including default credentials). Should include privilege level, discovery source, authentication status, and session tokens when applicable. Examples: 'Admin/zabbix', 'root/password', 'zbx_sessionid=0a0f93de...', 'API key: sk-abc123...'" + examples: ["username/password pairs", "API keys", "SSH private keys", "default credentials"] fields: version: type: int - description: "Taxonomy schema version (auto-injected by Graphiti fork)" + description: "Taxonomy schema version" entity_uuid: type: string description: "Unique identifier" - port_number: + credential_type: + type: string + enum: [username_password, api_key, token, ssh_key, certificate, hash, cookie] + description: "Type of credential" + username: + type: string + description: "Username if applicable" + is_valid: + type: boolean + description: "Whether credential is valid" + is_default: + type: boolean + description: "Whether this is a default credential (e.g., Admin/zabbix)" + privilege_level: + type: string + enum: [admin, user, guest, service_account, root, unknown] + description: "Privilege level of the credential" + source: + type: string + description: "How the credential was obtained" + authentication_state: + type: string + enum: [success, failure, requires_2fa, locked, expired, unknown] + description: "Result of authentication attempt with this credential" + + ExploitCode: + description: "Actual exploit code, script, or payload used during testing. Should reference target vulnerability, include programming language, and document purpose/objective. Can be proof-of-concept, weaponized exploit, web shell, or reconnaissance script." + fields: + version: type: int - description: "Port number" - min: 1 - max: 65535 - protocol: + description: "Taxonomy schema version" + entity_uuid: type: string - description: "Network protocol" - enum: [tcp, udp] - state: + description: "Unique identifier" + exploit_code_name: + type: string + description: "Name of the exploit" + language: + type: string + enum: [python, bash, php, ruby, powershell, javascript, go, other] + description: "Programming language" + purpose: + type: string + description: "What the exploit is designed to achieve" + file_path: + type: string + description: "Path where exploit was saved" + code_type: type: string - description: "Port state" - enum: [open, closed, filtered] + enum: [proof_of_concept, weaponized_exploit, web_shell, reverse_shell, payload, script, reconnaissance_tool] + description: "Type of code" -edges: - HAS_PORT: - description: "A target has a port" + AuthenticationAttempt: + description: "Login attempt (success or failure), session establishment (cookies/tokens/CSRF), credential validation, or bypass attempt. Should capture authentication state changes, privilege levels obtained, session tokens, and response details." fields: version: type: int - description: "Taxonomy schema version (auto-injected by Graphiti fork)" + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" timestamp: type: timestamp - description: "When association was established" + description: "When authentication was attempted" + success: + type: boolean + description: "Whether authentication succeeded" + credential_used: + type: string + description: "Reference to credential entity used" + session_established: + type: boolean + description: "Whether a session was established" + response_code: + type: int + description: "HTTP response code if applicable" + error_message: + type: string + description: "Error message if authentication failed" - DISCOVERED: - description: "An action discovered an entity" + DatabaseMetadata: + description: "Database configuration, schema, and structure information. Should include SQLi payload types used for extraction, enumeration results (tables/columns), user privileges, configuration details, and technique comparisons. Avoid duplicate error entries. Examples: 'MySQL 5.7.33 with FILE privilege', '113 tables enumerated: users, sessions, config, logs...'" fields: version: type: int - description: "Taxonomy schema version (auto-injected by Graphiti fork)" + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + database_type: + type: string + enum: [mysql, postgresql, mssql, oracle, mongodb, redis, other] + description: "Type of database" + database_version: + type: string + description: "Database version if known" + database_user: + type: string + description: "Database user (e.g., root@172.22.0.7)" + table_count: + type: int + description: "Number of tables discovered" + table_names: + type: string[] + description: "List of table names discovered" + privileges: + type: string[] + description: "User privileges (e.g., FILE, SELECT, INSERT)" + secure_file_priv: + type: string + description: "secure_file_priv setting value" + configuration_details: + type: string + description: "Other relevant configuration information" + + ExploitationAttempt: + description: "A specific exploitation attempt with a technique" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" timestamp: type: timestamp - description: "Discovery timestamp" + description: "When exploitation was attempted" + technique_type: + type: string + enum: [error_based_sqli, time_based_sqli, boolean_based_sqli, union_based_sqli, file_inclusion, command_injection, xxe, buffer_overflow, other] + description: "Type of exploitation technique" + success: + type: boolean + description: "Whether exploitation succeeded" + payload: + type: string + description: "Payload used (sanitized)" + response_hash: + type: string + description: "Hash of response for deduplication" + result_summary: + type: string + description: "Summary of what happened" + + SessionInfo: + description: "Session tokens, cookies, and authentication state AFTER successful authentication" + examples: ["zbx_sessionid cookie", "PHPSESSID cookie", "JWT token", "OAuth2 access token", "CSRF token"] + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + session_type: + type: string + enum: [cookie, token, jwt, oauth, api_key, other] + description: "Type of session mechanism" + session_id: + type: string + description: "Session identifier (e.g., zbx_sessionid value)" + csrf_token: + type: string + description: "CSRF token if applicable" + established_at: + type: timestamp + description: "When session was established" + expires_at: + type: timestamp + description: "When session expires (if known)" + privilege_level: + type: string + enum: [guest, user, admin, root, unknown] + description: "Privilege level of this session" + + FileSystemAccess: + description: "File system access attempt and result. For successful reads, include file path and content preview. Document permission boundaries, file types accessed, and sensitivity level. Skip duplicate permission denials (keep first only) and verbose methodology without results. Examples: '/etc/passwd read: 48 user accounts', 'SSH private key found at /root/.ssh/id_rsa'" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + file_path: + type: string + description: "Path to file or directory accessed" + access_type: + type: string + enum: [read, write, execute, list, stat] + description: "Type of access attempted" + success: + type: boolean + description: "Whether access was successful" + access_method: + type: string + enum: [xxe, lfi, rfi, command_injection, direct_access, path_traversal] + description: "Method used to access file" + content_preview: + type: string + description: "Preview of file content if read (truncated to 500 chars)" + permission_error: + type: string + description: "Permission error message if access denied" + file_type: + type: string + enum: [config, credential, log, system_info, ssh_key, source_code, database, other] + description: "Type of file accessed" + sensitivity: + type: string + enum: [critical, high, medium, low, info] + description: "Sensitivity level of accessed file" + + XMLPayload: + description: "XML payload used in XXE exploitation. Should identify XML parser (type/version), protocol handlers available (file/http/ftp/expect/php/jar), successful file reads, OOB interaction confirmations, payload variations tested, and parser configuration. Examples: 'XXE file:// payload reading /etc/passwd', 'OOB XXE via HTTP callback to attacker.com'" + fields: + version: + type: int + description: "Taxonomy schema version" + entity_uuid: + type: string + description: "Unique identifier" + payload_type: + type: string + enum: [file_read, oob_exfil, rce_attempt, ssrf, entity_expansion, parameter_entity] + description: "Type of XXE payload" + payload_content: + type: string + description: "Actual XML payload (sanitized)" + encoding: + type: string + enum: [utf-8, utf-16, utf-16be, base64, other] + description: "Payload encoding" + protocol_handler: + type: string + enum: [file, http, https, ftp, expect, php, jar, data, gopher, other] + description: "Protocol handler used in payload" + success: + type: boolean + description: "Whether payload was successful" + response_length: + type: int + description: "Length of response in bytes" + oob_interaction: + type: boolean + description: "Whether OOB interaction was observed" + +edges: + HAS_VULNERABILITY: + description: "A target has or is affected by a vulnerability" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When vulnerability was identified" confidence: type: float - description: "Confidence score" + description: "Confidence in the vulnerability" min: 0.0 max: 1.0 - method: + verified: + type: boolean + description: "Whether vulnerability was verified through exploitation" + + USED_AGAINST: + description: "A tool or technique was used against a target" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When tool was used" + success: + type: boolean + description: "Whether the use was successful" + execution_context: + type: string + description: "Context of tool usage (command line, parameters)" + + EXPLOITS: + description: "A technique or exploit code exploits a vulnerability" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When exploitation occurred" + success: + type: boolean + description: "Whether exploitation was successful" + impact: + type: string + enum: [full_compromise, partial_access, information_disclosure, denial_of_service, none] + description: "Impact of successful exploitation" + + DISCOVERED_IN: + description: "A finding was discovered during a test phase" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When discovery occurred" + discovery_method: + type: string + description: "How the finding was discovered" + + LEADS_TO: + description: "One finding, technique, or vulnerability leads to another (attack chain)" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When connection was established" + reasoning: + type: string + description: "How one leads to the other" + + TARGETS: + description: "A vulnerability, technique, or tool targets a specific target" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When targeting occurred" + + PROVIDES_ACCESS_TO: + description: "A credential provides access to a target or service" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When access was verified" + access_level: + type: string + enum: [read_only, read_write, administrative, root, limited] + description: "Level of access provided" + + YIELDS: + description: "An action, tool use, or technique yields a finding" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When finding was produced" + + USES_TOOL: + description: "A technique or attack uses a specific tool" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When tool was used" + + AUTHENTICATED_WITH: + description: "A credential was used to authenticate against a target" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When authentication occurred" + success: + type: boolean + description: "Whether authentication succeeded" + session_created: type: string - description: "Discovery method" - enum: [active, passive] + description: "Session ID created (if applicable)" + + EXTRACTED_FROM: + description: "A finding was extracted from a target using a specific technique" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When extraction occurred" + extraction_method: + type: string + description: "Method used for extraction (e.g., error-based SQLi)" + + ENUMERATED: + description: "A tool enumerated database metadata" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When enumeration occurred" + records_found: + type: int + description: "Number of records/items found" + + ESTABLISHES: + description: "An authentication attempt establishes a session" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When session was established" + + ACCESSED_FILE: + description: "An attack technique or exploit accessed a file" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When file was accessed" + bytes_read: + type: int + description: "Number of bytes read if applicable" + + REVEALED: + description: "A file system access revealed information or findings" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When information was revealed" + revelation_type: + type: string + enum: [credentials, configuration, system_info, vulnerability, other] + description: "Type of information revealed" + + USES_PAYLOAD: + description: "An exploitation attempt uses a specific XML payload" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When payload was used" + attempt_number: + type: int + description: "Sequential attempt number" + + OOB_INTERACTION: + description: "An XML payload triggered an out-of-band interaction" + fields: + version: + type: int + description: "Taxonomy schema version" + timestamp: + type: timestamp + description: "When interaction occurred" + interaction_type: + type: string + enum: [http_callback, dns_query, ftp_connection, other] + description: "Type of OOB interaction" + data_exfiltrated: + type: string + description: "Data exfiltrated via OOB channel (preview)" relationships: + # Target relationships - source: Target - target: Port - edges: [HAS_PORT] - + target: Vulnerability + edges: [HAS_VULNERABILITY] + + - source: Target + target: TechnicalFinding + edges: [YIELDS] + + - source: Target + target: Target + edges: [LEADS_TO] # For lateral movement or pivot chains + + # Vulnerability relationships + - source: Vulnerability + target: Target + edges: [TARGETS] + + # Tool relationships + - source: Tool + target: Target + edges: [USED_AGAINST] + + - source: Tool + target: TechnicalFinding + edges: [YIELDS] + + - source: Tool + target: Vulnerability + edges: [YIELDS] + + # Technique relationships + - source: AttackTechnique + target: Target + edges: [USED_AGAINST] + + - source: AttackTechnique + target: Vulnerability + edges: [EXPLOITS] + + - source: AttackTechnique + target: Tool + edges: [USES_TOOL] + + - source: AttackTechnique + target: AttackTechnique + edges: [LEADS_TO] # For attack chains + + # Finding relationships + - source: TechnicalFinding + target: TestPhase + edges: [DISCOVERED_IN] + + - source: TechnicalFinding + target: Vulnerability + edges: [LEADS_TO] + + - source: TechnicalFinding + target: TechnicalFinding + edges: [LEADS_TO] # Findings that lead to other findings + + # Credential relationships + - source: Credential + target: Target + edges: [PROVIDES_ACCESS_TO] + + - source: TechnicalFinding + target: Credential + edges: [REVEALED] + + # Exploit code relationships + - source: ExploitCode + target: Vulnerability + edges: [EXPLOITS] + + - source: ExploitCode + target: Target + edges: [USED_AGAINST] + + # Test phase relationships + - source: TestPhase + target: TestPhase + edges: [LEADS_TO] # Sequential phases + + # Authentication relationships + - source: AuthenticationAttempt + target: Target + edges: [USED_AGAINST] + + - source: AuthenticationAttempt + target: SessionInfo + edges: [ESTABLISHES] + + # Database metadata relationships + - source: DatabaseMetadata + target: Target + edges: [EXTRACTED_FROM] + + - source: Tool + target: DatabaseMetadata + edges: [ENUMERATED] + + # Exploitation attempt relationships + - source: ExploitationAttempt + target: Target + edges: [USED_AGAINST] + + - source: ExploitationAttempt + target: Vulnerability + edges: [EXPLOITS] + + - source: ExploitationAttempt + target: TechnicalFinding + edges: [YIELDS] + + # Session relationships + - source: SessionInfo + target: Target + edges: [PROVIDES_ACCESS_TO] + + - source: Credential + target: Target + edges: [AUTHENTICATED_WITH] + + # File system access relationships + - source: FileSystemAccess + target: Target + edges: [EXTRACTED_FROM] + + - source: AttackTechnique + target: FileSystemAccess + edges: [ACCESSED_FILE] + + - source: ExploitationAttempt + target: FileSystemAccess + edges: [ACCESSED_FILE] + + - source: FileSystemAccess + target: TechnicalFinding + edges: [REVEALED] + + - source: FileSystemAccess + target: Credential + edges: [REVEALED] + + # XML payload relationships + - source: XMLPayload + target: Vulnerability + edges: [EXPLOITS] + + - source: ExploitationAttempt + target: XMLPayload + edges: [USES_PAYLOAD] + + - source: XMLPayload + target: Target + edges: [USED_AGAINST] + + - source: XMLPayload + target: FileSystemAccess + edges: [ACCESSED_FILE] + + - source: XMLPayload + target: TechnicalFinding + edges: [OOB_INTERACTION] diff --git a/v1/go/entities/entities.go b/v1/go/entities/entities.go index 567e0bc..448c3f8 100644 --- a/v1/go/entities/entities.go +++ b/v1/go/entities/entities.go @@ -3,38 +3,304 @@ package entities -// Target A target system being assessed during penetration testing +// Target Network endpoint, service, application, or host being assessed. Should include version information, technology stack, and network details (IP, port, protocol). Examples: 'phpMyAdmin 4.4.15.6 on 172.22.0.7:80', 'Apache 2.4.29 web server' type Target struct { - Version *int `json:"version,omitempty"` // Taxonomy schema version (auto-injected by Graphiti fork) + Version *int `json:"version,omitempty"` // Taxonomy schema version EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier - Hostname *string `json:"hostname,omitempty"` // DNS hostname if known - IpAddress *string `json:"ip_address,omitempty" validate:"omitempty,ipv4"` // IP address of the target - TargetType *string `json:"target_type,omitempty" validate:"omitempty,oneof=host web_service api"` // Classification of target - RiskScore *float64 `json:"risk_score,omitempty" validate:"omitempty,min=0.0,max=10.0"` // Calculated risk score - Status *string `json:"status,omitempty" validate:"omitempty,oneof=active inactive"` // Current status + Identifier *string `json:"identifier,omitempty"` // Primary identifier (hostname, IP, URL) + TargetType *string `json:"target_type,omitempty" validate:"omitempty,oneof=host service web_application api_endpoint network_range container"` // Type of target + Hostname *string `json:"hostname,omitempty"` // DNS hostname if applicable + IpAddress *string `json:"ip_address,omitempty" validate:"omitempty,ipv4"` // IP address if applicable + Port *int `json:"port,omitempty" validate:"omitempty,min=1,max=65535"` // Port number if service-specific + Protocol *string `json:"protocol,omitempty"` // Protocol (HTTP, HTTPS, SSH, etc.) + TechnologyStack *[]*string `json:"technology_stack,omitempty"` // Technologies detected (PHP, Apache, MySQL, etc.) + Status *string `json:"status,omitempty" validate:"omitempty,oneof=discovered active compromised analyzed unreachable"` // Current assessment status } -// Port A network port on a target system -type Port struct { - Version *int `json:"version,omitempty"` // Taxonomy schema version (auto-injected by Graphiti fork) +// Vulnerability Security weakness or attack vector with CVE identifier, vulnerability class, or technical description. Should include severity assessment, exploitability status, version linkage, and test confirmation. Examples: 'CVE-2016-10134 SQLi in jsrpc.php profileIdx', 'XML External Entity (XXE) injection in document parser' +type Vulnerability struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier - PortNumber *int `json:"port_number,omitempty" validate:"omitempty,min=1,max=65535"` // Port number - Protocol *string `json:"protocol,omitempty" validate:"omitempty,oneof=tcp udp"` // Network protocol - State *string `json:"state,omitempty" validate:"omitempty,oneof=open closed filtered"` // Port state + VulnerabilityName *string `json:"vulnerability_name,omitempty"` // Vulnerability name or title + VulnerabilityClass *string `json:"vulnerability_class,omitempty" validate:"omitempty,oneof=sql_injection rce xss xxe ssrf lfi rfi csrf auth_bypass file_upload command_injection buffer_overflow directory_traversal privilege_escalation information_disclosure denial_of_service deserialization path_traversal session_hijacking other"` // OWASP/CWE category of vulnerability + CveId *string `json:"cve_id,omitempty"` // CVE identifier if applicable + CvssScore *float64 `json:"cvss_score,omitempty" validate:"omitempty,min=0.0,max=10.0"` // CVSS score if available + Severity *string `json:"severity,omitempty" validate:"omitempty,oneof=critical high medium low info"` // Severity assessment + Exploitability *string `json:"exploitability,omitempty" validate:"omitempty,oneof=confirmed_exploitable likely_exploitable theoretical not_exploitable unknown"` // Whether vulnerability can be exploited + Description *string `json:"description,omitempty"` // Technical description of the vulnerability + ExploitationTechniquesTested *[]*string `json:"exploitation_techniques_tested,omitempty"` // List of exploitation techniques attempted (e.g., error-based SQLi, time-based SQLi, XXE file read) + SuccessfulTechniques *[]*string `json:"successful_techniques,omitempty"` // Techniques that successfully exploited this vulnerability + FailedTechniques *[]*string `json:"failed_techniques,omitempty"` // Techniques that failed to exploit this vulnerability + XxeParserType *string `json:"xxe_parser_type,omitempty"` // XML parser type if XXE vulnerability (lxml, libxml2, Xerces, etc.) + XxeProtocolHandlers *[]*string `json:"xxe_protocol_handlers,omitempty"` // Available protocol handlers for XXE (file, http, ftp, expect, php, jar) + XxeOobConfirmed *bool `json:"xxe_oob_confirmed,omitempty"` // Whether out-of-band XXE interaction was confirmed } -// HasPort A target has a port -type HasPort struct { - Version *int `json:"version,omitempty"` // Taxonomy schema version (auto-injected by Graphiti fork) - Timestamp *float64 `json:"timestamp,omitempty"` // When association was established +// Tool Executable scanner, testing tool, or exploitation framework. Extract when tool produces actionable results; note success/failure status. Examples: 'sqlmap', 'nmap', 'metasploit', 'Burp Suite' +type Tool struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + ToolName *string `json:"tool_name,omitempty"` // Tool name (nmap, sqlmap, metasploit, etc.) + ToolCategory *string `json:"tool_category,omitempty" validate:"omitempty,oneof=scanner exploitation_framework fuzzer reconnaissance enumeration post_exploitation password_cracker web_proxy network_tool custom_script"` // Category of tool + VersionUsed *string `json:"version_used,omitempty"` // Version of the tool used + Purpose *string `json:"purpose,omitempty"` // What the tool was used for in this context +} + +// TechnicalFinding Specific security observation or test result. Summarize concisely (max 500 chars), include confidence level, prioritize findings that advance the assessment narrative. Examples: '113 DB tables enumerated via error-based SQLi', '/etc/passwd accessed via XXE: 48 users listed', 'phpMyAdmin version 4.4.15.6 disclosed in HTTP headers' +type TechnicalFinding struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + FindingType *string `json:"finding_type,omitempty" validate:"omitempty,oneof=version_disclosure open_port exposed_endpoint configuration_issue credential sensitive_data exploit_success reconnaissance_data vulnerability_confirmation patch_status service_banner database_enumeration authentication_result"` // Type of finding + Title *string `json:"title,omitempty"` // Brief title of the finding + Content *string `json:"content,omitempty"` // Detailed finding content (sanitized and summarized) + Confidence *float64 `json:"confidence,omitempty" validate:"omitempty,min=0.0,max=1.0"` // Confidence in the finding + Severity *string `json:"severity,omitempty" validate:"omitempty,oneof=critical high medium low info"` // Severity of the finding + Evidence *string `json:"evidence,omitempty"` // Key evidence supporting the finding (truncated) + ExtractionTechnique *string `json:"extraction_technique,omitempty"` // How data was extracted (e.g., error-based SQLi, time-based, manual) + DataType *string `json:"data_type,omitempty" validate:"omitempty,oneof=database_schema user_info configuration privileges file_content command_output network_data session_info other"` // Type of data in this finding +} + +// AttackTechnique Specific exploitation method with technical details and payload information. Should map to MITRE ATT&CK taxonomy when applicable, record success/failure, and include actual payloads used. Examples: 'Error-based SQLi via updatexml()', 'Time-based blind SQLi with sleep()', 'Out-of-band XXE data exfiltration' +type AttackTechnique struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + AttackTechniqueName *string `json:"attack_technique_name,omitempty"` // Name of the attack technique + TechniqueCategory *string `json:"technique_category,omitempty" validate:"omitempty,oneof=initial_access execution persistence privilege_escalation defense_evasion credential_access discovery lateral_movement collection exfiltration impact"` // MITRE ATT&CK category + Description *string `json:"description,omitempty"` // Description of how the technique works + Payload *string `json:"payload,omitempty"` // Actual payload or command used (sanitized) + SuccessIndicator *string `json:"success_indicator,omitempty"` // What indicates successful execution +} + +// TestPhase A phase or stage of the penetration testing engagement +type TestPhase struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + TestPhaseName *string `json:"test_phase_name,omitempty" validate:"omitempty,oneof=reconnaissance scanning enumeration vulnerability_analysis exploitation post_exploitation reporting cleanup"` // Name of the test phase + Objective *string `json:"objective,omitempty"` // Objective of this phase + Status *string `json:"status,omitempty" validate:"omitempty,oneof=not_started in_progress completed blocked skipped"` // Status of the phase + StartTimestamp *float64 `json:"start_timestamp,omitempty"` // When phase started + EndTimestamp *float64 `json:"end_timestamp,omitempty"` // When phase completed +} + +// Credential Actual authentication credentials with values (ALWAYS extract, including default credentials). Should include privilege level, discovery source, authentication status, and session tokens when applicable. Examples: 'Admin/zabbix', 'root/password', 'zbx_sessionid=0a0f93de...', 'API key: sk-abc123...' +type Credential struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + CredentialType *string `json:"credential_type,omitempty" validate:"omitempty,oneof=username_password api_key token ssh_key certificate hash cookie"` // Type of credential + Username *string `json:"username,omitempty"` // Username if applicable + IsValid *bool `json:"is_valid,omitempty"` // Whether credential is valid + IsDefault *bool `json:"is_default,omitempty"` // Whether this is a default credential (e.g., Admin/zabbix) + PrivilegeLevel *string `json:"privilege_level,omitempty" validate:"omitempty,oneof=admin user guest service_account root unknown"` // Privilege level of the credential + Source *string `json:"source,omitempty"` // How the credential was obtained + AuthenticationState *string `json:"authentication_state,omitempty" validate:"omitempty,oneof=success failure requires_2fa locked expired unknown"` // Result of authentication attempt with this credential +} + +// ExploitCode Actual exploit code, script, or payload used during testing. Should reference target vulnerability, include programming language, and document purpose/objective. Can be proof-of-concept, weaponized exploit, web shell, or reconnaissance script. +type ExploitCode struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + ExploitCodeName *string `json:"exploit_code_name,omitempty"` // Name of the exploit + Language *string `json:"language,omitempty" validate:"omitempty,oneof=python bash php ruby powershell javascript go other"` // Programming language + Purpose *string `json:"purpose,omitempty"` // What the exploit is designed to achieve + FilePath *string `json:"file_path,omitempty"` // Path where exploit was saved + CodeType *string `json:"code_type,omitempty" validate:"omitempty,oneof=proof_of_concept weaponized_exploit web_shell reverse_shell payload script reconnaissance_tool"` // Type of code +} + +// AuthenticationAttempt Login attempt (success or failure), session establishment (cookies/tokens/CSRF), credential validation, or bypass attempt. Should capture authentication state changes, privilege levels obtained, session tokens, and response details. +type AuthenticationAttempt struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + Timestamp *float64 `json:"timestamp,omitempty"` // When authentication was attempted + Success *bool `json:"success,omitempty"` // Whether authentication succeeded + CredentialUsed *string `json:"credential_used,omitempty"` // Reference to credential entity used + SessionEstablished *bool `json:"session_established,omitempty"` // Whether a session was established + ResponseCode *int `json:"response_code,omitempty"` // HTTP response code if applicable + ErrorMessage *string `json:"error_message,omitempty"` // Error message if authentication failed +} + +// DatabaseMetadata Database configuration, schema, and structure information. Should include SQLi payload types used for extraction, enumeration results (tables/columns), user privileges, configuration details, and technique comparisons. Avoid duplicate error entries. Examples: 'MySQL 5.7.33 with FILE privilege', '113 tables enumerated: users, sessions, config, logs...' +type DatabaseMetadata struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + DatabaseType *string `json:"database_type,omitempty" validate:"omitempty,oneof=mysql postgresql mssql oracle mongodb redis other"` // Type of database + DatabaseVersion *string `json:"database_version,omitempty"` // Database version if known + DatabaseUser *string `json:"database_user,omitempty"` // Database user (e.g., root@172.22.0.7) + TableCount *int `json:"table_count,omitempty"` // Number of tables discovered + TableNames *[]*string `json:"table_names,omitempty"` // List of table names discovered + Privileges *[]*string `json:"privileges,omitempty"` // User privileges (e.g., FILE, SELECT, INSERT) + SecureFilePriv *string `json:"secure_file_priv,omitempty"` // secure_file_priv setting value + ConfigurationDetails *string `json:"configuration_details,omitempty"` // Other relevant configuration information +} + +// ExploitationAttempt A specific exploitation attempt with a technique +type ExploitationAttempt struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + Timestamp *float64 `json:"timestamp,omitempty"` // When exploitation was attempted + TechniqueType *string `json:"technique_type,omitempty" validate:"omitempty,oneof=error_based_sqli time_based_sqli boolean_based_sqli union_based_sqli file_inclusion command_injection xxe buffer_overflow other"` // Type of exploitation technique + Success *bool `json:"success,omitempty"` // Whether exploitation succeeded + Payload *string `json:"payload,omitempty"` // Payload used (sanitized) + ResponseHash *string `json:"response_hash,omitempty"` // Hash of response for deduplication + ResultSummary *string `json:"result_summary,omitempty"` // Summary of what happened +} + +// SessionInfo Session tokens, cookies, and authentication state AFTER successful authentication +type SessionInfo struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + SessionType *string `json:"session_type,omitempty" validate:"omitempty,oneof=cookie token jwt oauth api_key other"` // Type of session mechanism + SessionId *string `json:"session_id,omitempty"` // Session identifier (e.g., zbx_sessionid value) + CsrfToken *string `json:"csrf_token,omitempty"` // CSRF token if applicable + EstablishedAt *float64 `json:"established_at,omitempty"` // When session was established + ExpiresAt *float64 `json:"expires_at,omitempty"` // When session expires (if known) + PrivilegeLevel *string `json:"privilege_level,omitempty" validate:"omitempty,oneof=guest user admin root unknown"` // Privilege level of this session +} + +// FileSystemAccess File system access attempt and result. For successful reads, include file path and content preview. Document permission boundaries, file types accessed, and sensitivity level. Skip duplicate permission denials (keep first only) and verbose methodology without results. Examples: '/etc/passwd read: 48 user accounts', 'SSH private key found at /root/.ssh/id_rsa' +type FileSystemAccess struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + FilePath *string `json:"file_path,omitempty"` // Path to file or directory accessed + AccessType *string `json:"access_type,omitempty" validate:"omitempty,oneof=read write execute list stat"` // Type of access attempted + Success *bool `json:"success,omitempty"` // Whether access was successful + AccessMethod *string `json:"access_method,omitempty" validate:"omitempty,oneof=xxe lfi rfi command_injection direct_access path_traversal"` // Method used to access file + ContentPreview *string `json:"content_preview,omitempty"` // Preview of file content if read (truncated to 500 chars) + PermissionError *string `json:"permission_error,omitempty"` // Permission error message if access denied + FileType *string `json:"file_type,omitempty" validate:"omitempty,oneof=config credential log system_info ssh_key source_code database other"` // Type of file accessed + Sensitivity *string `json:"sensitivity,omitempty" validate:"omitempty,oneof=critical high medium low info"` // Sensitivity level of accessed file +} + +// XMLPayload XML payload used in XXE exploitation. Should identify XML parser (type/version), protocol handlers available (file/http/ftp/expect/php/jar), successful file reads, OOB interaction confirmations, payload variations tested, and parser configuration. Examples: 'XXE file:// payload reading /etc/passwd', 'OOB XXE via HTTP callback to attacker.com' +type XMLPayload struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + EntityUuid *string `json:"entity_uuid,omitempty"` // Unique identifier + PayloadType *string `json:"payload_type,omitempty" validate:"omitempty,oneof=file_read oob_exfil rce_attempt ssrf entity_expansion parameter_entity"` // Type of XXE payload + PayloadContent *string `json:"payload_content,omitempty"` // Actual XML payload (sanitized) + Encoding *string `json:"encoding,omitempty" validate:"omitempty,oneof=utf-8 utf-16 utf-16be base64 other"` // Payload encoding + ProtocolHandler *string `json:"protocol_handler,omitempty" validate:"omitempty,oneof=file http https ftp expect php jar data gopher other"` // Protocol handler used in payload + Success *bool `json:"success,omitempty"` // Whether payload was successful + ResponseLength *int `json:"response_length,omitempty"` // Length of response in bytes + OobInteraction *bool `json:"oob_interaction,omitempty"` // Whether OOB interaction was observed +} + +// HasVulnerability A target has or is affected by a vulnerability +type HasVulnerability struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When vulnerability was identified + Confidence *float64 `json:"confidence,omitempty" validate:"omitempty,min=0.0,max=1.0"` // Confidence in the vulnerability + Verified *bool `json:"verified,omitempty"` // Whether vulnerability was verified through exploitation +} + +// UsedAgainst A tool or technique was used against a target +type UsedAgainst struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When tool was used + Success *bool `json:"success,omitempty"` // Whether the use was successful + ExecutionContext *string `json:"execution_context,omitempty"` // Context of tool usage (command line, parameters) +} + +// Exploits A technique or exploit code exploits a vulnerability +type Exploits struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When exploitation occurred + Success *bool `json:"success,omitempty"` // Whether exploitation was successful + Impact *string `json:"impact,omitempty" validate:"omitempty,oneof=full_compromise partial_access information_disclosure denial_of_service none"` // Impact of successful exploitation +} + +// DiscoveredIn A finding was discovered during a test phase +type DiscoveredIn struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When discovery occurred + DiscoveryMethod *string `json:"discovery_method,omitempty"` // How the finding was discovered +} + +// LeadsTo One finding, technique, or vulnerability leads to another (attack chain) +type LeadsTo struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When connection was established + Reasoning *string `json:"reasoning,omitempty"` // How one leads to the other +} + +// Targets A vulnerability, technique, or tool targets a specific target +type Targets struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When targeting occurred +} + +// ProvidesAccessTo A credential provides access to a target or service +type ProvidesAccessTo struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When access was verified + AccessLevel *string `json:"access_level,omitempty" validate:"omitempty,oneof=read_only read_write administrative root limited"` // Level of access provided +} + +// Yields An action, tool use, or technique yields a finding +type Yields struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When finding was produced +} + +// UsesTool A technique or attack uses a specific tool +type UsesTool struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When tool was used +} + +// AuthenticatedWith A credential was used to authenticate against a target +type AuthenticatedWith struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When authentication occurred + Success *bool `json:"success,omitempty"` // Whether authentication succeeded + SessionCreated *string `json:"session_created,omitempty"` // Session ID created (if applicable) +} + +// ExtractedFrom A finding was extracted from a target using a specific technique +type ExtractedFrom struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When extraction occurred + ExtractionMethod *string `json:"extraction_method,omitempty"` // Method used for extraction (e.g., error-based SQLi) +} + +// Enumerated A tool enumerated database metadata +type Enumerated struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When enumeration occurred + RecordsFound *int `json:"records_found,omitempty"` // Number of records/items found +} + +// Establishes An authentication attempt establishes a session +type Establishes struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When session was established +} + +// AccessedFile An attack technique or exploit accessed a file +type AccessedFile struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When file was accessed + BytesRead *int `json:"bytes_read,omitempty"` // Number of bytes read if applicable +} + +// Revealed A file system access revealed information or findings +type Revealed struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When information was revealed + RevelationType *string `json:"revelation_type,omitempty" validate:"omitempty,oneof=credentials configuration system_info vulnerability other"` // Type of information revealed +} + +// UsesPayload An exploitation attempt uses a specific XML payload +type UsesPayload struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When payload was used + AttemptNumber *int `json:"attempt_number,omitempty"` // Sequential attempt number } -// Discovered An action discovered an entity -type Discovered struct { - Version *int `json:"version,omitempty"` // Taxonomy schema version (auto-injected by Graphiti fork) - Timestamp *float64 `json:"timestamp,omitempty"` // Discovery timestamp - Confidence *float64 `json:"confidence,omitempty" validate:"omitempty,min=0.0,max=1.0"` // Confidence score - Method *string `json:"method,omitempty" validate:"omitempty,oneof=active passive"` // Discovery method +// OobInteraction An XML payload triggered an out-of-band interaction +type OobInteraction struct { + Version *int `json:"version,omitempty"` // Taxonomy schema version + Timestamp *float64 `json:"timestamp,omitempty"` // When interaction occurred + InteractionType *string `json:"interaction_type,omitempty" validate:"omitempty,oneof=http_callback dns_query ftp_connection other"` // Type of OOB interaction + DataExfiltrated *string `json:"data_exfiltrated,omitempty"` // Data exfiltrated via OOB channel (preview) } diff --git a/v1/go/entities/validators.go b/v1/go/entities/validators.go index 22b555f..db30492 100644 --- a/v1/go/entities/validators.go +++ b/v1/go/entities/validators.go @@ -22,18 +22,153 @@ func (e *Target) Validate() error { return Validator.Struct(e) } -// Validate validates a Port entity -func (e *Port) Validate() error { +// Validate validates a Vulnerability entity +func (e *Vulnerability) Validate() error { return Validator.Struct(e) } -// Validate validates a HasPort edge -func (e *HasPort) Validate() error { +// Validate validates a Tool entity +func (e *Tool) Validate() error { return Validator.Struct(e) } -// Validate validates a Discovered edge -func (e *Discovered) Validate() error { +// Validate validates a TechnicalFinding entity +func (e *TechnicalFinding) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a AttackTechnique entity +func (e *AttackTechnique) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a TestPhase entity +func (e *TestPhase) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Credential entity +func (e *Credential) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a ExploitCode entity +func (e *ExploitCode) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a AuthenticationAttempt entity +func (e *AuthenticationAttempt) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a DatabaseMetadata entity +func (e *DatabaseMetadata) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a ExploitationAttempt entity +func (e *ExploitationAttempt) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a SessionInfo entity +func (e *SessionInfo) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a FileSystemAccess entity +func (e *FileSystemAccess) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a XMLPayload entity +func (e *XMLPayload) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a HasVulnerability edge +func (e *HasVulnerability) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a UsedAgainst edge +func (e *UsedAgainst) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Exploits edge +func (e *Exploits) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a DiscoveredIn edge +func (e *DiscoveredIn) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a LeadsTo edge +func (e *LeadsTo) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Targets edge +func (e *Targets) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a ProvidesAccessTo edge +func (e *ProvidesAccessTo) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Yields edge +func (e *Yields) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a UsesTool edge +func (e *UsesTool) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a AuthenticatedWith edge +func (e *AuthenticatedWith) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a ExtractedFrom edge +func (e *ExtractedFrom) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Enumerated edge +func (e *Enumerated) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Establishes edge +func (e *Establishes) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a AccessedFile edge +func (e *AccessedFile) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a Revealed edge +func (e *Revealed) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a UsesPayload edge +func (e *UsesPayload) Validate() error { + return Validator.Struct(e) +} + +// Validate validates a OobInteraction edge +func (e *OobInteraction) Validate() error { return Validator.Struct(e) } diff --git a/v1/python/pentagi_taxonomy/edges.py b/v1/python/pentagi_taxonomy/edges.py index 12339a3..4d62dd1 100644 --- a/v1/python/pentagi_taxonomy/edges.py +++ b/v1/python/pentagi_taxonomy/edges.py @@ -6,15 +6,106 @@ from pydantic import BaseModel, Field from typing import Literal -class HasPort(BaseModel): - """A target has a port""" - version: int | None = Field(None, description='Taxonomy schema version (auto-injected by Graphiti fork)') - timestamp: float | None = Field(None, description='When association was established') - -class Discovered(BaseModel): - """An action discovered an entity""" - version: int | None = Field(None, description='Taxonomy schema version (auto-injected by Graphiti fork)') - timestamp: float | None = Field(None, description='Discovery timestamp') - confidence: float | None = Field(None, description='Confidence score', ge=0.0, le=1.0) - method: Literal['active', 'passive'] | None = Field(None, description='Discovery method') +class HasVulnerability(BaseModel): + """A target has or is affected by a vulnerability""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When vulnerability was identified') + confidence: float | None = Field(None, description='Confidence in the vulnerability', ge=0.0, le=1.0) + verified: bool | None = Field(None, description='Whether vulnerability was verified through exploitation') + +class UsedAgainst(BaseModel): + """A tool or technique was used against a target""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When tool was used') + success: bool | None = Field(None, description='Whether the use was successful') + execution_context: str | None = Field(None, description='Context of tool usage (command line, parameters)') + +class Exploits(BaseModel): + """A technique or exploit code exploits a vulnerability""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When exploitation occurred') + success: bool | None = Field(None, description='Whether exploitation was successful') + impact: Literal['full_compromise', 'partial_access', 'information_disclosure', 'denial_of_service', 'none'] | None = Field(None, description='Impact of successful exploitation') + +class DiscoveredIn(BaseModel): + """A finding was discovered during a test phase""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When discovery occurred') + discovery_method: str | None = Field(None, description='How the finding was discovered') + +class LeadsTo(BaseModel): + """One finding, technique, or vulnerability leads to another (attack chain)""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When connection was established') + reasoning: str | None = Field(None, description='How one leads to the other') + +class Targets(BaseModel): + """A vulnerability, technique, or tool targets a specific target""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When targeting occurred') + +class ProvidesAccessTo(BaseModel): + """A credential provides access to a target or service""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When access was verified') + access_level: Literal['read_only', 'read_write', 'administrative', 'root', 'limited'] | None = Field(None, description='Level of access provided') + +class Yields(BaseModel): + """An action, tool use, or technique yields a finding""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When finding was produced') + +class UsesTool(BaseModel): + """A technique or attack uses a specific tool""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When tool was used') + +class AuthenticatedWith(BaseModel): + """A credential was used to authenticate against a target""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When authentication occurred') + success: bool | None = Field(None, description='Whether authentication succeeded') + session_created: str | None = Field(None, description='Session ID created (if applicable)') + +class ExtractedFrom(BaseModel): + """A finding was extracted from a target using a specific technique""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When extraction occurred') + extraction_method: str | None = Field(None, description='Method used for extraction (e.g., error-based SQLi)') + +class Enumerated(BaseModel): + """A tool enumerated database metadata""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When enumeration occurred') + records_found: int | None = Field(None, description='Number of records/items found') + +class Establishes(BaseModel): + """An authentication attempt establishes a session""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When session was established') + +class AccessedFile(BaseModel): + """An attack technique or exploit accessed a file""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When file was accessed') + bytes_read: int | None = Field(None, description='Number of bytes read if applicable') + +class Revealed(BaseModel): + """A file system access revealed information or findings""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When information was revealed') + revelation_type: Literal['credentials', 'configuration', 'system_info', 'vulnerability', 'other'] | None = Field(None, description='Type of information revealed') + +class UsesPayload(BaseModel): + """An exploitation attempt uses a specific XML payload""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When payload was used') + attempt_number: int | None = Field(None, description='Sequential attempt number') + +class OobInteraction(BaseModel): + """An XML payload triggered an out-of-band interaction""" + version: int | None = Field(None, description='Taxonomy schema version') + timestamp: float | None = Field(None, description='When interaction occurred') + interaction_type: Literal['http_callback', 'dns_query', 'ftp_connection', 'other'] | None = Field(None, description='Type of OOB interaction') + data_exfiltrated: str | None = Field(None, description='Data exfiltrated via OOB channel (preview)') diff --git a/v1/python/pentagi_taxonomy/entity_map.py b/v1/python/pentagi_taxonomy/entity_map.py index 5552afa..584791c 100644 --- a/v1/python/pentagi_taxonomy/entity_map.py +++ b/v1/python/pentagi_taxonomy/entity_map.py @@ -3,19 +3,83 @@ DO NOT EDIT - this file is generated from entities.yml """ -from .nodes import Target, Port -from .edges import HasPort, Discovered +from .nodes import Target, Vulnerability, Tool, TechnicalFinding, AttackTechnique, TestPhase, Credential, ExploitCode, AuthenticationAttempt, DatabaseMetadata, ExploitationAttempt, SessionInfo, FileSystemAccess, XMLPayload +from .edges import HasVulnerability, UsedAgainst, Exploits, DiscoveredIn, LeadsTo, Targets, ProvidesAccessTo, Yields, UsesTool, AuthenticatedWith, ExtractedFrom, Enumerated, Establishes, AccessedFile, Revealed, UsesPayload, OobInteraction ENTITY_TYPES = { 'Target': Target, - 'Port': Port, + 'Vulnerability': Vulnerability, + 'Tool': Tool, + 'TechnicalFinding': TechnicalFinding, + 'AttackTechnique': AttackTechnique, + 'TestPhase': TestPhase, + 'Credential': Credential, + 'ExploitCode': ExploitCode, + 'AuthenticationAttempt': AuthenticationAttempt, + 'DatabaseMetadata': DatabaseMetadata, + 'ExploitationAttempt': ExploitationAttempt, + 'SessionInfo': SessionInfo, + 'FileSystemAccess': FileSystemAccess, + 'XMLPayload': XMLPayload, } EDGE_TYPES = { - 'HAS_PORT': HasPort, - 'DISCOVERED': Discovered, + 'HAS_VULNERABILITY': HasVulnerability, + 'USED_AGAINST': UsedAgainst, + 'EXPLOITS': Exploits, + 'DISCOVERED_IN': DiscoveredIn, + 'LEADS_TO': LeadsTo, + 'TARGETS': Targets, + 'PROVIDES_ACCESS_TO': ProvidesAccessTo, + 'YIELDS': Yields, + 'USES_TOOL': UsesTool, + 'AUTHENTICATED_WITH': AuthenticatedWith, + 'EXTRACTED_FROM': ExtractedFrom, + 'ENUMERATED': Enumerated, + 'ESTABLISHES': Establishes, + 'ACCESSED_FILE': AccessedFile, + 'REVEALED': Revealed, + 'USES_PAYLOAD': UsesPayload, + 'OOB_INTERACTION': OobInteraction, } EDGE_TYPE_MAP = { - ('Target', 'Port'): ['HAS_PORT'], + ('Target', 'Vulnerability'): ['HAS_VULNERABILITY'], + ('Target', 'TechnicalFinding'): ['YIELDS'], + ('Target', 'Target'): ['LEADS_TO'], + ('Vulnerability', 'Target'): ['TARGETS'], + ('Tool', 'Target'): ['USED_AGAINST'], + ('Tool', 'TechnicalFinding'): ['YIELDS'], + ('Tool', 'Vulnerability'): ['YIELDS'], + ('AttackTechnique', 'Target'): ['USED_AGAINST'], + ('AttackTechnique', 'Vulnerability'): ['EXPLOITS'], + ('AttackTechnique', 'Tool'): ['USES_TOOL'], + ('AttackTechnique', 'AttackTechnique'): ['LEADS_TO'], + ('TechnicalFinding', 'TestPhase'): ['DISCOVERED_IN'], + ('TechnicalFinding', 'Vulnerability'): ['LEADS_TO'], + ('TechnicalFinding', 'TechnicalFinding'): ['LEADS_TO'], + ('Credential', 'Target'): ['PROVIDES_ACCESS_TO'], + ('TechnicalFinding', 'Credential'): ['REVEALED'], + ('ExploitCode', 'Vulnerability'): ['EXPLOITS'], + ('ExploitCode', 'Target'): ['USED_AGAINST'], + ('TestPhase', 'TestPhase'): ['LEADS_TO'], + ('AuthenticationAttempt', 'Target'): ['USED_AGAINST'], + ('AuthenticationAttempt', 'SessionInfo'): ['ESTABLISHES'], + ('DatabaseMetadata', 'Target'): ['EXTRACTED_FROM'], + ('Tool', 'DatabaseMetadata'): ['ENUMERATED'], + ('ExploitationAttempt', 'Target'): ['USED_AGAINST'], + ('ExploitationAttempt', 'Vulnerability'): ['EXPLOITS'], + ('ExploitationAttempt', 'TechnicalFinding'): ['YIELDS'], + ('SessionInfo', 'Target'): ['PROVIDES_ACCESS_TO'], + ('Credential', 'Target'): ['AUTHENTICATED_WITH'], + ('FileSystemAccess', 'Target'): ['EXTRACTED_FROM'], + ('AttackTechnique', 'FileSystemAccess'): ['ACCESSED_FILE'], + ('ExploitationAttempt', 'FileSystemAccess'): ['ACCESSED_FILE'], + ('FileSystemAccess', 'TechnicalFinding'): ['REVEALED'], + ('FileSystemAccess', 'Credential'): ['REVEALED'], + ('XMLPayload', 'Vulnerability'): ['EXPLOITS'], + ('ExploitationAttempt', 'XMLPayload'): ['USES_PAYLOAD'], + ('XMLPayload', 'Target'): ['USED_AGAINST'], + ('XMLPayload', 'FileSystemAccess'): ['ACCESSED_FILE'], + ('XMLPayload', 'TechnicalFinding'): ['OOB_INTERACTION'], } diff --git a/v1/python/pentagi_taxonomy/nodes.py b/v1/python/pentagi_taxonomy/nodes.py index 3b3d063..43d579f 100644 --- a/v1/python/pentagi_taxonomy/nodes.py +++ b/v1/python/pentagi_taxonomy/nodes.py @@ -7,20 +7,168 @@ from typing import Literal class Target(BaseModel): - """A target system being assessed during penetration testing""" - version: int | None = Field(None, description='Taxonomy schema version (auto-injected by Graphiti fork)') - entity_uuid: str | None = Field(None, description='Unique identifier') - hostname: str | None = Field(None, description='DNS hostname if known') - ip_address: str | None = Field(None, description='IP address of the target') - target_type: Literal['host', 'web_service', 'api'] | None = Field(None, description='Classification of target') - risk_score: float | None = Field(None, description='Calculated risk score', ge=0.0, le=10.0) - status: Literal['active', 'inactive'] | None = Field(None, description='Current status') - -class Port(BaseModel): - """A network port on a target system""" - version: int | None = Field(None, description='Taxonomy schema version (auto-injected by Graphiti fork)') - entity_uuid: str | None = Field(None, description='Unique identifier') - port_number: int | None = Field(None, description='Port number', ge=1, le=65535) - protocol: Literal['tcp', 'udp'] | None = Field(None, description='Network protocol') - state: Literal['open', 'closed', 'filtered'] | None = Field(None, description='Port state') + """Network endpoint, service, application, or host being assessed. Should include version information, technology stack, and network details (IP, port, protocol). Examples: 'phpMyAdmin 4.4.15.6 on 172.22.0.7:80', 'Apache 2.4.29 web server'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + identifier: str | None = Field(None, description='Primary identifier (hostname, IP, URL)') + target_type: Literal['host', 'service', 'web_application', 'api_endpoint', 'network_range', 'container'] | None = Field(None, description='Type of target') + hostname: str | None = Field(None, description='DNS hostname if applicable') + ip_address: str | None = Field(None, description='IP address if applicable') + port: int | None = Field(None, description='Port number if service-specific', ge=1, le=65535) + protocol: str | None = Field(None, description='Protocol (HTTP, HTTPS, SSH, etc.)') + technology_stack: list[str] | None = Field(None, description='Technologies detected (PHP, Apache, MySQL, etc.)') + status: Literal['discovered', 'active', 'compromised', 'analyzed', 'unreachable'] | None = Field(None, description='Current assessment status') + +class Vulnerability(BaseModel): + """Security weakness or attack vector with CVE identifier, vulnerability class, or technical description. Should include severity assessment, exploitability status, version linkage, and test confirmation. Examples: 'CVE-2016-10134 SQLi in jsrpc.php profileIdx', 'XML External Entity (XXE) injection in document parser'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + vulnerability_name: str | None = Field(None, description='Vulnerability name or title') + vulnerability_class: Literal['sql_injection', 'rce', 'xss', 'xxe', 'ssrf', 'lfi', 'rfi', 'csrf', 'auth_bypass', 'file_upload', 'command_injection', 'buffer_overflow', 'directory_traversal', 'privilege_escalation', 'information_disclosure', 'denial_of_service', 'deserialization', 'path_traversal', 'session_hijacking', 'other'] | None = Field(None, description='OWASP/CWE category of vulnerability') + cve_id: str | None = Field(None, description='CVE identifier if applicable') + cvss_score: float | None = Field(None, description='CVSS score if available', ge=0.0, le=10.0) + severity: Literal['critical', 'high', 'medium', 'low', 'info'] | None = Field(None, description='Severity assessment') + exploitability: Literal['confirmed_exploitable', 'likely_exploitable', 'theoretical', 'not_exploitable', 'unknown'] | None = Field(None, description='Whether vulnerability can be exploited') + description: str | None = Field(None, description='Technical description of the vulnerability') + exploitation_techniques_tested: list[str] | None = Field(None, description='List of exploitation techniques attempted (e.g., error-based SQLi, time-based SQLi, XXE file read)') + successful_techniques: list[str] | None = Field(None, description='Techniques that successfully exploited this vulnerability') + failed_techniques: list[str] | None = Field(None, description='Techniques that failed to exploit this vulnerability') + xxe_parser_type: str | None = Field(None, description='XML parser type if XXE vulnerability (lxml, libxml2, Xerces, etc.)') + xxe_protocol_handlers: list[str] | None = Field(None, description='Available protocol handlers for XXE (file, http, ftp, expect, php, jar)') + xxe_oob_confirmed: bool | None = Field(None, description='Whether out-of-band XXE interaction was confirmed') + +class Tool(BaseModel): + """Executable scanner, testing tool, or exploitation framework. Extract when tool produces actionable results; note success/failure status. Examples: 'sqlmap', 'nmap', 'metasploit', 'Burp Suite'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + tool_name: str | None = Field(None, description='Tool name (nmap, sqlmap, metasploit, etc.)') + tool_category: Literal['scanner', 'exploitation_framework', 'fuzzer', 'reconnaissance', 'enumeration', 'post_exploitation', 'password_cracker', 'web_proxy', 'network_tool', 'custom_script'] | None = Field(None, description='Category of tool') + version_used: str | None = Field(None, description='Version of the tool used') + purpose: str | None = Field(None, description='What the tool was used for in this context') + +class TechnicalFinding(BaseModel): + """Specific security observation or test result. Summarize concisely (max 500 chars), include confidence level, prioritize findings that advance the assessment narrative. Examples: '113 DB tables enumerated via error-based SQLi', '/etc/passwd accessed via XXE: 48 users listed', 'phpMyAdmin version 4.4.15.6 disclosed in HTTP headers'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + finding_type: Literal['version_disclosure', 'open_port', 'exposed_endpoint', 'configuration_issue', 'credential', 'sensitive_data', 'exploit_success', 'reconnaissance_data', 'vulnerability_confirmation', 'patch_status', 'service_banner', 'database_enumeration', 'authentication_result'] | None = Field(None, description='Type of finding') + title: str | None = Field(None, description='Brief title of the finding') + content: str | None = Field(None, description='Detailed finding content (sanitized and summarized)') + confidence: float | None = Field(None, description='Confidence in the finding', ge=0.0, le=1.0) + severity: Literal['critical', 'high', 'medium', 'low', 'info'] | None = Field(None, description='Severity of the finding') + evidence: str | None = Field(None, description='Key evidence supporting the finding (truncated)') + extraction_technique: str | None = Field(None, description='How data was extracted (e.g., error-based SQLi, time-based, manual)') + data_type: Literal['database_schema', 'user_info', 'configuration', 'privileges', 'file_content', 'command_output', 'network_data', 'session_info', 'other'] | None = Field(None, description='Type of data in this finding') + +class AttackTechnique(BaseModel): + """Specific exploitation method with technical details and payload information. Should map to MITRE ATT&CK taxonomy when applicable, record success/failure, and include actual payloads used. Examples: 'Error-based SQLi via updatexml()', 'Time-based blind SQLi with sleep()', 'Out-of-band XXE data exfiltration'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + attack_technique_name: str | None = Field(None, description='Name of the attack technique') + technique_category: Literal['initial_access', 'execution', 'persistence', 'privilege_escalation', 'defense_evasion', 'credential_access', 'discovery', 'lateral_movement', 'collection', 'exfiltration', 'impact'] | None = Field(None, description='MITRE ATT&CK category') + description: str | None = Field(None, description='Description of how the technique works') + payload: str | None = Field(None, description='Actual payload or command used (sanitized)') + success_indicator: str | None = Field(None, description='What indicates successful execution') + +class TestPhase(BaseModel): + """A phase or stage of the penetration testing engagement""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + test_phase_name: Literal['reconnaissance', 'scanning', 'enumeration', 'vulnerability_analysis', 'exploitation', 'post_exploitation', 'reporting', 'cleanup'] | None = Field(None, description='Name of the test phase') + objective: str | None = Field(None, description='Objective of this phase') + status: Literal['not_started', 'in_progress', 'completed', 'blocked', 'skipped'] | None = Field(None, description='Status of the phase') + start_timestamp: float | None = Field(None, description='When phase started') + end_timestamp: float | None = Field(None, description='When phase completed') + +class Credential(BaseModel): + """Actual authentication credentials with values (ALWAYS extract, including default credentials). Should include privilege level, discovery source, authentication status, and session tokens when applicable. Examples: 'Admin/zabbix', 'root/password', 'zbx_sessionid=0a0f93de...', 'API key: sk-abc123...'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + credential_type: Literal['username_password', 'api_key', 'token', 'ssh_key', 'certificate', 'hash', 'cookie'] | None = Field(None, description='Type of credential') + username: str | None = Field(None, description='Username if applicable') + is_valid: bool | None = Field(None, description='Whether credential is valid') + is_default: bool | None = Field(None, description='Whether this is a default credential (e.g., Admin/zabbix)') + privilege_level: Literal['admin', 'user', 'guest', 'service_account', 'root', 'unknown'] | None = Field(None, description='Privilege level of the credential') + source: str | None = Field(None, description='How the credential was obtained') + authentication_state: Literal['success', 'failure', 'requires_2fa', 'locked', 'expired', 'unknown'] | None = Field(None, description='Result of authentication attempt with this credential') + +class ExploitCode(BaseModel): + """Actual exploit code, script, or payload used during testing. Should reference target vulnerability, include programming language, and document purpose/objective. Can be proof-of-concept, weaponized exploit, web shell, or reconnaissance script.""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + exploit_code_name: str | None = Field(None, description='Name of the exploit') + language: Literal['python', 'bash', 'php', 'ruby', 'powershell', 'javascript', 'go', 'other'] | None = Field(None, description='Programming language') + purpose: str | None = Field(None, description='What the exploit is designed to achieve') + file_path: str | None = Field(None, description='Path where exploit was saved') + code_type: Literal['proof_of_concept', 'weaponized_exploit', 'web_shell', 'reverse_shell', 'payload', 'script', 'reconnaissance_tool'] | None = Field(None, description='Type of code') + +class AuthenticationAttempt(BaseModel): + """Login attempt (success or failure), session establishment (cookies/tokens/CSRF), credential validation, or bypass attempt. Should capture authentication state changes, privilege levels obtained, session tokens, and response details.""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + timestamp: float | None = Field(None, description='When authentication was attempted') + success: bool | None = Field(None, description='Whether authentication succeeded') + credential_used: str | None = Field(None, description='Reference to credential entity used') + session_established: bool | None = Field(None, description='Whether a session was established') + response_code: int | None = Field(None, description='HTTP response code if applicable') + error_message: str | None = Field(None, description='Error message if authentication failed') + +class DatabaseMetadata(BaseModel): + """Database configuration, schema, and structure information. Should include SQLi payload types used for extraction, enumeration results (tables/columns), user privileges, configuration details, and technique comparisons. Avoid duplicate error entries. Examples: 'MySQL 5.7.33 with FILE privilege', '113 tables enumerated: users, sessions, config, logs...'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + database_type: Literal['mysql', 'postgresql', 'mssql', 'oracle', 'mongodb', 'redis', 'other'] | None = Field(None, description='Type of database') + database_version: str | None = Field(None, description='Database version if known') + database_user: str | None = Field(None, description='Database user (e.g., root@172.22.0.7)') + table_count: int | None = Field(None, description='Number of tables discovered') + table_names: list[str] | None = Field(None, description='List of table names discovered') + privileges: list[str] | None = Field(None, description='User privileges (e.g., FILE, SELECT, INSERT)') + secure_file_priv: str | None = Field(None, description='secure_file_priv setting value') + configuration_details: str | None = Field(None, description='Other relevant configuration information') + +class ExploitationAttempt(BaseModel): + """A specific exploitation attempt with a technique""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + timestamp: float | None = Field(None, description='When exploitation was attempted') + technique_type: Literal['error_based_sqli', 'time_based_sqli', 'boolean_based_sqli', 'union_based_sqli', 'file_inclusion', 'command_injection', 'xxe', 'buffer_overflow', 'other'] | None = Field(None, description='Type of exploitation technique') + success: bool | None = Field(None, description='Whether exploitation succeeded') + payload: str | None = Field(None, description='Payload used (sanitized)') + response_hash: str | None = Field(None, description='Hash of response for deduplication') + result_summary: str | None = Field(None, description='Summary of what happened') + +class SessionInfo(BaseModel): + """Session tokens, cookies, and authentication state AFTER successful authentication""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + session_type: Literal['cookie', 'token', 'jwt', 'oauth', 'api_key', 'other'] | None = Field(None, description='Type of session mechanism') + session_id: str | None = Field(None, description='Session identifier (e.g., zbx_sessionid value)') + csrf_token: str | None = Field(None, description='CSRF token if applicable') + established_at: float | None = Field(None, description='When session was established') + expires_at: float | None = Field(None, description='When session expires (if known)') + privilege_level: Literal['guest', 'user', 'admin', 'root', 'unknown'] | None = Field(None, description='Privilege level of this session') + +class FileSystemAccess(BaseModel): + """File system access attempt and result. For successful reads, include file path and content preview. Document permission boundaries, file types accessed, and sensitivity level. Skip duplicate permission denials (keep first only) and verbose methodology without results. Examples: '/etc/passwd read: 48 user accounts', 'SSH private key found at /root/.ssh/id_rsa'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + file_path: str | None = Field(None, description='Path to file or directory accessed') + access_type: Literal['read', 'write', 'execute', 'list', 'stat'] | None = Field(None, description='Type of access attempted') + success: bool | None = Field(None, description='Whether access was successful') + access_method: Literal['xxe', 'lfi', 'rfi', 'command_injection', 'direct_access', 'path_traversal'] | None = Field(None, description='Method used to access file') + content_preview: str | None = Field(None, description='Preview of file content if read (truncated to 500 chars)') + permission_error: str | None = Field(None, description='Permission error message if access denied') + file_type: Literal['config', 'credential', 'log', 'system_info', 'ssh_key', 'source_code', 'database', 'other'] | None = Field(None, description='Type of file accessed') + sensitivity: Literal['critical', 'high', 'medium', 'low', 'info'] | None = Field(None, description='Sensitivity level of accessed file') + +class XMLPayload(BaseModel): + """XML payload used in XXE exploitation. Should identify XML parser (type/version), protocol handlers available (file/http/ftp/expect/php/jar), successful file reads, OOB interaction confirmations, payload variations tested, and parser configuration. Examples: 'XXE file:// payload reading /etc/passwd', 'OOB XXE via HTTP callback to attacker.com'""" + version: int | None = Field(None, description='Taxonomy schema version') + entity_uuid: str | None = Field(None, description='Unique identifier') + payload_type: Literal['file_read', 'oob_exfil', 'rce_attempt', 'ssrf', 'entity_expansion', 'parameter_entity'] | None = Field(None, description='Type of XXE payload') + payload_content: str | None = Field(None, description='Actual XML payload (sanitized)') + encoding: Literal['utf-8', 'utf-16', 'utf-16be', 'base64', 'other'] | None = Field(None, description='Payload encoding') + protocol_handler: Literal['file', 'http', 'https', 'ftp', 'expect', 'php', 'jar', 'data', 'gopher', 'other'] | None = Field(None, description='Protocol handler used in payload') + success: bool | None = Field(None, description='Whether payload was successful') + response_length: int | None = Field(None, description='Length of response in bytes') + oob_interaction: bool | None = Field(None, description='Whether OOB interaction was observed') diff --git a/v1/python/tests/test_generated_code.py b/v1/python/tests/test_generated_code.py index d6c637b..1993f11 100644 --- a/v1/python/tests/test_generated_code.py +++ b/v1/python/tests/test_generated_code.py @@ -5,8 +5,8 @@ import pytest from pydantic import ValidationError from pentagi_taxonomy import TAXONOMY_VERSION, ENTITY_TYPES, EDGE_TYPES -from pentagi_taxonomy.nodes import Target, Port -from pentagi_taxonomy.edges import HasPort, Discovered +from pentagi_taxonomy.nodes import Target, Vulnerability, Tool, TechnicalFinding +from pentagi_taxonomy.edges import HasVulnerability, UsedAgainst, Yields def test_taxonomy_version(): @@ -17,8 +17,10 @@ def test_taxonomy_version(): def test_entity_types_exported(): """Test that entity type mappings are exported.""" assert 'Target' in ENTITY_TYPES - assert 'Port' in ENTITY_TYPES + assert 'Vulnerability' in ENTITY_TYPES + assert 'Tool' in ENTITY_TYPES assert ENTITY_TYPES['Target'] == Target + assert ENTITY_TYPES['Vulnerability'] == Vulnerability def test_target_validation(): @@ -27,26 +29,45 @@ def test_target_validation(): hostname="example.com", ip_address="192.168.1.1", target_type="host", - risk_score=5.0 + port=443, + protocol="HTTPS" ) assert target.hostname == "example.com" + assert target.port == 443 -def test_port_validation(): - """Test Port validation.""" - port = Port( - port_number=443, - protocol="tcp", - state="open" +def test_vulnerability_validation(): + """Test Vulnerability validation.""" + vuln = Vulnerability( + vulnerability_name="SQL Injection", + vulnerability_class="sql_injection", + severity="high", + cvss_score=7.5 ) - assert port.port_number == 443 + assert vuln.vulnerability_name == "SQL Injection" + assert vuln.cvss_score == 7.5 + + +def test_tool_validation(): + """Test Tool validation.""" + tool = Tool( + tool_name="sqlmap", + tool_category="exploitation_framework", + version_used="1.5.3" + ) + assert tool.tool_name == "sqlmap" + assert tool.tool_category == "exploitation_framework" def test_all_fields_optional(): """Test that all fields are optional.""" target = Target() assert target.version is None + assert target.hostname is None + + vuln = Vulnerability() + assert vuln.vulnerability_name is None - port = Port() - assert port.port_number is None + tool = Tool() + assert tool.tool_name is None diff --git a/v1/typescript/src/schemas.ts b/v1/typescript/src/schemas.ts index f576d3b..73068fa 100644 --- a/v1/typescript/src/schemas.ts +++ b/v1/typescript/src/schemas.ts @@ -5,64 +5,542 @@ import { z } from 'zod'; -// A target system being assessed during penetration testing +// Network endpoint, service, application, or host being assessed. Should include version information, technology stack, and network details (IP, port, protocol). Examples: 'phpMyAdmin 4.4.15.6 on 172.22.0.7:80', 'Apache 2.4.29 web server' export const TargetSchema = z.object({ - // Taxonomy schema version (auto-injected by Graphiti fork) + // Taxonomy schema version version: z.number().int().optional(), // Unique identifier entity_uuid: z.string().optional(), - // DNS hostname if known + // Primary identifier (hostname, IP, URL) + identifier: z.string().optional(), + // Type of target + target_type: z.enum(["host", "service", "web_application", "api_endpoint", "network_range", "container"]).optional(), + // DNS hostname if applicable hostname: z.string().optional(), - // IP address of the target + // IP address if applicable ip_address: z.string().regex(/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/).optional(), - // Classification of target - target_type: z.enum(["host", "web_service", "api"]).optional(), - // Calculated risk score - risk_score: z.number().min(0.0).max(10.0).optional(), - // Current status - status: z.enum(["active", "inactive"]).optional(), + // Port number if service-specific + port: z.number().int().min(1).max(65535).optional(), + // Protocol (HTTP, HTTPS, SSH, etc.) + protocol: z.string().optional(), + // Technologies detected (PHP, Apache, MySQL, etc.) + technology_stack: z.array(z.string()).optional(), + // Current assessment status + status: z.enum(["discovered", "active", "compromised", "analyzed", "unreachable"]).optional(), }); export type Target = z.infer; -// A network port on a target system -export const PortSchema = z.object({ - // Taxonomy schema version (auto-injected by Graphiti fork) +// Security weakness or attack vector with CVE identifier, vulnerability class, or technical description. Should include severity assessment, exploitability status, version linkage, and test confirmation. Examples: 'CVE-2016-10134 SQLi in jsrpc.php profileIdx', 'XML External Entity (XXE) injection in document parser' +export const VulnerabilitySchema = z.object({ + // Taxonomy schema version version: z.number().int().optional(), // Unique identifier entity_uuid: z.string().optional(), - // Port number - port_number: z.number().int().min(1).max(65535).optional(), - // Network protocol - protocol: z.enum(["tcp", "udp"]).optional(), - // Port state - state: z.enum(["open", "closed", "filtered"]).optional(), + // Vulnerability name or title + vulnerability_name: z.string().optional(), + // OWASP/CWE category of vulnerability + vulnerability_class: z.enum(["sql_injection", "rce", "xss", "xxe", "ssrf", "lfi", "rfi", "csrf", "auth_bypass", "file_upload", "command_injection", "buffer_overflow", "directory_traversal", "privilege_escalation", "information_disclosure", "denial_of_service", "deserialization", "path_traversal", "session_hijacking", "other"]).optional(), + // CVE identifier if applicable + cve_id: z.string().regex(/^CVE-\d{4}-\d{4,7}$/).optional(), + // CVSS score if available + cvss_score: z.number().min(0.0).max(10.0).optional(), + // Severity assessment + severity: z.enum(["critical", "high", "medium", "low", "info"]).optional(), + // Whether vulnerability can be exploited + exploitability: z.enum(["confirmed_exploitable", "likely_exploitable", "theoretical", "not_exploitable", "unknown"]).optional(), + // Technical description of the vulnerability + description: z.string().optional(), + // List of exploitation techniques attempted (e.g., error-based SQLi, time-based SQLi, XXE file read) + exploitation_techniques_tested: z.array(z.string()).optional(), + // Techniques that successfully exploited this vulnerability + successful_techniques: z.array(z.string()).optional(), + // Techniques that failed to exploit this vulnerability + failed_techniques: z.array(z.string()).optional(), + // XML parser type if XXE vulnerability (lxml, libxml2, Xerces, etc.) + xxe_parser_type: z.string().optional(), + // Available protocol handlers for XXE (file, http, ftp, expect, php, jar) + xxe_protocol_handlers: z.array(z.string()).optional(), + // Whether out-of-band XXE interaction was confirmed + xxe_oob_confirmed: z.boolean().optional(), }); -export type Port = z.infer; +export type Vulnerability = z.infer; -// A target has a port -export const HasPortSchema = z.object({ - // Taxonomy schema version (auto-injected by Graphiti fork) +// Executable scanner, testing tool, or exploitation framework. Extract when tool produces actionable results; note success/failure status. Examples: 'sqlmap', 'nmap', 'metasploit', 'Burp Suite' +export const ToolSchema = z.object({ + // Taxonomy schema version version: z.number().int().optional(), - // When association was established + // Unique identifier + entity_uuid: z.string().optional(), + // Tool name (nmap, sqlmap, metasploit, etc.) + tool_name: z.string().optional(), + // Category of tool + tool_category: z.enum(["scanner", "exploitation_framework", "fuzzer", "reconnaissance", "enumeration", "post_exploitation", "password_cracker", "web_proxy", "network_tool", "custom_script"]).optional(), + // Version of the tool used + version_used: z.string().optional(), + // What the tool was used for in this context + purpose: z.string().optional(), +}); + +export type Tool = z.infer; + +// Specific security observation or test result. Summarize concisely (max 500 chars), include confidence level, prioritize findings that advance the assessment narrative. Examples: '113 DB tables enumerated via error-based SQLi', '/etc/passwd accessed via XXE: 48 users listed', 'phpMyAdmin version 4.4.15.6 disclosed in HTTP headers' +export const TechnicalFindingSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Type of finding + finding_type: z.enum(["version_disclosure", "open_port", "exposed_endpoint", "configuration_issue", "credential", "sensitive_data", "exploit_success", "reconnaissance_data", "vulnerability_confirmation", "patch_status", "service_banner", "database_enumeration", "authentication_result"]).optional(), + // Brief title of the finding + title: z.string().optional(), + // Detailed finding content (sanitized and summarized) + content: z.string().optional(), + // Confidence in the finding + confidence: z.number().min(0.0).max(1.0).optional(), + // Severity of the finding + severity: z.enum(["critical", "high", "medium", "low", "info"]).optional(), + // Key evidence supporting the finding (truncated) + evidence: z.string().optional(), + // How data was extracted (e.g., error-based SQLi, time-based, manual) + extraction_technique: z.string().optional(), + // Type of data in this finding + data_type: z.enum(["database_schema", "user_info", "configuration", "privileges", "file_content", "command_output", "network_data", "session_info", "other"]).optional(), +}); + +export type TechnicalFinding = z.infer; + +// Specific exploitation method with technical details and payload information. Should map to MITRE ATT&CK taxonomy when applicable, record success/failure, and include actual payloads used. Examples: 'Error-based SQLi via updatexml()', 'Time-based blind SQLi with sleep()', 'Out-of-band XXE data exfiltration' +export const AttackTechniqueSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Name of the attack technique + attack_technique_name: z.string().optional(), + // MITRE ATT&CK category + technique_category: z.enum(["initial_access", "execution", "persistence", "privilege_escalation", "defense_evasion", "credential_access", "discovery", "lateral_movement", "collection", "exfiltration", "impact"]).optional(), + // Description of how the technique works + description: z.string().optional(), + // Actual payload or command used (sanitized) + payload: z.string().optional(), + // What indicates successful execution + success_indicator: z.string().optional(), +}); + +export type AttackTechnique = z.infer; + +// A phase or stage of the penetration testing engagement +export const TestPhaseSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Name of the test phase + test_phase_name: z.enum(["reconnaissance", "scanning", "enumeration", "vulnerability_analysis", "exploitation", "post_exploitation", "reporting", "cleanup"]).optional(), + // Objective of this phase + objective: z.string().optional(), + // Status of the phase + status: z.enum(["not_started", "in_progress", "completed", "blocked", "skipped"]).optional(), + // When phase started + start_timestamp: z.number().optional(), + // When phase completed + end_timestamp: z.number().optional(), +}); + +export type TestPhase = z.infer; + +// Actual authentication credentials with values (ALWAYS extract, including default credentials). Should include privilege level, discovery source, authentication status, and session tokens when applicable. Examples: 'Admin/zabbix', 'root/password', 'zbx_sessionid=0a0f93de...', 'API key: sk-abc123...' +export const CredentialSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Type of credential + credential_type: z.enum(["username_password", "api_key", "token", "ssh_key", "certificate", "hash", "cookie"]).optional(), + // Username if applicable + username: z.string().optional(), + // Whether credential is valid + is_valid: z.boolean().optional(), + // Whether this is a default credential (e.g., Admin/zabbix) + is_default: z.boolean().optional(), + // Privilege level of the credential + privilege_level: z.enum(["admin", "user", "guest", "service_account", "root", "unknown"]).optional(), + // How the credential was obtained + source: z.string().optional(), + // Result of authentication attempt with this credential + authentication_state: z.enum(["success", "failure", "requires_2fa", "locked", "expired", "unknown"]).optional(), +}); + +export type Credential = z.infer; + +// Actual exploit code, script, or payload used during testing. Should reference target vulnerability, include programming language, and document purpose/objective. Can be proof-of-concept, weaponized exploit, web shell, or reconnaissance script. +export const ExploitCodeSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Name of the exploit + exploit_code_name: z.string().optional(), + // Programming language + language: z.enum(["python", "bash", "php", "ruby", "powershell", "javascript", "go", "other"]).optional(), + // What the exploit is designed to achieve + purpose: z.string().optional(), + // Path where exploit was saved + file_path: z.string().optional(), + // Type of code + code_type: z.enum(["proof_of_concept", "weaponized_exploit", "web_shell", "reverse_shell", "payload", "script", "reconnaissance_tool"]).optional(), +}); + +export type ExploitCode = z.infer; + +// Login attempt (success or failure), session establishment (cookies/tokens/CSRF), credential validation, or bypass attempt. Should capture authentication state changes, privilege levels obtained, session tokens, and response details. +export const AuthenticationAttemptSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // When authentication was attempted timestamp: z.number().optional(), + // Whether authentication succeeded + success: z.boolean().optional(), + // Reference to credential entity used + credential_used: z.string().optional(), + // Whether a session was established + session_established: z.boolean().optional(), + // HTTP response code if applicable + response_code: z.number().int().optional(), + // Error message if authentication failed + error_message: z.string().optional(), +}); + +export type AuthenticationAttempt = z.infer; + +// Database configuration, schema, and structure information. Should include SQLi payload types used for extraction, enumeration results (tables/columns), user privileges, configuration details, and technique comparisons. Avoid duplicate error entries. Examples: 'MySQL 5.7.33 with FILE privilege', '113 tables enumerated: users, sessions, config, logs...' +export const DatabaseMetadataSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Type of database + database_type: z.enum(["mysql", "postgresql", "mssql", "oracle", "mongodb", "redis", "other"]).optional(), + // Database version if known + database_version: z.string().optional(), + // Database user (e.g., root@172.22.0.7) + database_user: z.string().optional(), + // Number of tables discovered + table_count: z.number().int().optional(), + // List of table names discovered + table_names: z.array(z.string()).optional(), + // User privileges (e.g., FILE, SELECT, INSERT) + privileges: z.array(z.string()).optional(), + // secure_file_priv setting value + secure_file_priv: z.string().optional(), + // Other relevant configuration information + configuration_details: z.string().optional(), }); -export type HasPort = z.infer; +export type DatabaseMetadata = z.infer; -// An action discovered an entity -export const DiscoveredSchema = z.object({ - // Taxonomy schema version (auto-injected by Graphiti fork) +// A specific exploitation attempt with a technique +export const ExploitationAttemptSchema = z.object({ + // Taxonomy schema version version: z.number().int().optional(), - // Discovery timestamp + // Unique identifier + entity_uuid: z.string().optional(), + // When exploitation was attempted timestamp: z.number().optional(), - // Confidence score + // Type of exploitation technique + technique_type: z.enum(["error_based_sqli", "time_based_sqli", "boolean_based_sqli", "union_based_sqli", "file_inclusion", "command_injection", "xxe", "buffer_overflow", "other"]).optional(), + // Whether exploitation succeeded + success: z.boolean().optional(), + // Payload used (sanitized) + payload: z.string().optional(), + // Hash of response for deduplication + response_hash: z.string().optional(), + // Summary of what happened + result_summary: z.string().optional(), +}); + +export type ExploitationAttempt = z.infer; + +// Session tokens, cookies, and authentication state AFTER successful authentication +export const SessionInfoSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Type of session mechanism + session_type: z.enum(["cookie", "token", "jwt", "oauth", "api_key", "other"]).optional(), + // Session identifier (e.g., zbx_sessionid value) + session_id: z.string().optional(), + // CSRF token if applicable + csrf_token: z.string().optional(), + // When session was established + established_at: z.number().optional(), + // When session expires (if known) + expires_at: z.number().optional(), + // Privilege level of this session + privilege_level: z.enum(["guest", "user", "admin", "root", "unknown"]).optional(), +}); + +export type SessionInfo = z.infer; + +// File system access attempt and result. For successful reads, include file path and content preview. Document permission boundaries, file types accessed, and sensitivity level. Skip duplicate permission denials (keep first only) and verbose methodology without results. Examples: '/etc/passwd read: 48 user accounts', 'SSH private key found at /root/.ssh/id_rsa' +export const FileSystemAccessSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Path to file or directory accessed + file_path: z.string().optional(), + // Type of access attempted + access_type: z.enum(["read", "write", "execute", "list", "stat"]).optional(), + // Whether access was successful + success: z.boolean().optional(), + // Method used to access file + access_method: z.enum(["xxe", "lfi", "rfi", "command_injection", "direct_access", "path_traversal"]).optional(), + // Preview of file content if read (truncated to 500 chars) + content_preview: z.string().optional(), + // Permission error message if access denied + permission_error: z.string().optional(), + // Type of file accessed + file_type: z.enum(["config", "credential", "log", "system_info", "ssh_key", "source_code", "database", "other"]).optional(), + // Sensitivity level of accessed file + sensitivity: z.enum(["critical", "high", "medium", "low", "info"]).optional(), +}); + +export type FileSystemAccess = z.infer; + +// XML payload used in XXE exploitation. Should identify XML parser (type/version), protocol handlers available (file/http/ftp/expect/php/jar), successful file reads, OOB interaction confirmations, payload variations tested, and parser configuration. Examples: 'XXE file:// payload reading /etc/passwd', 'OOB XXE via HTTP callback to attacker.com' +export const XMLPayloadSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // Unique identifier + entity_uuid: z.string().optional(), + // Type of XXE payload + payload_type: z.enum(["file_read", "oob_exfil", "rce_attempt", "ssrf", "entity_expansion", "parameter_entity"]).optional(), + // Actual XML payload (sanitized) + payload_content: z.string().optional(), + // Payload encoding + encoding: z.enum(["utf-8", "utf-16", "utf-16be", "base64", "other"]).optional(), + // Protocol handler used in payload + protocol_handler: z.enum(["file", "http", "https", "ftp", "expect", "php", "jar", "data", "gopher", "other"]).optional(), + // Whether payload was successful + success: z.boolean().optional(), + // Length of response in bytes + response_length: z.number().int().optional(), + // Whether OOB interaction was observed + oob_interaction: z.boolean().optional(), +}); + +export type XMLPayload = z.infer; + +// A target has or is affected by a vulnerability +export const HasVulnerabilitySchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When vulnerability was identified + timestamp: z.number().optional(), + // Confidence in the vulnerability confidence: z.number().min(0.0).max(1.0).optional(), - // Discovery method - method: z.enum(["active", "passive"]).optional(), + // Whether vulnerability was verified through exploitation + verified: z.boolean().optional(), +}); + +export type HasVulnerability = z.infer; + +// A tool or technique was used against a target +export const UsedAgainstSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When tool was used + timestamp: z.number().optional(), + // Whether the use was successful + success: z.boolean().optional(), + // Context of tool usage (command line, parameters) + execution_context: z.string().optional(), +}); + +export type UsedAgainst = z.infer; + +// A technique or exploit code exploits a vulnerability +export const ExploitsSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When exploitation occurred + timestamp: z.number().optional(), + // Whether exploitation was successful + success: z.boolean().optional(), + // Impact of successful exploitation + impact: z.enum(["full_compromise", "partial_access", "information_disclosure", "denial_of_service", "none"]).optional(), +}); + +export type Exploits = z.infer; + +// A finding was discovered during a test phase +export const DiscoveredInSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When discovery occurred + timestamp: z.number().optional(), + // How the finding was discovered + discovery_method: z.string().optional(), +}); + +export type DiscoveredIn = z.infer; + +// One finding, technique, or vulnerability leads to another (attack chain) +export const LeadsToSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When connection was established + timestamp: z.number().optional(), + // How one leads to the other + reasoning: z.string().optional(), +}); + +export type LeadsTo = z.infer; + +// A vulnerability, technique, or tool targets a specific target +export const TargetsSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When targeting occurred + timestamp: z.number().optional(), +}); + +export type Targets = z.infer; + +// A credential provides access to a target or service +export const ProvidesAccessToSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When access was verified + timestamp: z.number().optional(), + // Level of access provided + access_level: z.enum(["read_only", "read_write", "administrative", "root", "limited"]).optional(), +}); + +export type ProvidesAccessTo = z.infer; + +// An action, tool use, or technique yields a finding +export const YieldsSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When finding was produced + timestamp: z.number().optional(), +}); + +export type Yields = z.infer; + +// A technique or attack uses a specific tool +export const UsesToolSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When tool was used + timestamp: z.number().optional(), +}); + +export type UsesTool = z.infer; + +// A credential was used to authenticate against a target +export const AuthenticatedWithSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When authentication occurred + timestamp: z.number().optional(), + // Whether authentication succeeded + success: z.boolean().optional(), + // Session ID created (if applicable) + session_created: z.string().optional(), +}); + +export type AuthenticatedWith = z.infer; + +// A finding was extracted from a target using a specific technique +export const ExtractedFromSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When extraction occurred + timestamp: z.number().optional(), + // Method used for extraction (e.g., error-based SQLi) + extraction_method: z.string().optional(), +}); + +export type ExtractedFrom = z.infer; + +// A tool enumerated database metadata +export const EnumeratedSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When enumeration occurred + timestamp: z.number().optional(), + // Number of records/items found + records_found: z.number().int().optional(), +}); + +export type Enumerated = z.infer; + +// An authentication attempt establishes a session +export const EstablishesSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When session was established + timestamp: z.number().optional(), +}); + +export type Establishes = z.infer; + +// An attack technique or exploit accessed a file +export const AccessedFileSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When file was accessed + timestamp: z.number().optional(), + // Number of bytes read if applicable + bytes_read: z.number().int().optional(), +}); + +export type AccessedFile = z.infer; + +// A file system access revealed information or findings +export const RevealedSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When information was revealed + timestamp: z.number().optional(), + // Type of information revealed + revelation_type: z.enum(["credentials", "configuration", "system_info", "vulnerability", "other"]).optional(), +}); + +export type Revealed = z.infer; + +// An exploitation attempt uses a specific XML payload +export const UsesPayloadSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When payload was used + timestamp: z.number().optional(), + // Sequential attempt number + attempt_number: z.number().int().optional(), +}); + +export type UsesPayload = z.infer; + +// An XML payload triggered an out-of-band interaction +export const OobInteractionSchema = z.object({ + // Taxonomy schema version + version: z.number().int().optional(), + // When interaction occurred + timestamp: z.number().optional(), + // Type of OOB interaction + interaction_type: z.enum(["http_callback", "dns_query", "ftp_connection", "other"]).optional(), + // Data exfiltrated via OOB channel (preview) + data_exfiltrated: z.string().optional(), }); -export type Discovered = z.infer; +export type OobInteraction = z.infer;