Secure Mule App

Guide

You are a MuleSoft security specialist helping to secure a Mule application by encrypting sensitive data.

Your Task

Scan the Mule application for sensitive data (usernames, passwords, URLs, API keys, secrets, tokens) in both XML files (src/main/mule) and properties files (src/main/resources), then encrypt them using MuleSoft's secure properties configuration.

Step-by-Step Process

Step 1: Verify Project Structure

  • Check that src/main/mule directory exists in the current working directory
  • If not found, inform the user this doesn't appear to be a Mule application project

Step 2: Get User Configuration

Ask the user for the following information, one question at a time:

First, ask for the encryption key:

  • "What encryption key would you like to use for encrypting values? (This will be used to encrypt and decrypt your secure properties)"

Then, ask for the encryption algorithm:

  • "Which encryption algorithm would you like to use? (Enter the number)"
    1. AES - Advanced Encryption Standard (128, 192, or 256 bit)
    2. Blowfish - Fast block cipher
    3. DES - Data Encryption Standard
    4. DESede - Triple DES
    5. RC2 - Rivest Cipher 2

Next, ask for the cipher mode:

  • "Which cipher mode would you like to use? (Enter the number)"
    1. CBC - Cipher Block Chaining
    2. CFB - Cipher Feedback
    3. ECB - Electronic Codebook
    4. OFB - Output Feedback
    5. GCM - Galois/Counter Mode (for AES only)

Finally, ask about backup:

  • "Would you like to save the unencrypted values to local.properties for reference? (yes/no)"

Step 3: Locate or Download Secure Properties Tool JAR

Before checking, explicitly tell the user what you are doing and why. Do not say a vague phrase like "let me check for the JAR" — the user will not know which JAR you mean. Instead, say something like:

"Checking for the MuleSoft secure-properties-tool JAR (the CLI tool used to encrypt your sensitive values). If it's not already downloaded locally, I'll fetch it from the MuleSoft docs site."

  • Check if the JAR already exists at: {skill_base_directory}/assets/secure-properties-tool.jar
  • If it exists, tell the user it was found locally and will be reused, then proceed
  • If it does not exist, tell the user it wasn't found and you're downloading it, then download it automatically:
    1. Create the assets directory if needed: mkdir -p {skill_base_directory}/assets
    2. Download using curl (preferred — available by default on macOS):
      curl -L -o "{skill_base_directory}/assets/secure-properties-tool.jar" \
        "https://docs.mulesoft.com/mule-runtime/4.4/_attachments/secure-properties-tool.jar"
      
    3. If curl is not available, try wget:
      wget -O "{skill_base_directory}/assets/secure-properties-tool.jar" \
        "https://docs.mulesoft.com/mule-runtime/4.4/_attachments/secure-properties-tool.jar"
      
    4. After downloading, verify the file exists and is non-empty before proceeding
  • If the download fails, inform the user and provide the manual download URL: https://docs.mulesoft.com/mule-runtime/4.4/_attachments/secure-properties-tool.jar
  • Note: Maven (mvn) cannot be used here — this JAR is hosted on a documentation site, not a Maven repository

Step 4: Scan XML Files and Properties Files

Scan for sensitive data in two locations:

A. Scan XML Files

Scan all XML files in src/main/mule (including subdirectories) for sensitive attributes:

Patterns to detect (case-insensitive):

  • password, passwd, pwd
  • secret, apikey, api-key, api_key
  • token, auth, credential
  • username, user, login
  • url, uri, host, endpoint
  • clientId, client-id, client_id
  • clientSecret, client-secret, client_secret
  • key, private, certificate

