33

CodeIgniter is giving me a Disallowed Key Characters error. I've narrowed it down to the name attribute of a form field: name='prod[50-4121.5]' but I'm not sure what to do about it.

Kenny Linsky
  • 1,726
  • 3
  • 17
  • 41
John Rand
  • 995
  • 2
  • 10
  • 20

21 Answers21

37

The problem is you are using characters not included in the standard Regex. Use this:

!preg_match("/^[a-z0-9\x{4e00}-\x{9fa5}\:\;\.\,\?\!\@\#\$%\^\*\"\~\'+=\\\ &_\/\.\[\]-\}\{]+$/iu", $str)

As per the comments (and personal experience) you should not modify they Input.php file — rather, you should create/use your own MY_Input.php as follows:

<?php

class MY_Input extends CI_Input {

    /**
     * Clean Keys
     *
     * This is a helper function. To prevent malicious users
     * from trying to exploit keys we make sure that keys are
     * only named with alpha-numeric text and a few other items.
     * 
     * Extended to allow: 
     *      - '.' (dot), 
     *      - '[' (open bracket),
     *      - ']' (close bracket)
     * 
     * @access  private
     * @param   string
     * @return  string
     */
    function _clean_input_keys($str) {
        // UPDATE: Now includes comprehensive Regex that can process escaped JSON
        if (!preg_match("/^[a-z0-9\:\;\.\,\?\!\@\#\$%\^\*\"\~\'+=\\\ &_\/\.\[\]-\}\{]+$/iu", $str)) {
            /**
             * Check for Development enviroment - Non-descriptive 
             * error so show me the string that caused the problem 
             */
            if (getenv('ENVIRONMENT') && getenv('ENVIRONMENT') == 'DEVELOPMENT') {
                var_dump($str);
            }
            exit('Disallowed Key Characters.');
        }

        // Clean UTF-8 if supported
        if (UTF8_ENABLED === TRUE) {
            $str = $this->uni->clean_string($str);
        }

        return $str;
    }

}

// /?/> /* Should never close php file - if you have a space after code, it can mess your life up */

++Chinese Character Support

