13. Writing your own Safe Perl.

Only a restricted set of the Perl language is available: usage of unsafe features (even within eval statements) are trapped and the program is not run. There are many Perl operators not available to the CGI directory in which your program is run. These include the operators that could affect the operating system. The following list is not exhaustive but includes the most common excluded operators:

  • system, `backticks`, exec, fork, syscall, signal handlers, pipes (including open(FOO, "|bar") and open(FOO, "bar|")) 
  • network access (socket, bind, connect, ...) 
  • File munging (rename, link, opendir, chown, ...) 
  • System V IPC (shared memory, message queues, semaphores) 
  • File tests (-r, -w, -l, ...) 
  • Calling perl on other files (require, use, do 'file')

Opening files for reading/writing is restricted. The "open" command is subject to the following restrictions: 

  • Files opened for reading must be owned by the user. Your CGI program is run with a current directory of ~/cgi/. It is strongly recommended that you use relative pathnames (for example, "../public_html/foo").
  • Files opened for writing must be opened by using a filename containing no "/" characters. The filename is taken to live in the directory ~/cgi/out and the file must already exist at the time the open is performed. It can be a symbolic link if desired.

Once you have written and debugged your CGI program, put it in ~/cgi/bin (creating that directory if necessary). There is no need to include a leading "#!" line, nor will one be honoured if you do. Supposing that your username is quux and your program is called foo, the URL to run your program is

http://users.ox.ac.uk/cgi-bin/safeperl/quux/foo

When the web server runs your program it will run it with the privileges of your Oxford account.

Any use of a masked operator in your Perl program will trigger a compile time error (which your browser will display) and the program will not run at all. A "masked operator" is an operator which is restricted but which, unlike "open", is not aliased to a secure sanitised version. The error message will be something like opname trapped by operation mask at line ... where opname is replaced by the name of the offending operator.

Please be aware that, even with the restrictions on what your program can do, it is possible that someone out on the web will be able to persuade it do something you weren't expecting. Even with the file limitations, for example, your program may have a bug which lets someone see the contents of any file you own. You are responsible for the CGI programs you write and you must ensure that your CGI programs do not contravene OUCS rules.

Sorting lists

For sorting lists, the perl built in sort operator is masked (since inconsistent comparison subroutines can cause the underlying C library qsort function to core dump). Two functions are provided for sorting lists in the two most common collating sequences: ASCII and numeric. To sort an array @unsorted into increasing ASCII order use 

    @sorted = sort_ascii(@unsorted);

To sort into increasing numerical order use 

    @sorted = sort_numeric(@unsorted);

If you want a decreasing order, then just use the standard Perl reverse operator on the resulting array.

Common problems

  • Every CGI script must output at least one header line. If your program generates output, it needs a Content-type line indicating what kind of document (MIME type) it is producing. If your script outputs an HTML page, the correct format is: Content-type: text/html

If it is raw text then

Content-type: text/plain

  • The final header output (even if it is only Content-type:) must be followed by two pairs of <CR>/<LF> or, although less correct, two line feeds (ascii 10 decimal). This means there must be a blank line after the last header line.

Up: Contents Previous: 12. Sending email from your CGI script Next: 14. Re-directing to a different site