Validation

Robot validation and security checks.

Robot Validator

class linkforge.core.RobotValidator(checks=None)[source]

Bases: object

Validates robot structure for URDF export and simulation.

Runs a configurable registry of ValidationCheck instances. By default, all standard checks run in dependency order. Callers can pass a custom list to run only a specific subset of validation rules.

Example

>>> from linkforge.core.models import Robot, Link
>>> from linkforge.core import RobotValidator
>>> robot = Robot(name="test_robot")
>>> robot.add_link(Link(name="base_link"))
>>> # Validating a robot
>>> result = RobotValidator().validate(robot)
>>> if result.is_valid:
...     print("Robot is valid!")
... else:
...     print(f"Found {result.error_count} errors")
Parameters:

checks (list[ValidationCheck] | None)

DEFAULT_CHECKS: list[type[ValidationCheck]] = [<class 'linkforge.core.validation.checks.HasLinksCheck'>, <class 'linkforge.core.validation.checks.DuplicateNameCheck'>, <class 'linkforge.core.validation.checks.JointReferenceCheck'>, <class 'linkforge.core.validation.checks.TreeStructureCheck'>, <class 'linkforge.core.validation.checks.MassPropertiesCheck'>, <class 'linkforge.core.validation.checks.GeometryCheck'>, <class 'linkforge.core.validation.checks.Ros2ControlCheck'>, <class 'linkforge.core.validation.checks.MimicChainCheck'>, <class 'linkforge.core.validation.checks.SemanticCheck'>, <class 'linkforge.core.validation.checks.SemanticConsistencyCheck'>]
__init__(checks=None)[source]

Initialize validator.

Parameters:

checks (list[ValidationCheck] | None) – Optional custom list of check instances to run. Defaults to DEFAULT_CHECKS (all standard checks).

validate(robot)[source]

Run all registered validation checks on a robot model.

Parameters:

robot (Robot) – The Robot model instance to validate.

Return type:

ValidationResult

Returns:

ValidationResult containing all errors and warnings.

Validation Result

class linkforge.core.ValidationResult(issues=<factory>, robot_name='')[source]

Bases: object

Result of robot validation.

Parameters:
  • issues (list[ValidationIssue])

  • robot_name (str)

issues: list[ValidationIssue]
robot_name: str = ''
property errors: list[ValidationIssue]

Get only errors.

property warnings: list[ValidationIssue]

Get only warnings.

property is_valid: bool

Check if validation passed (no errors).

Note: Warnings don’t block validity.

property has_warnings: bool

Check if there are any warnings.

property error_count: int

Number of errors.

property warning_count: int

Number of warnings.

add_error(title, message, affected_objects=None, suggestion=None, code=None, auto_fix=None)[source]

Add an error to the validation result.

Parameters:
Return type:

None

add_warning(title, message, affected_objects=None, suggestion=None, code=None, auto_fix=None)[source]

Add a warning to the validation result.

Parameters:
Return type:

None

__str__()[source]

String representation.

Return type:

str

__init__(issues=<factory>, robot_name='')
Parameters:
  • issues (list[ValidationIssue])

  • robot_name (str)

Security

Security validation functions for robot model parsing.

This module provides security checks to prevent malicious robot description files from accessing unauthorized file system locations or causing other security issues.

linkforge.core.validation.security.validate_mesh_path(mesh_filepath, source_directory, allow_absolute=False, sandbox_root=None)[source]

Validate that a mesh file path is safe to access.

This function prevents path traversal attacks by ensuring that mesh paths stay within the robot model’s directory or its subdirectories.

Security Note: Absolute paths are discouraged for portability and security. Use allow_absolute=True only when loading trusted robot description files.

Parameters:
  • mesh_filepath (Path) – The mesh file path from the URDF (may be relative or absolute)

  • source_directory (Path) – The directory containing the robot model file

  • allow_absolute (bool) – If True, allows absolute paths (default: False for security)

  • sandbox_root (Path | None) – The root directory for the sandbox. If None, source_directory is used. Access is restricted to files within this root and its subdirectories.

Return type:

Path

Returns:

The validated absolute path to the mesh file

Raises:
linkforge.core.validation.security.is_suspicious_location(path)[source]

Check if a path resolves to a suspicious system location.

Parameters:

path (Path)

Return type:

bool

linkforge.core.validation.security.validate_package_uri(uri)[source]

Validate a ROS package:// URI.

Parameters:

uri (str) – The package URI to validate (e.g., β€œpackage://my_robot/meshes/arm.stl”)

Return type:

str

Returns:

The validated URI

Raises:

RobotSecurityError – If the URI is malformed or contains suspicious components

linkforge.core.validation.security.find_sandbox_root(filepath)[source]

Find a sensible sandbox root for a given file.

For robotics projects, this frequently means going up one level if the file is inside a robot model folder (e.g., β€˜urdf’ or β€˜xacro’), or searching for a package.xml.

Parameters:

filepath (Path) – Path to the robot model file (URDF, XACRO, etc.)

Return type:

Path

Returns:

The detected sandbox root Path

Usage Examples

Validate Robot

from linkforge.core import RobotValidator

validator = RobotValidator()
result = validator.validate(robot)

if result.is_valid:
    print(" Robot is valid!")
else:
    print(" Validation errors:")
    for error in result.errors:
        print(f"  - {error}")

    print("\nWarnings:")
    for warning in result.warnings:
        print(f"  - {warning}")

Security Checks

from linkforge.core.validation import validate_mesh_path, find_sandbox_root
from linkforge.core import RobotSecurityError
from pathlib import Path

# Validate mesh path (prevents path traversal)
try:
    validate_mesh_path(Path("../../etc/passwd"), Path("/tmp"))  # Raises RobotSecurityError
except RobotSecurityError as e:
    print(f"Security error: {e}")

# Valid paths within sandbox
urdf_dir = Path("/my_robot/urdf")
validate_mesh_path(Path("meshes/robot.stl"), urdf_dir)  # OK

# Auto-detect sandbox root for sibling folder access
urdf_file = Path("/my_robot/urdf/robot.urdf")
sandbox = find_sandbox_root(urdf_file)  # Returns /my_robot
validate_mesh_path(Path("../meshes/part.stl"), urdf_dir, sandbox_root=sandbox)  # OK

Validation Checks

The validator performs the following checks:

Structure Validation

  • Robot has a name

  • At least one link exists

  • All links have unique names

  • All joints have unique names

  • Tree structure is valid (no cycles, single root)

Joint Validation

  • Parent and child links exist

  • Joint limits are valid (lower ≀ upper)

  • Axis is non-zero for revolute/prismatic joints

  • Mimic joints reference existing joints

Sensor Validation

  • Sensors are attached to existing links

  • Sensor-specific info is provided

  • Update rates are positive

Security Validation

  • Mesh paths don’t escape the sandbox root

  • Sandbox root auto-detection for sibling folders

  • Numeric values are within safe ranges

  • XML depth is limited (prevents XML bombs)