// NOTE: \x{4e00}-\x{9fa5} = allow chinese characters
// NOTE: 'i' — case insensitive
// NOTE: 'u' — UTF-8 mode
if (!preg_match("/^[a-z0-9\x{4e00}-\x{9fa5}\:\;\.\,\?\!\@\#\$%\^\*\"\~\'+=\\\ &_\/\.\[\]-\}\{]+$/iu", $str) { ... }

// NOTE: When Chinese characters are provided in a URL, they are not 'really' there; the browser/OS
//   handles the copy/paste -> unicode conversion, eg:
//        一二三  -->  xn--4gqsa60b   
//   'punycode' converts these codes according to RFC 3492 and RFC 5891.
//   https://github.com/bestiejs/punycode.js ---  $ bower install punycode
Tyler Wall
  • 3,747
  • 7
  • 37
  • 52
  • 1
    Upvoting the more elegant solution. Or you can remove the `preg_match` entirely. I'm not aware of any inherent security vulnerabilities that this might open. – Jonah Aug 28 '14 at 18:25
  • Where should I place this file? – Charlesliam Dec 08 '14 at 08:18
  • You should be able to create a `MY_Input.php` file in a Core Folder (or wherever your `My_*` files are - I have modified my Codeigniter Instance for security purposes.) – Tyler Wall Dec 09 '14 at 18:18
  • Ok, so I manage to override the function '_clean_input_keys($str)' placing the file MY_Input.php into application/core/, however I can't go thru when I'm processing the form. @Wallter, the format of my fields are name[number], because I can change de amount of fields dynamically. Do I need to do something else? Thanks! – Lvkz Dec 29 '14 at 15:59
  • This is great.I just change my span html 0.0 t 0 and it worked – Rasel Aug 23 '16 at 06:49
27

Open libraries/Input.php (system/core/Input.php in CI version 2.0+) and locate function _clean_input_keys($str){, The whole block should look like so:

function _clean_input_keys($str)
{
    if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
    {
        exit('Disallowed Key Characters.');
    }

    return $str;
}

Modify the PCRE sot that it allows the new chars.

Please not that the char thats missing is the .(dot) and you should always escape the .(dot) in Regular Expressions as they will otherwise allow any single char.

/^[a-z0-9:_\/-\.]+$/i
Wesley Murch
  • 101,186
  • 37
  • 194
  • 228
RobertPitt
  • 56,863
  • 21
  • 114
  • 161
9

To use CodeIgniter with jQuery Ajax, use "Object" as data instead of Query string as below:

$.ajax({
    url: site_url + "ajax/signup",
    data: ({'email': email, 'password': password}), //<--- Use Object
    type: "post",
    success: function(response, textStatus, jqXHR){
        $('#sign-up').html(response);
    },
    error: function(jqXHR, textStatus, errorThrown){
        console.log("The following error occured: "+
                    textStatus, errorThrown);
    }
});
  • I've been searching for hours trying to find why my posted data wouldn't return any of the PHP headers. Thank you for this answer. – Matthew Jul 25 '17 at 23:30
3
function _clean_input_keys($str)
{
if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
{
exit('Disallowed Key Characters.');
}

return $str;
}

Please add .$str to exit('Disallowed Key Characters.'); Like: exit('Disallowed Key Characters. '.$str);

to help you in your search for rogue errors.

richardwhitney
  • 506
  • 1
  • 6
  • 21
3

I had the same error after I posted a form of mine. I simply missed the opening quote in one of my input name attributes. I had:

<input name=first_name">

Fixing that got rid of the error.

Keith Ritter
  • 351
  • 3
  • 3
3

Step1. Search for function _clean_input_keys on /system/core/Input.php

Step2. Modify this line

exit(‘Disallowed Key Characters.’);

to

exit(‘Disallowed Key Characters.’ . $str);

Step3. Refresh page to see the characters which generate the error

Step4. If you need to add those characters into the exception list, just add to this line

if ( ! preg_match(“/^[a-z0-9:_/-]+$|/i”, $str))

I add | (pipe) character on the example above

Uttam Panara
  • 541
  • 2
  • 10
  • 28
2

I got this error when sending data from a rich text editor where I had included an ampersand. Replacing the ampersand with %26 - the URL encoding of ampersand - solved the problem. I also found that a jQuery ajax request configured like this magically solves the problem:

request = $.ajax({
        "url": url,
        type: "PUT",
        dataType: "json",
        data: json
    });

where the object json is, surprise, surprise, a JSON object containing a property with a value that contains an ampersand.

DavidHyogo
  • 2,838
  • 4
  • 31
  • 48
  • Thank you!, i was working with curl and adding `curl_setopt($ch, CURLOPT_HTTPHEADER,array("Content-Type: application/json"));` , which is the equivalent of `dataType:"json"`, solve my problem. – bistoco Oct 26 '16 at 01:21
2

Open libraries/Input.php (system/core/Input.php in CI version 2.0+) and locate function _clean_input_keys($str){,

Modify if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str)) to if ( ! preg_match("/^[a-z0-9:_\-|]+$/i", $str))

Eugine Joseph
  • 1,552
  • 3
  • 18
  • 40
2

I had the same problem thanks to french specials characters. Here is my class in case anybody needs it. It has to be saved here : /application/core/MY_Input.php

(also this extension will report witch character is not allowed in the future)

class MY_Input extends CI_Input {

function __construct()
{
    parent::__construct();
}

/**
* Clean Keys
*
* This is a helper function. To prevent malicious users
* from trying to exploit keys we make sure that keys are
* only named with alpha-numeric text and a few other items.
*
* @access   private
* @param    string
* @return   string
*/
function _clean_input_keys($str)
{
    if ( ! preg_match("/^[a-z0-9:_\/-àâçéèêëîôùû]+$/i", $str))
    {
        exit('Disallowed Key Characters : '.$str);
    }

    // Clean UTF-8 if supported
    if (UTF8_ENABLED === TRUE)
    {
        $str = $this->uni->clean_string($str);
    }

    return $str;
}

}

Read The Friendly Manual about core classes extension : http://ellislab.com/codeigniter/user-guide/general/core_classes.html

Guidouil
  • 1,694
  • 2
  • 18
  • 18
2

I had the same error after I posted a form of mine. they have a space in to my input name attributes. input name=' first_name'

Fixing that got rid of the error.

Ron raj
  • 21
  • 1
2

Php will evaluate what you wrote between the [] brackets.

$foo = array('eins', 'zwei', 'apples', 'oranges');
var_dump($foo[3-1]);

Will produce string(6) "apples", because it returns $foo[2].

If you want that as a string, put inverted commas around it.

Tilman Koester
  • 1,739
  • 2
  • 11
  • 25
  • Codeigniter filters the URI for a specific traditional set of characters, you have to 'permit' now chars if you want them to be passed, and the the `QUERY_STRING` is not the same as `GPC` so there parsed differently. – RobertPitt Nov 16 '10 at 20:19
  • @RobertPitt haha, I still don't really get his question ;) – Tilman Koester Nov 16 '10 at 20:25
  • 1
    when you go `http://site.com/controller/[a][b]` it strikes an error because CI found a `[` and `]` which are not permitted by default :) – RobertPitt Nov 16 '10 at 20:26
  • @RobertPitt Oh, I get your comment, just didn't think the question had anything to do with URIs ;) But then again the question was a bit short anyways. – Tilman Koester Nov 16 '10 at 21:00
