adv_mark_false_positive
Mark a finding as a false positive in the .adversary.json file by specifying the finding UUID, reason, and marked-by details to manage security insights effectively.
Instructions
Mark a finding as a false positive in the .adversary.json file
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| finding_uuid | Yes | UUID of the finding to mark as false positive | |
| marked_by | No | Name of the person marking this as false positive | MCP User |
| path | No | Path to directory containing .adversary.json or direct path to .adversary.json file | . |
| reason | No | Reason for marking as false positive | Manually marked via MCP tool |
Implementation Reference
- MCP handler function that dispatches the adv_mark_false_positive tool: validates parameters, instantiates FalsePositiveService with JsonRepository, executes the mark_as_false_positive operation, and returns JSON result.async def _handle_mark_false_positive( self, name: str, arguments: dict ) -> list[types.TextContent]: """Handle mark false positive requests.""" try: # Comprehensive input validation validated_args = self._input_validator.validate_mcp_arguments( arguments, tool_name="adv_mark_false_positive" ) finding_uuid = validated_args.get("finding_uuid", "") reason = validated_args.get("reason", "") marked_by = validated_args.get("marked_by", "user") adversary_file_path = validated_args.get( "adversary_file_path", ".adversary.json" ) if not finding_uuid: raise CleanAdversaryToolError("finding_uuid parameter is required") # Initialize false positive repository and service fp_repository = FalsePositiveJsonRepository(adversary_file_path) fp_service = FalsePositiveService(fp_repository) # Mark as false positive success = await fp_service.mark_as_false_positive( uuid=finding_uuid, reason=reason, marked_by=marked_by ) result = { "success": success, "finding_uuid": finding_uuid, "message": ( f"Finding {finding_uuid} marked as false positive" if success else f"Failed to mark finding {finding_uuid} as false positive" ), } return [types.TextContent(type="text", text=json.dumps(result, indent=2))] except Exception as e: logger.error(f"Mark false positive failed: {e}") raise CleanAdversaryToolError(f"Mark false positive failed: {str(e)}")
- src/adversary_mcp_server/application/mcp_server.py:1552-1580 (registration)Tool registration including name, description, and input schema definition returned by get_tools().Tool( name="adv_mark_false_positive", description="Mark a finding as a false positive", inputSchema={ "type": "object", "properties": { "finding_uuid": { "type": "string", "description": "UUID of the finding to mark as false positive", }, "reason": { "type": "string", "description": "Reason for marking as false positive", "default": "", }, "marked_by": { "type": "string", "description": "Who marked it as false positive", "default": "user", }, "adversary_file_path": { "type": "string", "description": "Path to .adversary.json file", "default": ".adversary.json", }, }, "required": ["finding_uuid"], }, ),
- Pydantic-like input schema validation definition for the tool parameters."type": "object", "properties": { "finding_uuid": { "type": "string", "description": "UUID of the finding to mark as false positive", }, "reason": { "type": "string", "description": "Reason for marking as false positive", "default": "", }, "marked_by": { "type": "string", "description": "Who marked it as false positive", "default": "user", }, "adversary_file_path": { "type": "string", "description": "Path to .adversary.json file", "default": ".adversary.json", }, }, "required": ["finding_uuid"], },
- Application service layer method: validates UUID, creates domain FalsePositiveInfo entity, delegates persistence to IFalsePositiveRepository.async def mark_as_false_positive( self, uuid: str, reason: str = "", marked_by: str = "user", ) -> bool: """ Mark a security finding as a false positive. Args: uuid: UUID of the finding to mark reason: Reason for marking as false positive marked_by: Who marked it as false positive Returns: True if marked successfully, False otherwise """ try: # Validate inputs if not uuid.strip(): raise ValueError("UUID cannot be empty") # Create false positive info fp_info = FalsePositiveInfo.create_false_positive( uuid=uuid, reason=reason, marked_by=marked_by, ) # Save to repository success = await self.repository.save_false_positive_info(fp_info) if success: self.logger.info( f"Marked finding {uuid} as false positive (reason: '{reason}', marked_by: {marked_by})" ) else: self.logger.error(f"Failed to mark finding {uuid} as false positive") return success except Exception as e: self.logger.error(f"Error marking finding {uuid} as false positive: {e}") return False
- Infrastructure persistence layer: loads .adversary.json, finds threat by UUID, merges false positive info into threat object, atomically saves back to JSON file.async def save_false_positive_info(self, info: FalsePositiveInfo) -> bool: """Save false positive information.""" try: # Load current data data = self._load_adversary_json() if not data: self.logger.warning( f"No .adversary.json file found at {self.adversary_file} - cannot save false positive info" ) return False if "threats" not in data: self.logger.warning("No threats section in .adversary.json file") return False # Find and update the threat updated = False for threat in data["threats"]: if threat.get("uuid") == info.uuid: # Update threat with false positive information fp_dict = info.to_dict() threat.update(fp_dict) updated = True break if not updated: self.logger.warning( f"Threat {info.uuid} not found in .adversary.json file" ) return False # Save the updated data success = self._save_adversary_json(data) if success: self.logger.info( f"Saved false positive info for {info.uuid} to {self.adversary_file}" ) return success except Exception as e: self.logger.error(f"Error saving false positive info for {info.uuid}: {e}") return False