Shared Services account¶
A shared system account for running web services is preferred as it can enable functionality for users that they cannot (or should not) perform themselves, eg database modifications (and for that, you should seriously consider Data Controlller for SAS®). It can also avoids unix permissions issues, as created files are owned by default under the end user identity.
However - as it is a shared account, the ability to run code under this identity should be appropriately governed. In particular, code injection must be protected against - for this reason, URL parameters are a bad idea, much better to send tables using an adapter such as SASjs.
It is also recommended to ensure you have a secure release process, which includes code review and automated testing, to ensure the safety of your production environment.
By default your services will run on a Stored Process server under the shared credentials stored in the
SAS General Servers group group (
sassrv per factory settings).
It is also possible to run STPs under a Workspace Server context (where end user OS credentials match
By default, services will run on the SAS Compute server under the client identity. Since Viya 3.5 it is also possible to run under a shared identity, and to pool the session - see documentation.
For enhanced sas viya security you can even determine which users can execute code on a particular context (all authenticated users, or a particular set of users.)
The recommended SASjs folder structure is to group services into app subfolders, so that security can be applied at backend. The app itself can also be secured by setting permission on the parent folder. There is one more thing to consider - services can be viewed (and executed) by anyone who has the READ permission, either using the
SERVERURL/SASStoredProcess?_action=1063 url or by navigating in
SASJobExecution on Viya. Therefore your services should be built in such a way that no damage would be caused if an end user were to accidentally 'click' on one of the services and run it.
This folder structure is enforced when using the sasjs-cli tool.
Services should be built in such a way that they can be safely executed more than once. This is because it's possible that it WILL be run more than once (eg if the user clicks a button twice in succession).
The use of URL parameters (which are automatically converted to macro variables in a SAS session) should be avoided. Apart from the risk of code injection, there are also a number of reserved variables that may cause unintentional naming conflicts. Use the SASjs adapter instead!
Note that Viya automatically escapes certain characters (eg
;) to reduce this risk.
An integrity hash is a checksum of a file - if just one character inside a file is changed, the checksum is totally different. This makes it a great tool for verifying that a CSS or JS file has not been modified since the checksum was generated. Content served over http (without SSL certificates) are extremely susceptible to Man in the Middle (MitM) attacks. For this reason, it is best practice to either bundle all your dependencies inside your app, or apply SubResource Integrity (SRI) checking as per the w3.org spec. The syntax looks like this:
<script src="https://firstname.lastname@example.org/index.js" integrity="sha256-651B1pxDxaKb9yhXQOUSohZ+Nq9Txfc3gXlX/GSw1RQ=" crossorigin="anonymous"></script>
If your CSS or JS files are released via github, then they are automatically available with SRI checks using JSDelivr - for instance, to get the latest script tag for SASjs you can just click here and select "SRI".
If your files are elsewhere, or you'd like more control over the build, you can also generate the integrity hash yourself - here is the syntax:
cat myfile.js | openssl dgst -sha384 -binary | openssl enc -base64
Third Party Server¶
By setting up a dedicated web server and whitelisting it within SAS, you can isolate your frontend activities and enable frontend developers to deploy without having to enable access to the SAS Web Server directly.
Web devs can then work locally and push to that server, or work on the server directly. One option for enabling remote (cloud) development is the open-source server edition of vscode: https://github.com/cdr/code-server (note - this won't work with vscodium due to non open-source components.
To whitelist the server in Viya, open
Environment Manager -> Configuration -> View -> Definitions and select
sas.commons.web.security.cors. Make sure your domain (or
*) is entered under
target=blank is unsafe¶
Commonly used to open new tabs, be very careful opening external sites using a naked
_target=blank attribute - this opens a vulnerability for hijacking.
To avoid this, simply add a
rel="noopener noreferrer" attribute to the anchor tag.
Content Security Policy¶
This is a server setting that restricts the types of content that pages served from your domain can fetch. This might be to specific urls, or types of content (such as inline styles, base64 images, or external JS files). If you are being restricted by CSP policy you will see a message like the one below in your console window:
Content Security Policy: The page's settings blocked the loading of a resource at https://email@example.com,firstname.lastname@example.org,npm/@email@example.com ("default-src").
On SAS 9 the CSP configuration can be found in the following file location:
The line to be modified will look something like this:
Header set Content-Security-Policy "default-src 'self' ; script-src 'unsafe-inline' https://cdn.jsdelivr.net https://stackpath.bootstrapcdn.com; font-src 'self' data: fonts.gstatic.com;style-src 'self' fonts.googleapis.com"
After modifying the CSP the mid tier will need to be restarted (
Whilst it is often impossible to implement maximally secure settings, the configuration goal should be to enable as few of the 'insecure' ones as possible. More information is available here.
Note that the "default-src" provides a fallback where particular urls (eg font-src) are not specified.
It's also possible to go a step further and set the CSP policy in the HTML (rather than the headers from the web server). You may consider this for sensitive applications. An example:
<meta http-equiv="Content-Security-Policy" content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'">