SAS Viya Stable 2026.03 adds an important new capability to the LOCKDOWN feature of the SAS Viya programming run-time: the ability to restrict access to URLs for FILENAME URL and PROC HTTP calls in SAS programs.
As the description of What's New in Administration for Stable 2026.03 mentions, and the LOCKDOWN documentation for that release and later explains, four new arguments for the LOCKDOWN statement are supported:
LOCKDOWN URL= 'URL-path-1' < '... URL-path-n '>;
LOCKDOWN URL_FILE= fileref;
LOCKDOWN LIST_URL;
LOCKDOWN URL_CHECK= 'URL-path-to-be-validated';
As an example of the kind of PROC HTTP call you might want to prevent, I'll present a SAS program which publishes some text to Pastebin.com using PROC HTTP and Pastebin's API. I'll walk through the steps to get it working, which you can try for yourself. The text it publishes will be benign, but of course it could contain whatever sensitive data the user running the SAS program legitimately has access to, so this is an example of a potential route for a data breach.
Administrators of SAS Viya deployments with sensitive data obviously won't want their users to be able to paste that sensitive data to public websites!
So I'll go on to demonstrate how to prevent that, using the new LOCKDOWN URL statements in autoexec code. We'll explore what form the URL paths in the LOCKDOWN URL list need to be in to allow access to a URL, and see a way to prevent PROC HTTP and FILENAME URL from accessing any URLs.
This is something all SAS Viya Platform administrators should consider doing.
LOCKDOWN has long been a feature of the SAS programming language. It maintains a list of filesystem paths that user-written code is allowed to access: a LOCKDOWN allowlist. LOCKDOWN also limits access to SAS language features and access methods that could allow users to do unsafe things. SAS Administrators can add paths to the allowlist and/or enable disabled language features and access methods, though they should only do so when absolutely necessary, after a suitable risk assessment, and when other measures are in place to prevent their misuse.
I've written about LOCKDOWN before:
The ability to limit access to URLs for PROC HTTP and FILENAME URL statements is new in SAS Viya 2026.03 for the stable cadence, which means that from mid-May 2026 it should also be part of SAS Viya LTS 2026.03. That ability is managed by administrators using four new arguments to the LOCKDOWN statement:
LOCKDOWN URL= 'URL-path-1' < '... URL-path-n '>;
LOCKDOWN URL_FILE= fileref;
LOCKDOWN LIST_URL;
LOCKDOWN URL_CHECK= 'URL-path-to-be-validated';
By default, all URLs are allowed. If not, this would be a breaking change; SAS customers already using PROC HTTP and FILENAME URL in their code will see their code continue to run normally when they upgrade to SAS Viya 2026.03.
The new ability to limit URL access is an invitation to you as a SAS Administrator to take action.
Consider blocking all except an essential list of URLs in the SAS Viya deployments you maintain. Which URLs do your users need to be able to access through PROC HTTP and FILENAME URL statements, for your SAS programs to work? If you are confident that none are essential, consider blocking access to all URLs with something like:
LOCKDOWN URL='none';
If you can identify a list of URLs that your users programs do need to access, consider adding them to the LOCKDOWN URL list using the statements above - a long list of allowed URLs can be defined in a simple URL_FILE, as the documentation explains.
To ensure that only SAS Administrators can modify their SAS deployment's LOCKDOWN configuration, LOCKDOWN statements only work in autoexec code, which is run during initialization of a programming run-time (compute, connect or batch) session before it enters the locked down state. Only SAS Administrators can modify autoexec code blocks. Autoexec code blocks are available for all three types of SAS Programming Run-time server (compute, connect and batch) and for compute contexts, but connect and batch contexts don't have autoexec code blocks. If a user runs SAS code with a LOCKDOWN statement in it, they get a warning in the program's log output saying:
WARNING: The LOCKDOWN statement was not executed. Set the LOCKDOWN system option and add the LOCKDOWN statement to an AUTOEXEC file or to the INITSTMT statement.
Let's see an example program that makes a PROC HTTP call we would likely want to prevent.
As Pastebin.com's FAQ explains, Pastebin is a website where you can store any text online for easy sharing. The website is mainly used by programmers to store pieces of sources code or configuration information, but anyone is more than welcome to paste any type of text. The idea behind the site is to make it more convenient for people to share large amounts of text online.
After creating a free account, you can paste a string of text containing whatever you like to Pastebin by using a SAS program with a PROC HTTP statement that calls Pastebin's API. The text you paste is then publicly visible to anyone with the URL for your paste, or who finds your paste with a search. There are some limits for free accounts, but in short you can create up to 10 pastes per day.
%let api_dev_key=your_unique_developer_api_key; * Replace the placeholder string with your real Pastebin developer API key;
%let api_paste_name=An example PROC HTTP call we ought to prevent;
/* Generate a unique string of text which we will try to paste to pastebin.com */
%let api_paste_code=If this was really sensitive data posted from &SYSHOSTNAME. on &SYSDAY. &SYSDATE9., we should not be allowed to post it here. Fortunately this is just an example.;
%put &=api_paste_code;
filename resp TEMP;
filename headout TEMP;
filename input TEMP;
/* Populate input file with paramaters for a pastebin HTTP POST request */
data _null_;
file input;
put "api_dev_key=&api_dev_key."
'&' "api_option=paste"
'&' "api_paste_code=&api_paste_code."
'&' "api_paste_name=&api_paste_name.";
run;
/* Use PROC HTTP to create a new paste on pastebin.com containing the text we defined earlier */
proc http
method="POST"
url="https://pastebin.com/api/api_post.php"
in=input
out=resp
headerout=headout;
run;
%put NOTE &=SYS_PROCHTTP_STATUS_CODE;
data _null_;
length text $32767;
retain text '';
infile resp obs=20 end=last; /* Reads first 20 lines */
input;
text=cats(text,_infile_);
if last then call symput('PASTE_URL',text);
run;
%put &=PASTE_URL;
If you run the program and it completes successfully, the last line of should write out SAS log output line something like this:
PASTE_URL=https://pastebin.com/x9bYc0Q6
Browse to that URL, and you should see a page that looks something like this. It may be covered in annoying advertisements, though when I wrote this article, the ads seemed more intrusive on the second day than on the first:
Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.
Irrespective of the ads, it worked. There is nothing sensitive in the string which our example program just published, but to someone with elementary SAS programming skills and access to sensitive data, it would not take much imagination to think of several ways they could modify the code to post real sensitive data to a website where anyone could see it. This is obviously not desirable.
If your code does not run as expected, it can be helpful to inspect the data sent to the remote site, and the headers and response returned. You can add a debug argument to the proc http statement, with various arguments. Here is an example, but take a look at that documentation page to see the meaning of the several values you can set for the debug argument:
/* Use PROC HTTP to create a new paste on pastebin.com containing the text we defined earlier */
proc http
method="POST"
url="https://pastebin.com/api/api_post.php"
in=input
out=resp
headerout=headout
debug level = 2;
run;
Alternatively, you can add these snippets of code to the program. Run them after the corresponding parts of the code above which populates each file - a data step populates the input file, and the proc http call populates the resp and headout files:
/* Print contents of input file to log */
data _null_;
infile input obs=20; /* Reads first 20 lines */
input;
put _infile_; /* Writes line to log */
run;
/* Print contents of headout file to log */
data _null_;
infile headout obs=20; /* Reads first 20 lines */
input;
put _infile_; /* Writes line to log */
run;
/* Print contents of resp file to log */
data _null_;
infile resp obs=20; /* Reads first 20 lines */
input;
put _infile_; /* Writes line to log */
run;
Here are some other troubleshooting suggestions.
| If you see this in the SAS log... | ...try this: |
| PASTE_URL=Bad API request, invalid api_dev_key | Check you replaced your_unique_developer_api_key with your actual long alphanumeric developer API key string from https://pastebin.com/doc_api#1. Make sure you have the correct key value including a leading underscore if there is one. |
|
PASTE_URL=Bad API request, Post limit, maximum pastes per 24h reached
|
Wait and try again later.
Free accounts on pastebin are allowed to create 10 pastes in a rolling 24 hour period. |
|
NOTE: 422 Unprocessable Entity
|
Something about your the PROC HTTP call is malformed and the Pastebin API server couldn't understand it or didn't accept it. Try removing quotes if you have them where my example doesn't, or try encoding the text differently, e.g. with HTMLENCODE. |
It's likely that you do not want your users posting whatever they like to https://pastebin.com, or anywhere else they might be able to send it. Countless other online applications internally to your corporate environment and externally on the internet have REST API interfaces, and many of them allow data to be read or written, usually requiring some sort of authentication or key, but a capable user can likely provide or obtain that key.
So let's start by preventing users from accessing any URL at all with their PROC HTTP and FILENAME URL calls.
Sign in to SAS Viya as a member of the SASAdministrators group. In SAS Environment Manager, navigate to the Configuration page. With the default view set to All services, type 'compute' in the search box and select Compute Service. Collapse the list of configuration instances on the right hand side of the page, so you can see them all. Look for the sas.compute.server: autoexec_code configuration instance:
Click the edit button for the the sas.compute.server: autoexec_code configuration instance, and in the contents section of the Edit sas.compute.server Configuration dialog, add the following line to the existing code:
LOCKDOWN URL='none';
Be careful not to accidentally change or delete any existing autoexec code statements that are important for your environment.
Save your change. User-written SAS code in compute sessions started from this moment onwards should be unable to make PROC HTTP calls or run any FILENAME URL statements.
Switch back to SAS Studio, and start a new SAS compute session. If SAS Studio timed out, a new one will start when you sign in. If necessary, choose Options > Reset SAS Session so that a new SAS compute session starts, with the new LOCKDOWN URL list in effect.
Then try running SAS code with a PROC HTTP statement such as the one in the example program above. The PROC HTTP statement should results in an error message like this:
ERROR: The URL path https://pastebin.com/api/api_post.php is not in the list of accessible URL paths when SAS is in the lockdown state.
Here is an example of the log output you should see in a bit more context, including that error message:
100 /* Use PROC HTTP to create a new paste on pastebin.com containing the text we defined earlier */
101 proc http
102 method="POST"
103 url="https://pastebin.com/api/api_post.php"
104 in=input
105 out=resp
106 headerout=headout;
ERROR: The URL path https://pastebin.com/api/api_post.php is not in the list of accessible URL paths when SAS is in the lockdown
state.
107 run;
NOTE: PROCEDURE HTTP used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
If you run the whole program, there will likely be more error messages after this because the code goes on to read data from the resp output file, and it will not exist if the PROC HTTP call did not run.
We can no longer use PROC HTTP to either read from or publish arbitrary text to an external website - good. That covers a compute server. For completeness, consider doing the same for batch and connect servers too, since each type of SAS programming run-time server has its own separate configuration instances for autoexec code.
For SAS Batch servers, in SAS Environment Manager, on the Configuration page, search for 'batch' and select SAS Batch Service. As before, collapse the configuration instances, and edit sas.batch.server: autoexec_code. In the contents box, add the same LOCKDOWN URL='none'; statement to the existing batch autoexec code:
For SAS Connect servers, in SAS Environment Manager, on the Configuration page, search for 'connect' and select SAS/CONNECT Spawner. As before, collapse the configuration instances, and edit sas.connect.server: autoexec_code. In the contents box, add the same LOCKDOWN URL='none'; statement to the existing batch autoexec code:
Note: You may need to restart the SAS Connect Spawner for this change to take effect.
To allow all users to access a allowlist of URLs that you are happy for them to use with PROC HTTP and FILENAME URL, replace the word 'none' in the LOCKDOWN URL='none'; statement for your overall compute, batch and connect servers with a space-separated list of single-quoted URLs, as the documentation describes.
For batch and connect servers, the overall autoexec code is the only place where you can add a list of allowed URLs.
For a compute server, you might consider creating compute contexts which are only accessible to a subset of your users, and which have additional LOCKDOWN URL statements in their autoexec code blocks to allow users running compute sessions under the context access to some URLs, when other compute sessions cannot access them.
See also: Create group-specific and user-specific compute contexts - Part 1 - manual method and Create group-specific and user-specific compute contexts - Part 2 - scripted method.
With a LOCKDOWN URL='none'; statement in the compute server's global autoexec code block, try adding this statement to a compute context's autoexec code block. In SAS Environment Manager, as a member of the SASAdministrators group, on the Contexts page, change the View to Compute Contexts. Select a compute context (perhaps one which is only useable by a specific group of users), edit it, and on the Advanced tab, add this to the Autoexec content field:
LOCKDOWN URL='/pastebin.com';
Note that the syntax of the URL I used here is similar to the example in the documentation - we'll look more closely at what seems to work and what does not in a moment.
See the effect by switching back to SAS Studio, and make sure you start a new compute session under the compute context you modified. You might need to switch to that compute context (and be signed in as a user with permission to use it, if it is restricted to a group or some individual users), or you might need to reset your SAS session (Options > Reset SAS Session) to pick up the change to the compute context autoexec.
When your new compute session has started, under the modified context, try running the example program again. Because the compute context has a LOCKDOWN URL statement adding the pastebin URL to the list of allowed URLs, it should run successfully and you should see a log output line something like:
PASTE_URL=https://pastebin.com/NNGfmM8y
Pastebin is likely NOT one of the URLs you really want your users to have access to, so having used this to experiment with how to add a URL back to the URL allow list, you should remove it again!
Identify any other URLs that your users need access to, and add those to the URL allow list, with autoexec code statements having the smallest scope of effect available. For batch and connect servers, you can only add URLs to the LOCKDOWN URL allow list globally. For compute servers, you can do it at the compute context level, and you can restrict access to compute contexts if necessary.
If you want to allow access to SAS Viya REST APIs in your deployment, you can find the base URL for those with this code snippet:
%let myviyaurl = %sysfunc(getoption(servicesbaseurl));
%put &=myviyaurl;
If for example this reports that your SAS Viya services base URL is https://myviya.mydomain.com, then you can grant access to all the SAS Viya APIs with
LOCKDOWN URL='https://myviya.mydomain.com';
Or you can selectively grant access to e.g. just the folders API with:
LOCKDOWN URL='https://myviya.mydomain.com/folders';
I experimented a little with the parts of the URL included in the LOCKDOWN URL statement, to see what would result in a site being accessible for PROC HTTP calls, and here's what I found in my experimentation. I tested whether the full pastebin URL should be accessible with LOCKDOWN URL_CHECK= 'https://pastebin.com/api/api_post.php '; in the autoexec too.
This table below summarizes my quick test results, and is not as rigorous as official documentation. Your results may vary, and if they do, please let me know what you find:
| These strings in a LOCKDOWN URL=''; statement allowed PROC HTTP to access the Pastebin URL https: //pastebin.com/api/api_post.php | These strings in a LOCKDOWN URL=''; statement did not allow PROC HTTP to access the Pastebin URL https: //pastebin.com/api/api_post.php |
|
https://pastebin.com
/pastebin.com
pastebin.com
pastebin.com/api |
astebin.com
*astebin.com
/pastebin.com/u |
The gist seems to be that the URL string you allow should be the fully-qualified domain name, and may optionally include part or all of the protocol (e.g. https://) and part or all of an allowed path (e.g. pastebin.com/api).
Additionally, I found it interesting to look at the compute server pod logs after starting a compute session with various lockdown URL statements in effect, to see what paths were in the URL allow list. To do this, you can add a LOCKDOWN LIST_URL; statement to your compute context's autoexec code block, after other LOCKDOWN statements (e.g. including LOCKDOWN URL_CHECK= statements if you wish, not shown below).
Then start a new compute session under that compute context. That is enough to cause the autoexec code, including the LOCKDOWN LIST_URL; statement you added to it, to run - you don't need to run any code in SAS Studio or similar.
I am running my compute session as a user called geladm, hence username=geladm in the command below, to select the compute server pod running that compute session. The following bash command can be run from the command prompt on a server with kubectl access to the compute server pods in your SAS Viya namespace, and with jq installed:
kubectl logs $(kubectl get pods -l launcher.sas.com/requested-by-client=sas.studio,launcher.sas.com/username=geladm \
--field-selector status.phase=Running \
--sort-by=.metadata.creationTimestamp \
--output=jsonpath={.items[-1].metadata.name}) \
-c='sas-programming-environment' \
| grep -i -B 25 -A 3 'NOTE: The LOCKDOWN option has been set. SAS is now in the lockdown state.' \
| jq -R -r '. as $line | try (fromjson| "\(.level | ascii_upcase) \(.timeStamp) '['\(.source)']-' \(.message) " ) catch $line '
In my environment, here is part of the output from the above command, showing that both /none and /pastebin.com are allowed URL paths:
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- Add a url: none.
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- NOTE: AUTOEXEC processing completed.
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- Add a url: /pastebin.com.
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- Allowed urls: /pastebin.com
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- NOTE: These URL paths can be accessed when SAS is in the lockdown state:
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- /pastebin.com
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- /none
INFO 2026-04-30T15:23:15.429000+00:00 [compsrv]- NOTE: The LOCKDOWN option has been set. SAS is now in the lockdown state.
If you get the command working, you can adjust the grep arguments to fine-tune which lines of log output you want to see. In the example above, -B 25 shows 25 lines if output before the line which matched the searched-for string ('NOTE: The LOCKDOWN option has been set. SAS is now in the lockdown state.'), and -A 3 includes 3 lines after that string. Since the searched-for string seems to be in the log output twice (consistently, but I don't know why) we get three lines of log messages after the second instance of that line - I haven't included all of them in the partial output above because they are not as interesting. It doesn't really matter - it's good enough for us to be able to see what's going on.
The key point to take away is that restricting access to URLs with the updated LOCKDOWN feature is something a SAS Administrator should do in their SAS Viya 2026.03 environments and later.
See you next time!
Find more articles from SAS Global Enablement and Learning here.
Nearly 200 sessions are now available on demand with the SAS Innovate Digital Pass.
Explore Now →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.