SOLVED Custom cPanel Module Errors Out in Latest cPanel

Aug 9, 2022
7
0
1
Eu
cPanel Access Level
Root Administrator
I had a working custom cPanel module in /usr/local/cpanel/Cpanel/API that works with calls to...


...which stopped working in a new WHM version. The error in /usr/local/cpanel/logs/error_log is below:
-------------------------
[2023-11-17 07:58:12 +0000] die [Internal Death while parsing unknown 501082] Cannot convert a reference to HASH to typeglob at /usr/local/cpanel/Cpanel/API.pm line 367.
at /usr/local/cpanel/Cpanel/API.pm line 367.
Cpanel::API::_run_module_function(Cpanel::Args=HASH(0x29952c8), Cpanel::Result=HASH(0x2994fd0), "ExampleDevModule", "test_function") called at /usr/local/cpanel/Cpanel/API.pm line 253
Cpanel::API::execute("StarshipDev", "test_function", HASH(0x2994c10)) called at cpanel.pl line 1344
cpanel::cpanel::docpanelaction(HASH(0x2994e08)) called at cpanel.pl line 4587
cpanel::cpanel::run_fast_json_mode() called at cpanel.pl line 927
cpanel::cpanel::script("cpanel::cpanel", "--json-fast-connect", "--stdin") called at cpanel.pl line 324

Cannot convert a reference to HASH to typeglob at /usr/local/cpanel/Cpanel/API.pm line 367.
-------------------------

The error is not possible to debug since it does not give any info about what may be wrong in the module. It also gives the feeling that this module template may now be outdated since it looks like it cant even run the module function. But I cant find any example .pm modules anywhere on the internet and the one at github is from ten years ago. Checking other modules in the API dir does not give enough info about what could be wrong. Also developer documentation is all over the place, links and references given from forum threads or other cpanel documentation end up in 404. I spent an hour in between dead links in between the forum, old documentation etc.

Can someone point me in the direction of an up to date .pm module template or an actual, up to date, working documentation that exemplifies how to implement a module file for this endpoint? Alternatively anything that would allow me to call a WHM api and run a root-owned bash script or a root-owned PHP script in some folder inside the server to do some custom stuff would also work. (I may also run whm and cpanel commands from those scripts)
 
Last edited:

cPanelThomas

Developer
Feb 16, 2023
38
29
93
cPanel
cPanel Access Level
Root Administrator
Which version is this? v116? If this is a bug it would be helpful to know when precisely this started, as I can look up the version's tag in git to try to see what code might have been responsible for this kind of change. Regardless, I can at least give you some context about where this is failing. Like 367 starts a perl eval block which attempts to execute your module's custom function. The function itself is found and executed like so:
Code:
365     if ( my $function_cr = $function_cache{"Cpanel::API::${module}::$function"} ||= "Cpanel::API::${module}"->can($function) ) {
366         local $@;                                                              
367         eval {                                                                 
368             local $SIG{'__DIE__'};                                             
369             $result->status( scalar $function_cr->( $args, $result ) );        
370             1;                                                                 
371         } or do {                                                              
372             _handle_eval_fail( $result, $@ );                                  
373         };                                                                     
374     }
Since this code is inside an eval, It's hard to say without looking at your code what exactly is going wrong, but certainly if I had to guess, the subroutine you've defined which matches what we get with Cpanel::API::ExampleDevModule->can('test_function'); is perhaps returning something unexpected. Given you executed ExampleDevModule yet your stacktrace shows StarshipDev, I'd say that there's likely some shenanigans going on here with what this module is returning via UNIVERSAL::can, which might explain why typeglobs are involved in this error. If you want your module to return a subroutine reference from another module, It's probably better to use the have Cpanel::API::ExampleDevModule::test_function require that other module then return Cpanel::API::StarshipDev::test_function($args,$result); instead of fiddling with the symbol table across namespaces in perl.

Apologies in advance if I misunderstand what's happening here. Errors within an eval block are already frustrating enough to have to deal with at times. The "canonical" example for custom UAPI modules currently lives here: Custom UAPI Module Docs (LINK)
 
  • Like
Reactions: cPRex
Aug 9, 2022
7
0
1
Eu
cPanel Access Level
Root Administrator
Which version is this? v116? If this is a bug it would be helpful to know when precisely this started, as I can look up the version's tag in git to try to see what code might have been responsible for this kind of change.
This is moving from a 110.0.15 server to 114.0.12 server. The earlier one may have been broken recently with an upgrade too, not certain. I just know that it was working some months ago.

Since this code is inside an eval, It's hard to say without looking at your code what exactly is going wrong, but certainly if I had to guess, the subroutine you've defined which matches what we get with Cpanel::API::ExampleDevModule->can('test_function'); is perhaps returning something unexpected.
Basically this:

Code:
package Cpanel::API::ExampleDevModule;

use strict;
use JSON::XS qw( decode_json );
use Data::Dumper qw(Dumper);

our $VERSION = '1.0';

# Cpanel Dependencies
use Cpanel                   ();
use Cpanel::API              ();
use Cpanel::Locale           ();
use Cpanel::Logger           ();
use Cpanel::LiveAPI          ();

# Globals
my $logger;
my $locale;

...........

sub test_function{
    # $Cpanel::CPDATA pulls data from /var/cpanel/users/user file
    my $user = $Cpanel::CPDATA{'USER'};

    my ( $args, $result ) = @_;

    # Build the results.
    my $success = "true";

    if ($success) {
        return 1;
    }
    else {
        return 0;
    }
}
Given you executed ExampleDevModule yet your stacktrace shows StarshipDev, I'd say that there's likely some shenanigans going on here.
That's because I edited the code to post it here, must have missed that edit. There is no mismatch in between module and function names in the code.

The "canonical" example for custom UAPI modules currently lives here: Custom UAPI Module Docs (LINK)
Could package Cpanel::API::Module; not having been declared in this server cause this?
 
Last edited:
Aug 9, 2022
7
0
1
Eu
cPanel Access Level
Root Administrator
I started from scratch and I was able to call a new cpanel UAPI module, then do privilege escalation to a custom admin module and run a root owned php script with the executable bit on that was sitting in /root by using the admin module method below:


We can consider this solved.