If you absolutely must enable XCMD, which we do not recommend, then consider enabling SAS Watchdog to limit XCMD access to the filesystem. You should also take a further step to prevent users from changing the value of the SHELL environment variable inside SAS.
A SAS colleague, Phil Hopkins, recently found that in addition to extending the protection of the lockdown paths allow list to Python, R or Java code executed directly in SAS Compute sessions, SAS Watchdog extends the same protection to XCMD statements like filename pipe, the x statement, %SYSEXEC macro statements or the CALL SYSTEM routine. Attempts to access filesystem paths outside the lockdown paths list from XCMD statements are blocked by SAS Watchdog, which is something we were not previously aware of, but it is good news!
The lockdown paths list is part of LOCKDOWN, and you'll find lots of articles explaining what LOCKDOWN does and how to modify its settings for your needs with quick web search, or a search of articles published here. I recently wrote another article about how to see which paths are in the LOCKDOWN paths list, and how to add paths here.
To be clear, SAS Viya is designed to be secure by default. A number of SAS programming language features are disabled by default in SAS Viya, as they are in earlier versions of SAS. The LOCKDOWN SAS System option is enabled by default. Separately, XCMD is disabled by default. We recommend both features stay that way.
We do not recommend anyone write new SAS code that uses XCMD; in general there are far more secure ways to achieve your objectives than user-written shell statements, or the desired result should be reconsidered from a security perspective. If your SAS programs need to interact with files, some better alternatives are discussed at the end if this article. Allowing arbitrary user-written shell statements in SAS programs is just asking for something malicious or damaging to happen.
Customers may wish to - or have to - migrate legacy SAS code which uses XCMD to SAS Viya. These customers would be wise to rewrite migrated code so that it does not use these language features, if they have the choice.
However, in reality we know that some customers' regulatory requirements demand that they to continue to run legacy code unchanged, even in new versions of SAS Viya.
Other customers determine - rightly or wrongly - that the risks to their business arising from rewriting legacy code in this way seem greater than the risks which come with running SAS compute sessions with XCMD enabled. Customers can mitigate some of these risks in a number of ways, such as limiting XCMD to run in SAS compute contexts which can only be used by a select group of users. But if XCMD continues to be used, then you should consider enabling SAS Watchdog to limit the filesystem paths which OS commands run through XCMD can access.
The walkthrough below uses code Phil Hopkins chose to demonstrate what happens with an XCMD statement which tries to access a file outside the LOCKDOWN paths list, in a SAS Viya environment with LOCKDOWN enabled (as it should be), and XCMD enabled.
This environment is running SAS Viya Stable 2025.09, but I think the behavior is likely the same in any version we currently support.
Hopefully it is clear by now that I am not advocating enabling XCMD. However, if you must, one way to enable it for a compute context is to add an attribute to the compute context with a name of allowXCMD, and a value of true.
To test whether XCMD is enabled or not, you can run the following SAS code statement in e.g. SAS Studio:
filename mypipe pipe "cat /etc/csh.login";
If XCMD is not enabled, you will get an error message like this in the SAS program log output:
ERROR: Insufficient authorization to access PIPE.
Normally that is a good thing! However, for this experiment we need to have XCMD enabled.
If XCMD is enabled, that command should run successfully, without producing a log message.
Before we enable Watchdog, we will try to read input from that pipe, to see if we can get the output of the cat statement which tries to list the content of /etc/csh.login, which is outside the lockdown paths list:
/* Create a SAS dataset to store the output of the shell command */
data command_output;
infile mypipe truncover; /* Read from the pipe, handle lines shorter than max length gracefully */
input line $256.; /* Read each line of output into a variable named 'line' */
run;
If SAS Watchdog is not enabled (and XCMD is), the SAS program log output might look something like this:
NOTE: The infile MYPIPE is:
Pipe command="cat /etc/csh.login"
NOTE: 44 records were read from the infile MYPIPE.
The minimum record length was 0.
The maximum record length was 65.
NOTE: The data set WORK.COMMAND_OUTPUT has 44 observations and 1 variables.
In my environment, there are 44 observations in WORK.COMMAND_OUTPUT, and the content of the file is shown in the Output Data tab in SAS Studio:
Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.
So without SAS Watchdog, the end user can read the contents of a file which is outside the lockdown paths allow list. You can perhaps imagine what other operating system commands a user might try to run - there is no restriction imposed by SAS's software here. That is absolutely not desirable.
Enabling SAS Watchdog is a good idea if you are configure open source programming languages for use in SAS Compute sessions. It does add a little overhead to the CPU and memory use of compute server pods, for the watchdog sidecar container and the extra work it does, but in my opinion that overhead cost is very much worth it. It is also important to mention, especially to Kubernetes administrators, that SAS Watchdog runs with elevated privileges to perform its functionality.
To enable SAS Watchdog, follow the instructions in the README file at $deploy/sas-bases/overlays/sas-programming-environment/watchdog/README.md (for Markdown format) or $deploy/sas-bases/docs/configuring_sas_compute_server_to_use_sas_watchdog.htm (for HTML format). Doing that, I added a reference like this to the transformers: section of my deployment's kustomization.yaml file, and then redeployed SAS Viya:
- sas-bases/overlays/sas-programming-environment/watchdog
That line must appear somewhere before this line in the transformers: section :
- sas-bases/overlays/required/transformers.yaml
Having added the line, re-deploy SAS Viya in your usual way. If you have a SAS compute session running, start a new one to test that enabling SAS Watchdog worked. In SAS Studio you can choose Options > Reset SAS Session.
With SAS Viya redeployed and SAS Watchdog now enabled, try the same code again. There still should not be any errors in the SAS logs, but we will see if we get an error message from Linux, or if we can read the output of the cat statement which lists the content of /etc/csh.login:
/* Create a SAS dataset to store the output of the shell command */
data command_output;
infile mypipe truncover; /* Read from the pipe, handle lines shorter than max length gracefully */
input line $256.; /* Read each line of output into a variable named 'line' */
run;
If SAS Watchdog is enabled, the SAS program log output looks like this:
NOTE: The infile MYPIPE is:
Pipe command="cat /etc/csh.login"
NOTE: 1 record was read from the infile MYPIPE.
The minimum record length was 44.
The maximum record length was 44.
NOTE: The data set WORK.COMMAND_OUTPUT has 1 observations and 1 variables.
The key difference is in the last line: there is only 1 observation in WORK.COMMAND_OUTPUT. It contains the string "cat: /etc/csh.login: Operation not permitted".
It looks like this in SAS Studio's output tab:
This is good! It gives a little bit of extra protection to the filesystem inside the SAS Compute server container, from users running XCMD commands to explore filesystem paths they have no reason to be exploring, or to run binaries they have no business to be running. It does not make XCMD safe, but it arguably makes it a little bit safer.
Following an initial review of the SAS Watchdog coverage of XCMD statements, and after reading an earlier draft of this post, Phil Hopkins raised an important concern regarding the SAS SHELL environment variable. In testing I found that if the user changes the value of the SHELL environment variable using an options statement, to change the path to the linux shell inside the Compute server container that is used to run XCMD commands, so that the shell is something other than /bin/sh, then XCMD statements are run successfully using the alternative shell, and SAS Watchdog no longer ensures that commands run through XCMD are monitored by the OS for requests to access to filesystem paths outside the allowlist.
If that seems confusing, it boils down to this. If you run the statement below, or something else similar which sets the SHELL environment variable to something that is a valid symlink to (or an actual executable for) a linux shell, but is not /bin/sh, in an environment with XCMD and SAS Watchdog enabled, user-written XCMD commands still work, but they can access filesystem paths outside the lockdown paths allowlist:
options set=SHELL="/bin/bash";
Fortunately, the SAS Administrator can and should prevent users from modifying the SHELL environment variable.
If you have to enable XCMD, do this in addition to enabling SAS Watchdog. As documented in How to Restrict Environment Variables Defined by the SET= System Option, the steps to follow to add an environment variable to a SAS_OPTIONS_SET_DENY_LIST are described in these two files in your SAS Viya deployment's sas-bases directory:
To save you looking for them, the gist of the documented steps are:
The deny-options-set-variables.yaml file looks like this with just the SHELL environment variable in the deny list, though the docs above suggest some other SAS environment variables you could consider adding too:
apiVersion: builtin
kind: PatchTransformer
metadata:
name: deny-set-options-variables
patch: |-
- op: add
path: /data/SAS_OPTIONS_SET_DENY_LIST
value: "SHELL"
target:
kind: ConfigMap
name: sas-programming-environment-path-config
After following those steps, in a new SAS compute session an attempt to change the SHELL environment variable in SAS program code fails, and produces this warning in the SAS program log:
WARNING: The SHELL variable cannot be set using the options statement.
The same method can be used to prevent users from modifying other environment variables. This is a bit like using restricted_options to prevent users from modifying other SAS system options for the programming run-time. For more on that, see Restricted options in SAS Viya compute, connect and batch servers. There are other ways to set SAS environment variables, but I think they all require you to be a SAS administrator. I believe this step is sufficient to close that avenue off from users. Please let me know if I missed a way end users can modify SAS environment variables.
But of course, discussing steps to secure XCMD is missing a greater point: if you take security for your SAS Viya deployment sufficiently seriously, do not enable XCMD at all. Instead, if you can, it is preferable to rewrite or change the design of migrated code so that it does not need to run user-written commands in a shell inside the SAS compute (or connect or batch) container at all.
XCMD is often used to interact with files. There are literally dozens of SAS functions for dealing with files, none of which require XCMD to be enabled. Examples include FILENAME (but not filename pipe which does use XCMD), FILEEXIST, FEXIST, FGET, FOPEN, FPUT, FREAD, FWRITE, and many, many others in the External Files category of SAS Functions and CALL Routines. All of these functions are of course protected by LOCKDOWN by default.
As mentioned at the beginning of this article, to learn what paths are in the LOCKDOWN paths allow list, or to add paths to it (as seen by the SAS compute, connect or batch process running inside its sas-programming-environment container in its pod), see my recent post Managing the LOCKDOWN allowlist: find out what paths are included, and add paths where necessary.
My thanks to Phil Hopkins for discovering the way SAS Watchdog also limits filesystem access for commands run through XCMD, for recognizing that changing the SHELL environment variable in SAS would potentially interfere with this, and for the SAS code statements I have replicated here to demonstrate it - they are great examples and illustrated what happened nicely. Thank you very much to Bob Huemmer for confirming our understanding of how SAS Watchdog worked, and that it covered a feature not included in our SAS Help Center documentation at the time.
Any errors or omissions in this post are mine.
See you next time!
Find more articles from SAS Global Enablement and Learning here.
Thanks for this.
But this comment in the example test program is backwards.
infile mypipe truncover; /* Read from the pipe, truncate long lines */
The lines themselves are not truncated by the TRUNCOVER option. In fact the effect is just the opposite. The TRUNCOVER option allows the reading of lines that have fewer bytes than the INPUT statement requested.
Thank you very much for calling out my mistake @Tom , you are correct.
I have edited the comment in both places, changing the comment about the truncover option to the infile statement from "truncate long lines" to "handle lines shorter than max length gracefully".
Let me see if I have this right: the INPUT statement in the code above expects to read in lines that contain just one value, a single 256 character string. It stores that string in a dataset column named 'line', with an observation for each line of input read in, as usual. The truncover option tells the INPUT statement to accept input data from the file when that input has fewer characters than 'expected', i.e. when it is less than 256 characters long, and will still put that data in the 'line' column for this observation rather than setting its value to missing.
Ref: SAS® Viya® Platform Programming Documentation > INFILE statement, TRUNCOVER option , and https://support.sas.com/resources/papers/proceedings/proceedings/sugi26/p009-26.pdf, among many others.
I am curious as to what the reasoning is behind not allowing "arbitrary user-written shell statements". Wouldn't the underlying OS (Redhat, or whatever) already be configured in such a way that it rejects anything that is forbidden for that user -- access or modification to certain directories / files, sudo commands, ssh, etc.?
Hi @quickbluefish, thanks for your comment. It depends of course on what sensitive, confidential or business-critical content the SAS Viya deployment contains, and how much your organization depends on it continuing to function well.
My team here at SAS works mostly with short-lived, automatically-provisioned lab environments for our classes, that have no sensitive or confidential data in them. The biggest inconvenience that can arise from someone running destructive or resource-intensive commands on them would be to the single user who booked the collection themselves. They are isolated enough, and we give students root access to the lab environment anyway, so the risk of enabling XCMD and the other related functions that allow arbitrary user shell commands is pretty small. rm -rf / or similar is only going to kill the environment, and it was going to be terminated in a few hours or days anyway. Nobody but the student is usually using it. It can't use more CPU or RAM than we allocate to it. So we can enable XCMD in these environments without too much worry.
Some of our customers will use SAS Viya, and other versions of SAS software in a similarly low-risk way.
But it is possible to have a user do something foolish or destructive, like delete files on a path they legitimately have access to, or fill up a volume with a large amount of data, or go looking for data or configuration information on the server with a view to doing something of which the SAS or Kubernetes administrator would not approve. What it they try to download and run malware, or send company secrets to somewhere they shouldn't?
Administrators of production environments that manage customer data or personally-identifiable information, or operate in higher-risk environments where service continuity is important may be prohibited by their regulator from, or at least strongly against, ever letting their end users start a shell session even in the SAS Viya compute server containers. Yes, they should configure the OS and data sources on the filesystem and otherwise to prevent unauthorized access, but with a bit of imagination one can usually come up with something a user could do, unwittingly or deliberately, to make a mess or cause a security breach. Why would a SAS Administrator who will be held responsible for an infosec incident let them have XCMD if they don't need it?
Thanks @DavidStern - I think I'm just an ornery dinosaur who groans every time he sees a product gradually being 'nerfed' over time. I have worked in both kinds of environments over the past nearly 20 years - those where SAS users were granted user-appropriate access to the underlying file system through a command line interface and those where not only was there no terminal access, but not even xcmd access. Interestingly, there always seemed to be a positive correlation between the level of access and the sensitivity of data (and by sensitive, I mean does-not-get-more-sensitive wrt healthcare data). Access and resource use was always monitored and controlled by sys admins, uploads and downloads tracked/scanned, dire warning messages prevalent, etc. The data and analytic tools were on firewalled remote servers and users underwent basically the same level of background check as the sys admins (and I get that background checks are not free). Conversely, I have worked in environments where the healthcare data were what I would call, "Toys-R-Us level", and the analytic environment was entirely point-and-click and without any ability to automate things or perform file management or version control tasks on a reasonably low, software-agnostic level. Now I work for a giant company where SAS is rapidly being phased out, but with the little bit of access we still have, we cannot even get SAS to connect successfully with the company BitBucket, so users (being as there's no low-level access) are literally left-clicking on each individual program and downloading as a means of "version control". Sure, it's probably fixable (I have watched and tried to follow the SAS videos without success), but institutional knowledge in IT is in short supply and demand is less and less as new users gravitate toward other tools. I guess I feel that idiot-proofing and the "walled garden" approach can only go so far before it becomes, on balance, detrimental.
Sorry for the diatribe - I do get what you're saying that sys admins should not have to be responsible for negligent or malicious users and that this is the direction the industry is moving anyway ("Zero Trust" and what-not) and that's not SAS's fault. Thanks for taking the time to respond!
Thank you again @quickbluefish for sharing this perspective - all valid points, and I sympathize!
I have to chime in with @quickbluefish here.
For more than two decades, I was responsible for the data warehouse of a major insurance company, and through all this time we had commandline access for all users and XCMD enabled. And - lo and behold! -
we never had any issue beyond a user wrecking their own data and needing a restore from the daily backup.
In fact, we had many more such "accidents" through standard SAS code than through the mis- or abuse of command line tools.
If a system is set up insecure, standard SAS means (FOPEN, DOPEN, DREAD etc) can easily do the same harm that can be done from the commandline.
Note that we ran on AIX (not the crap from Redmond,WA) and the people responsible knew how to not shoot their own foot.
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and save with the early bird rate—just $795!
The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.