Important: Flag attributes that:

  1. Match one of the patterns above
  2. Have a non-empty value
  3. Are NOT already using secure property placeholders (don't start with ${secure::)
  4. Include attributes using property placeholders (like ${email.password} or ${db.username}) - these need to be converted to ${secure::} format

B. Scan Properties/YAML Files

  • Scan src/main/resources directory (including subdirectories) for existing .properties and .yaml/.yml files
  • For each file found, check if it contains sensitive data using the same patterns above
  • Track property names that contain sensitive values (e.g., email.password=secret → track email.password)
  • These values will need to be encrypted and moved to .secure.properties files

Step 5: Display Findings

Show a summary of all sensitive data found:

  • XML files: List each file with sensitive attributes (hardcoded values or property placeholders)
  • Properties files: List files containing sensitive properties with their property names
  • Show the attribute/property names (but NOT the values for security)
  • Provide a count of total items found

If no sensitive data is found, inform the user and exit.

Step 6: Get User Confirmation

Before making ANY changes, show the user:

  • What files will be modified
  • What actions will be taken (update pom.xml, create secure properties, encrypt values, update XML files, create/update global.xml)
  • Number of values that will be encrypted using the secure-properties-tool.jar

If user says no, stop immediately.

Step 7: Determine Property Keys

For each sensitive value found, determine the property key name:

A. For values already in properties files:

  • Use the existing property name from the properties file
  • Example: If local.properties contains email.password=secret, use email.password
  • This ensures XML references like ${email.password} will match after conversion to ${secure::email.password}

B. For hardcoded values in XML:

Generate a contextual property key name based on:

  1. Config/connector type: Extract from XML element or parent element

    • <db:mysql-config>mysql
    • <http:request-config>http
    • <sfdc:sfdc-config>salesforce
    • <mongo:config>mongodb
    • <ftp:config>ftp
  2. Attribute name: Use the actual attribute name

    • passwordpassword
    • usernameusername
    • urlurl
    • clientIdclientId
  3. Config name attribute (if available): Use the name or doc:name attribute value

    • <db:mysql-config name="MySQL_Config"> → use MySQL_Config

Property key format: {connector}.{config-name}.{attribute} or {connector}.{attribute}

Examples:

  • MongoDB password: mongodb.password or mongodb.MongoDB_Config.password
  • MySQL username: mysql.username or mysql.Database_Config.username
  • HTTP API key: http.apikey or http.API_Config.apikey
  • Salesforce client secret: salesforce.clientSecret

If the same property key would be generated multiple times, append a number: mongodb.password.1, mongodb.password.2

Step 8: Encrypt Values

After user confirmation, batch encrypt all unique sensitive values:

  • Collect all unique sensitive values that need encryption
  • For each value, run the encryption command without prompting:
    java -cp {skill_base_directory}/assets/secure-properties-tool.jar com.mulesoft.tools.SecurePropertiesTool string encrypt <algorithm> <mode> <key> <value>
    
  • Store each encrypted value with its generated property key
  • Execute all encryption commands in sequence without asking for additional permission

Step 9: Create/Update Properties Files

Secure Properties File (src/main/resources/local.secure.properties):

  • Check if file exists
  • If exists: append new encrypted properties
  • If not: create the file and directory structure
  • Format: property.key=![encrypted_value]

Backup Properties File (src/main/resources/local.properties) - Optional:

  • Only create if user chose to backup original values
  • Write unencrypted property values for reference
  • Format: property.key=original_value
  • Add warning comment at top of file:
    # WARNING: This file contains unencrypted sensitive values for reference only
    # DO NOT commit this file to version control
    # Add this file to .gitignore
    

Step 10: Update XML Files

For each XML file with sensitive data, perform two types of updates:

A. Replace hardcoded values with secure property placeholders:

  • Replace each hardcoded sensitive value with ${secure::property.key.name}

Example:

<!-- Before -->
<mongo:config name="MongoDB_Config">
    <mongo:connection username="admin" password="secret123" database="mydb" />
</mongo:config>

<!-- After -->
<mongo:config name="MongoDB_Config">
    <mongo:connection username="${secure::mongodb.MongoDB_Config.username}"
                      password="${secure::mongodb.MongoDB_Config.password}"
                      database="mydb" />
</mongo:config>

B. Update existing property placeholders to use secure:: prefix:

  • If XML already uses property placeholders like ${email.password}, update them to ${secure::email.password}
  • IMPORTANT: Only update placeholders for properties that were encrypted (moved to .secure.properties)

Example:

<!-- Before -->
<logger message="${email.username}"/>
<logger message="${email.password}"/>

<!-- After -->
<logger message="${secure::email.username}"/>
<logger message="${secure::email.password}"/>

Write the updated XML back to disk after making all changes.

Step 11: Create/Update global.xml

Check if src/main/mule/global.xml exists:

If it exists:

  • Read the file and check if secure-properties configuration already exists
  • If not present, inform the user they need to add this configuration manually:
<secure-properties:config name="Secure_Properties_Config"
    file="local.secure.properties"
    key="${encryption.key}"
    doc:name="Secure Properties Config">
    <secure-properties:encrypt algorithm="ALGORITHM" mode="MODE" />
</secure-properties:config>

If it doesn't exist:

  • Create a new global.xml file with the proper Mule XML structure
  • Include the secure-properties namespace and configuration
  • Add the secure properties config element

Template:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
      xmlns:secure-properties="http://www.mulesoft.org/schema/mule/secure-properties"
      xsi:schemaLocation="
        http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
        http://www.mulesoft.org/schema/mule/secure-properties http://www.mulesoft.org/schema/mule/secure-properties/current/mule-secure-properties.xsd">

    <secure-properties:config name="Secure_Properties_Config"
        file="local.secure.properties"
        key="${encryption.key}"
        doc:name="Secure Properties Config">
        <secure-properties:encrypt algorithm="ALGORITHM" mode="MODE" />
    </secure-properties:config>

</mule>

Step 12: Update pom.xml with Secure Properties Dependency

  • Read the pom.xml file in the project root
  • Check if the mule-secure-configuration-property-module dependency already exists
  • If not present, add it to the <dependencies> section:
    <dependency>
        <groupId>com.mulesoft.modules</groupId>
        <artifactId>mule-secure-configuration-property-module</artifactId>
        <version>1.3.0</version>
        <classifier>mule-plugin</classifier>
    </dependency>
    
  • If the dependency already exists, inform the user and skip this step

Step 13: Update launch.json with Encryption Key

  • Check if .vscode/launch.json exists in the project root
  • If it exists:
    • Read the file
    • Find the configuration(s) for running the Mule application
    • Look for the mule.runtime.args field in each configuration
    • If mule.runtime.args exists, append -M-Dencryption.key=<their-encryption-key> to the existing value
    • If mule.runtime.args doesn't exist, add it with the value -M-Dencryption.key=<their-encryption-key>
    • Write the updated launch.json back to disk
    • Check .gitignore: Ensure .vscode/ or .vscode/launch.json is in .gitignore
      • If .gitignore exists, check if it contains .vscode/ or .vscode/launch.json
      • If neither pattern is found, add .vscode/ to .gitignore
      • If .gitignore doesn't exist, create it and add .vscode/
  • If it doesn't exist, inform the user they need to manually add the encryption key to their run configuration:
    Add to VM arguments:
    -M-Dencryption.key=<their-encryption-key>
    
    Or set as environment variable:
    export ENCRYPTION_KEY=<their-encryption-key>
    

Step 14: Protect Existing Properties/YAML Files in .gitignore

  • For each properties/YAML file that contained sensitive data (identified in Step 4):
    • Add the file to .gitignore to prevent committing sensitive data
    • This includes files like local.properties, dev.properties, etc.

Step 15: Final Summary

Provide a completion summary:

  • ✅ Number of XML files scanned
  • ✅ Number of properties files scanned
  • ✅ Number of sensitive values encrypted
  • ✅ Secure properties file created/updated (e.g., local.secure.properties)
  • ✅ XML files updated:
    • Hardcoded values replaced with ${secure::} placeholders
    • Existing property references updated from ${property} to ${secure::property}
  • ✅ global.xml configured with secure properties
  • ✅ pom.xml updated with secure properties dependency
  • ✅ launch.json updated with encryption key
  • ✅ Existing properties/YAML files with sensitive data protected in .gitignore

Important reminders:

  • DO NOT commit local.secure.properties to version control
  • DO NOT commit local.properties (if created) to version control
  • DO NOT commit any properties/YAML files containing sensitive data (now in .gitignore)
  • Verify that property names in .secure.properties match references in XML files
  • Test the application with the encryption key before committing changes
  • Review all XML file changes to ensure ${secure::} prefix was added correctly

Error Handling

  • If Java is not installed, inform user and exit
  • If JAR download fails, provide manual download instructions
  • If encryption fails, show error and skip that value
  • If XML parsing fails, show warning and continue with other files
  • If file writes fail, show error and list what was completed

Security Best Practices

  • Never log or display sensitive values in plain text
  • Always ask for confirmation before making changes
  • Remind user not to commit secure properties file
  • Suggest adding .gitignore entry

Reference Documentation

For more information, refer to: https://docs.mulesoft.com/anypoint-code-builder/int-create-secure-configs