1

In my case, i was serializing an input form using jquery serialize() and then urlencoding it using encodeURIComponent().

var datas = form.serialize();
encodeURIComponent(datas);
$.getJSON(url,datas,function(){});

and codeigniter was giving the disallowed character error.

i figured the issue here was, jquery serialize gives an encoded output and i was again encoding it with the encodeURIcomponent which was unnecessary, and when codeingiter decoded it it was not getting the actual string as some part was encoded twice. i will explain it with an example.

string: quantity[]=1&option=sell

urlencoded while serializing: quantity%5B%5D%3D1%26option%3Dsell

again urlencoded with encodedURICompontent(): quantity%255B%255D%253D1%2526option%253Dsell

---at codeigntier

urldecode: quantity%5B%5D=1&option=sell

which has disallowed charecters as per the input class regex.

note: this is not an answer to this question, but would help to check if one is encountering this error...thanks.

MortalViews
  • 1,250
  • 12
  • 16
1

In Ubuntu, you can solve the problem by clearing the cookies of your browser. I had the same problem and solved it this way.

Jamshid Hashimi
  • 7,639
  • 2
  • 28
  • 27
  • if one is using http://localhost, and switching between several frameworks/languages locally, then this should be the first thing to check. – Kinjal Dixit May 26 '14 at 04:52
1

Took a while to figure this one out. Seems most of us missed the obvious error…the last “-” is not escaped.

Adding the . and | as I’ve seen other suggest may work for you, but the regex was supposed to be:

if ( ! preg_match("/^[a-z0-9:_\/\-\.|]+$/i", $str))  
1

i saw this error when i was trying to send a form, and in one of the fields' names, i let the word "endereço".

echo form_input(array('class' => 'form-control', 'name' => 'endereco', 'placeholder' => 'Endereço', 'value' => set_value('endereco')));

When i changed 'ç' for 'c', the error was gone.

heavyrick
  • 384
  • 7
  • 16
1

I had this issue but my problem was that I by mistake added a space before the name of the input like so:

<input type="text" name=" evening_time_phone">

When it shpuld be like this:

<input type="text" name="evening_time_phone">
Waqleh
  • 9,741
  • 8
  • 65
  • 103
0

I have the same problem and I've found it is in domain name of the email address which is somehow changed from . to _ like: name@domain_com instead name@domain.com

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
0

In my experience, it could be caused by uncompleted syntax, like :

$('#teks').val

instead of

$('#teks').val()
timbre timbre
  • 12,648
  • 10
  • 46
  • 77
mas_budhi
  • 31
  • 6
0

The error I referenced was generated in system/libraries/Input.php (about line 215 - look for function _clean_input_keys($str).

The regex there does not allow for the dot character in an index. I changed it so it would.

John Rand
  • 995
  • 2
  • 10
  • 20
0

Replace the below Code in the _clean_input_keys function

    if ( ! preg_match("/^[a-z0-9:_\/-]+$|/i", $str))
    {
        exit('Disallowed Key Characters.\n');
    }
    if (UTF8_ENABLED === TRUE)
    {
        $str = $this->uni->clean_string($str);
    }

    return $str;
0

In most of the cases when you have a existing software and you are trying to deploy in a new enviroment this kind of error should be caused by the PHP property

short_open_tag

Check if you have enabled in your new enviroment. In other words PHP couldn't read the tags in your code.

Tuxton
  • 1
  • 2