Skip to content

Latest commit

 

History

History
89 lines (79 loc) · 6.48 KB

File metadata and controls

89 lines (79 loc) · 6.48 KB

Mitigation Strategies Analysis for mobile-dev-inc/maestro

  1. Environment Variables: Never hardcode sensitive data (passwords, API keys, etc.) directly within Maestro flow YAML files. Use environment variables (e.g., ${MY_SECRET_KEY}) within the inputText, tapOn, or other relevant commands.
  2. Maestro Flow Modification: Replace all hardcoded sensitive data with references to environment variables. For example:
    # BAD:
    - inputText: "mysecretpassword"
    
    # GOOD:
    - inputText: "${MY_PASSWORD}"
  3. Pre-flight Checks (Data Validation): Before using any sensitive data obtained from environment variables, include assertions to validate its format or expected value (if possible). This adds a layer of defense against misconfiguration. Example:
    - assertVisible: "${API_KEY}" # Basic check that it's not empty
    # - runScript:  # More advanced validation (requires custom command)
    #     script: |
    #       if (!process.env.API_KEY.match(/^[a-zA-Z0-9]{32}$/)) {
    #         throw new Error("Invalid API Key format");
    #       }
  4. Custom Command for Masking (Conceptual): If sensitive data must be displayed on the screen, create a custom Maestro command that handles input and display with masking. This is a more advanced technique. The custom command would:
    • Take the sensitive data as input (likely from an environment variable).
    • Use a JavaScript library or custom logic to mask the data (e.g., replace characters with asterisks).
    • Use Maestro's inputText command to enter the masked value into the field.
    • Potentially store the original (unmasked) value in a secure way within the custom command's scope (not globally accessible) if needed for later verification.
  1. Environment Variables for URLs/Endpoints: Use environment variables (e.g., APP_URL, API_ENDPOINT) within Maestro flows to specify the target application URL or API endpoint.
  2. Conditional Flow Execution (runFlow.when.env): Use the runFlow command with the when.env condition to execute specific flows only in the intended environment. This prevents accidental execution against the wrong environment.
    - runFlow:
        when:
          env: "staging"
        file: staging-specific-flow.yaml
    - runFlow:
        when:
          env: "testing"
        file: testing-specific-flow.yaml
  3. Pre-flight Checks (Assertions): At the beginning of each Maestro flow, include assertions to verify that the flow is running in the correct environment. This is a crucial safeguard. Examples:
    - assertVisible:
        text: "Staging Environment" # If a specific text is present only in staging
        optional: true # Avoid failing if the text is not found (log a warning instead)
    - assertVisible:
        id: "staging-only-element" # If a specific element ID exists only in staging
        optional: true
    - evalScript: | # More robust check using JavaScript
        output.url === "${EXPECTED_STAGING_URL}"
    - assertTrue: "${output.url}"
  4. Custom Command for Environment Verification (Advanced): Create a custom Maestro command that encapsulates more complex environment verification logic. This command could:
    • Check multiple indicators (URL, presence of specific elements, API responses).
    • Log detailed information about the detected environment.
    • Throw an error if the environment is incorrect, halting the flow execution.
  1. Input Validation: Within the JavaScript code of any custom Maestro command, rigorously validate all input parameters. Use a validation library (e.g., joi, validator) or implement custom validation logic to prevent injection attacks and ensure data integrity.
    // Example custom command (simplified)
    function myCustomCommand(input) {
      if (!input.username || typeof input.username !== 'string' || input.username.length > 50) {
        throw new Error("Invalid username");
      }
      // ... rest of the command logic ...
    }
  2. Least Privilege (Conceptual - Limited within Maestro): While true sandboxing is difficult within Maestro's current architecture, strive to limit the scope of variables and operations within the custom command. Avoid using global variables or accessing unnecessary system resources.
  3. Avoid eval and Similar: Do not use eval() or similar functions (e.g., Function()) within custom commands, as they can introduce significant security risks if used with untrusted input.
  4. Secure Handling of Secrets (if needed): If a custom command must handle sensitive data, ensure it receives this data through environment variables (passed from the Maestro flow) and never hardcodes it.
  1. Prioritize Robust Selectors: Within Maestro flow YAML files, use the most robust and resilient selectors available:
    • accessibilityLabel: This is generally the most reliable option, as it's tied to the application's accessibility features.
    • id: Use IDs if they are unique and stable across application updates.
    • text: Use text content if it's unique and unlikely to change.
    • traits: (iOS-specific) Use UI element traits for selection.
    • index: Use as last resort.
  2. Avoid Fragile Selectors: Minimize or avoid:
    • Complex CSS selectors that depend on the exact DOM structure.
    • XPath expressions, especially absolute paths.
  3. Use optional: true strategically: When using assertVisible or tapOn with selectors that might not always be present (e.g., in different environments or application states), use optional: true to prevent the test from failing unnecessarily. Log a warning or use conditional logic instead.
  4. Use evalScript for dynamic checks: If you need to perform more complex checks on UI elements (e.g., verifying computed styles or dynamic attributes), use evalScript to execute JavaScript code within the browser context.