CyberPanel Community

ClosedCan not initiate remote transfer. Error message: ‘transferStatus’

ST
Sumit Tiwari #1

CyberPanel Remote Backup Transfer Bug Fix

Problem Description

When attempting to transfer websites between two fresh CyberPanel servers using the Remote Backups feature (:8090/backup/remoteBackups), users encounter the following error:

Can not initiate remote transfer. Error message: 'transferStatus'

Or alternatively:

Can not initiate remote transfer. Error message: API request contains potentially dangerous characters: `;`, `&&`, `||`, `|`, `` ` ``, `$`, `../` are not allowed.

Root Causes

Bug #1: KeyError - ‘transferStatus’

Location: backup/backupManager.py line 1253

Issue: The code attempts to access data['transferStatus'] without first checking if the key exists in the response. When the remote API returns an error response without this key, Python raises a KeyError which gets caught and displayed as 'transferStatus'.

Code Before Fix:

data = json.loads(r.text)

if data['transferStatus'] == 1:  # KeyError if 'transferStatus' doesn't exist

Bug #2: Newline Character in IP Address

Location: backup/backupManager.py line 1238

Issue: The machine IP address is read from /etc/cyberpanel/machineIP without stripping the trailing newline character (\n). When this IP (containing \n) is sent to the remote server’s API endpoint, the security middleware (CyberCP/secMiddleware.py line 196) rejects it because newline characters are blocked to prevent command injection attacks.

Code Before Fix:

ipFile = os.path.join("/etc", "cyberpanel", "machineIP")
f = open(ipFile)
ownIP = f.read()  # Contains '\n' at the end

Security Validation in secMiddleware.py:

if isinstance(value, (str, bytes)) and (value.find('\n') > -1 or value.find(';') > -1 or ...):
    return HttpResponse(json.dumps({
        'error_message': "API request contains potentially dangerous characters..."
    }))

Solution

Fix #1: Add Proper Error Handling

Add validation to check if transferStatus key exists before accessing it:

data = json.loads(r.text)

# Check if transferStatus key exists in response
if 'transferStatus' not in data:
    error_msg = data.get('error_message', 'Invalid response from remote server: ' + str(data))
    final_json = json.dumps({'remoteTransferStatus': 0,
                             'error_message': "Can not initiate remote transfer. Error message: " + error_msg})
    return HttpResponse(final_json)

if data['transferStatus'] == 1:
    # ... rest of the code

Also update the else block to safely get error_message:

else:
    error_msg = data.get('error_message', 'Unknown error from remote server')
    final_json = json.dumps({'remoteTransferStatus': 0,
                             'error_message': "Can not initiate remote transfer. Error message: " + error_msg})
    return HttpResponse(final_json)

Fix #2: Strip Newline from IP Address

Change line 1238 to strip whitespace characters:

ipFile = os.path.join("/etc", "cyberpanel", "machineIP")
f = open(ipFile)
ownIP = f.read().strip()  # Remove trailing newline and whitespace

Implementation Steps

Option 1: Manual Patch (Recommended)

  1. Backup the original file:

    sudo cp /usr/local/CyberCP/public/backup/backupManager.py /usr/local/CyberCP/public/backup/backupManager.py.backup
    
  2. Edit the file:

    sudo nano /usr/local/CyberCP/public/backup/backupManager.py
    
  3. Apply Fix #2 (around line 1238):

    Find:

    ownIP = f.read()
    

    Replace with:

    ownIP = f.read().strip()
    
  4. Apply Fix #1 (around line 1251-1253):

    Find:

    data = json.loads(r.text)
    
    if data['transferStatus'] == 1:
    

    Replace with:

    data = json.loads(r.text)
    
    # Check if transferStatus key exists in response
    if 'transferStatus' not in data:
        error_msg = data.get('error_message', 'Invalid response from remote server: ' + str(data))
        final_json = json.dumps({'remoteTransferStatus': 0,
                                 'error_message': "Can not initiate remote transfer. Error message: " + error_msg})
        return HttpResponse(final_json)
    
    if data['transferStatus'] == 1:
    
  5. Update the else block (around line 1278-1282):

    Find:

    else:
        final_json = json.dumps({'remoteTransferStatus': 0,
                                 'error_message': "Can not initiate remote transfer. Error message: " +
                                                  data['error_message']})
        return HttpResponse(final_json)
    

    Replace with:

    else:
        error_msg = data.get('error_message', 'Unknown error from remote server')
        final_json = json.dumps({'remoteTransferStatus': 0,
                                 'error_message': "Can not initiate remote transfer. Error message: " + error_msg})
        return HttpResponse(final_json)
    
  6. Restart CyberPanel services:

    sudo systemctl restart lscpd
    

Option 2: Replace the Modified File

  1. Download the fixed file to your server
  2. Replace the original:
    sudo cp backupManager.py /usr/local/CyberCP/public/backup/backupManager.py
    sudo systemctl restart lscpd
    

Verification

After applying the fix:

  1. Test the remote backup transfer:

    • Go to https://your-server-ip:8090/backup/remoteBackups
    • Enter remote server IP, admin password
    • Select a website
    • Click “Start Transfer”
  2. Check for proper error messages:

    • If there are connection issues, you should now see meaningful error messages instead of 'transferStatus'
    • The security validation error should no longer appear
  3. Enable debug mode (optional):

    sudo touch /usr/local/CyberCP/debug
    

    Then check logs at /usr/local/CyberCP/logs/ for detailed transfer status

Technical Details

Why This Bug Existed

  1. Inconsistent Code Pattern: Throughout the CyberPanel codebase, when reading from /etc/cyberpanel/machineIP, the standard pattern is:

    ipData = f.read()
    ipAddress = ipData.split('\n', 1)[0]
    

    The bug in backupManager.py was an inconsistency where this pattern wasn’t followed.

  2. Missing Validation: The code assumed the API would always return a valid response with transferStatus key, but didn’t handle cases where the API might return an error response with a different structure.

Files Modified

  • File: /usr/local/CyberCP/public/backup/backupManager.py
  • Function: BackupManager.starRemoteTransfer() (note: typo in original function name)
  • Lines Changed: 1238, 1253-1258, 1286-1289

Related Files (No Changes Needed)

  • CyberCP/secMiddleware.py - Security validation middleware
  • plogical/remoteBackup.py - Remote backup utilities
  • api/views.py - API endpoint for remoteTransfer

Additional Notes

Prerequisites for Remote Backup

Ensure both servers have:

  • :white_check_mark: Ports 8090 (CyberPanel) and SSH port (default 22) open
  • :white_check_mark: Admin user has API access enabled
  • :white_check_mark: SSH root login enabled (the code automatically enables this)
  • :white_check_mark: Valid SSL certificates for CyberPanel

Common Issues After Fix

If you still face issues after applying the fix:

  1. Check firewall rules:

    sudo firewall-cmd --list-all
    
  2. Verify API access:

    • Go to Users → List Users
    • Edit admin user
    • Ensure “API Access” is enabled
  3. Check SSH connectivity:

    ssh root@remote-server-ip
    
  4. Review logs:

    tail -f /usr/local/CyberCP/logs/access.log
    tail -f /usr/local/CyberCP/logs/error.log
    

Contributing

If you encounter any issues with this fix or have improvements, please report them to the CyberPanel GitHub repository:

Version Information

  • CyberPanel Version: Stable branch (as of 2025-10-22)
  • Affected Versions: All versions with remote backup feature
  • Fix Status: Pending official merge into stable branch

License

This fix follows the same license as CyberPanel (GPL-3.0)

8 replies
bi
bitnode #2

Im getting Internal Error

The server encountered an unexpected condition which prevented it from fulfilling the request.strong text

ST
Sumit Tiwari #3

Please explain in more detail what error you’re getting and where exactly it appears. A screenshot or the exact error message would help me understand the issue better

bi
bitnode #4

I did only change fix #2 on line 1238 and it is working now. Otherwhise I got a 500-error on the whole server. Thank you. Seems like Cyberpanel is full of these bugs. However have you got google drive backups working? I´m getting a “Scope has changed from “xxxx” to “xxxx xxxx xxxx”.” error when trying to connect my google account.

ST
Sumit Tiwari #5

The error “Scope has changed from ‘xxxx’ to ‘xxxx xxxx xxxx’” occurs because scopes are being stored as a string but Google’s OAuth2 library expects them as a list.

Root Cause

Location 1:

backup/backupManager.py line 121

  • Scopes received from OAuth callback are stored as a string
  • Google expects a list of scopes

Location 2:

plogical/IncScheduler.py lines 262, 280, 372

  • When creating credentials, scopes need to be in list format
  • If stored as string, it causes scope validation errors
bi
bitnode #6

You got a fix for this aswell? :sweat_smile:

ST
Sumit Tiwari #7

The Problem

When you try to connect Google Drive, you get:


Scope has changed from "xxxx" to "xxxx xxxx xxxx"

This happens because the code stores scopes like "scope1 scope2" (string) but Google needs ["scope1", "scope2"] (list).

The Fix

You need to modify two files:

File 1: /usr/local/CyberCP/backup/backupManager.py

Around line 121, change this:


gDriveData['scopes'] = request.GET.get('s')

To this:


scopes_string = request.GET.get('s')

if isinstance(scopes_string, str):

gDriveData['scopes'] = scopes_string.split()

else:

gDriveData['scopes'] = scopes_string if scopes_string else []

File 2: /usr/local/CyberCP/plogical/IncScheduler.py

Find all three places where google.oauth2.credentials.Credentials is created (around lines 259, 275, and 367).

Before each credential creation, add this scope conversion:


scopes = gDriveData.get('scopes', [])

if isinstance(scopes, str):

scopes = scopes.split() if scopes else []

elif not isinstance(scopes, list):

scopes = []

Then use scopes instead of gDriveData['scopes'] in the Credentials call.

How to Apply

  1. Backup the files first:

sudo cp /usr/local/CyberCP/backup/backupManager.py /usr/local/CyberCP/public/backup/backupManager.py.backup

sudo cp /usr/local/CyberCP/plogical/IncScheduler.py /usr/local/CyberCP/plogical/IncScheduler.py.backup

  1. Edit the files with nano or your preferred editor

  2. Restart CyberPanel:


sudo systemctl restart lscpd

  1. Delete your old Google Drive account in CyberPanel and revoke access at https:// myaccount. google. com/ permissions

  2. Set up a fresh Google Drive account - it should work now!

  3. here is working backup and incscheduler github . com /Dynamicearner/cyberpanelrelatedissues/tree/main

Note: The file locations mentioned are based on my configuration. Please edit them according to your own setup if needed.

ST
Sumit Tiwari #8

:joy: yeah if this work for you then tell me by the way in my machine its working

bi
bitnode #9

I´ll try and get back to you! Getting Error message: [Errno 28] No space left on device [736][5009] on remote backups, is it maybe tmp? I have 160gb ssd and 8gig ram so it should be enough

Sign in to reply