Is it possible to access the attachments in public or no user role KB articles without login?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-04-2019 10:00 AM
We have CMS self service portal and KB articles are show in the portal. The KB articles have no role (or I can make it public) and I checked the "Display Attachment" check box. My problem is that end users can see the articles without login but, they can not download the attachment in the articles. Any help is appreciate!

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-04-2019 10:17 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-04-2019 11:55 AM
Public KB articles' attachments can be download by users logged to the system. My problem is that I need enable users not logged to the system (public users) should be able to download attachments attached to the KB articles.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-03-2020 08:37 PM
For future folks that find this while looking for a way to make attachments public. Note: Always check for your particular situation that ServiceNow hasn't added the functionality.
Don't try to open up the sys_attachment processor to the public. You will inevitably create a security vulnerability, if not immediately, at some time in future when some unintentional ACL modification is made. As processors are deprecated you should go down the path of an API.
In our case, we used a 'Scripted REST API', with the security turned off, then performed appropriate checks within the script itself to ensure the sys_id couldn't be brute forced to gain access to something they shouldn't. Never trust ACLs alone when opening things to the public. The censored code below just ensures the attachment is attached to something we want the user to retrieve. The first checks the table, the second part makes sure the attachment is attached to an exposed 'article'.
The GET looked like this
Note that the 'content-type' is critical to allow the browser to save the attachment instead of just displaying it.
Final step is to replace all of the sys_attachment links for your exposed 'articles' with your new API.
In this case a Business Rule on the table checks the html field for all sys_attachment links and replaces them with the API. The sys_id stays the same. This results in a clickable link that acts just as the sys_attachment processor would. Again, ensure you add security in your scripted REST to ensure that someone cannot access an attachment sys_id they should not.
Good luck!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-04-2021 01:03 PM
For anyone else finding this useful, and that may want to do this in a scoped app here is the code:
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
var grSA = new GlideRecord('sys_attachment');
grSA.addEncodedQuery("file_name=<filename>");
grSA.orderByDesc('sys_created_on');//optional
grSA.setLimit(1);// I was filtering for the most recent attachment with a particular name. You do you.
grSA.query();
if (grSA.next()) {
var hdrs = {};
hdrs['Content-Type'] = 'application/octet-stream';
hdrs['Content-Disposition'] = 'attachment;filename=' + grSA.file_name;
response.setStatus(200);
response.setHeaders(hdrs);
var gsa = new GlideSysAttachment();
var attachmentStream = new gsa.getContentStream(grSA.sys_id); //This is the change for a scoped app. see examples here: https://developer.servicenow.com/dev.do#!/reference/api/paris/server/sn_ws-namespace/c_RESTAPIResponseStream#r_RESTAPIResponseStream-writeStream_Object
var writer = response.getStreamWriter();
writer.writeStream(attachmentStream);
} else {
response.setStatus(404);
}
})(request, response);