← All KB Checks
HIGHScriptOnlyCheck

Attachment Role Restriction

nowisor-attachment-role-restriction··Source on GitHub →

Attachment Role Restriction

This page describes the nowisor-attachment-role-restriction check from the nowisor Instance Scan Pack v1.0.0. The check audits the glide.attachment.role system property and produces a finding when the property is not registered, is empty, or is set to the literal string 'public'. The default value on Zurich Patch 6 is 'public' — meaning the OOB configuration grants attachment access to any authenticated user. Production deployments are expected to set this to a more restricted role explicitly.

What this finding means

Your ServiceNow instance is using the OOB default for attachment role restriction — the property glide.attachment.role is either unset, empty, or 'public'. All three states have the same effective behavior: any authenticated user can upload attachments to any record they can read, and download attachments from any record they can read.

The 'public' value is misleading by name. It is not a "no-role-required" sentinel — it is the literal name of an OOB role (public) that every authenticated user holds by virtue of authenticating. The effect is the same as no restriction: any authenticated session can attach files. The property exists precisely to allow tightening this default; production deployments routinely set it to a more restrictive role like attachment_writer or a custom role created for the purpose.

The check is a single aggregate finding — the property either passes or it doesn't, the finding either fires or it doesn't. The evidence in the finding records the current property value so you can distinguish between the three failure modes (NOT_REGISTERED / empty / 'public').

Why it matters for your compliance

Attachment access is one of the lowest-friction data-egress paths in the platform. Regulators that care about data classification and protection treat attachment controls as a first-tier concern.

NIS2 Article 21§2(h) — policies and procedures regarding the use of cryptography and, where appropriate, encryption. While 21§2(h) is nominally about cryptography, NIS2's interpretation extends to the controls that protect data from unauthorized access — including the role-based gates on data-bearing surfaces like attachments. An attachment surface open to all authenticated users is a structural gap in the data-protection layer that NIS2 expects entities to maintain.

ISO 27001 A.5.34 — privacy and protection of personally identifiable information (PII). A.5.34 specifically addresses controls on personal data. Attachments uploaded to ServiceNow records frequently contain PII — HR documents, customer correspondence, identity documents. A broadly accessible attachment surface defeats the record-level ACLs that normally protect PII; the attachment metadata table (sys_attachment) and content table (sys_attachment_doc) become side-channels that bypass the parent-record controls.

DORA Article 9 — ICT risk management framework. DORA Article 9§4(c) covers detection of anomalous activities. Financial entities under DORA frequently store sensitive operational data in attachments (incident response artifacts, change documentation). An attachment surface accessible to all authenticated users makes anomaly detection essentially impossible — every authenticated user is a legitimate accessor by definition, so anomalous access patterns are statistically invisible.

The check is severity 2 (high). The failure mode is conditional — exposure depends on what sensitive content actually exists in attachments — but the conditional is common in practice. Most instances have at least some PII or operational sensitivity in the attachment surface; very few have audited the attachment content to confirm none.

The attack path

The path is opportunistic rather than targeted. An authenticated attacker explores the attachment surface looking for content that is more sensitive than the record-level ACLs would suggest.

Step 1 — Authenticate. The attacker has a legitimate authenticated session — either a compromised user account, an insider role, or an account obtained through prior phishing. The session has minimal permissions; itil or ess is enough.

Step 2 — Enumerate sys_attachment. With glide.attachment.role set to 'public', the attacker can query the attachment metadata table via the REST API:

GET /api/now/table/sys_attachment
  ?sysparm_query=file_nameLIKEpdf
   ^ORfile_nameLIKEdocx
   ^ORfile_nameLIKExlsx
  &sysparm_limit=1000

The query returns metadata for attachments matching the file-name filter. The metadata includes sys_id, file_name, content_type, and table_name (which parent table the attachment belongs to). The attacker now has a directory of attachments to assess.

Step 3 — Pull interesting files. For each attachment of interest, the attacker fetches the content:

GET /api/now/attachment/<sys_id>/file

The attachment content streams back. The platform may apply the parent record's ACL to the request (depending on configuration), but in many 'public'-restricted instances the attachment endpoint serves content without re-evaluating the parent ACL — the original record-level protection is bypassed.

Step 4 — Exfiltrate. The attacker has the file content. The original record may have been protected by a strict ACL (HR data, change documentation, customer correspondence), but the attachment was the side-channel. The exfiltration may or may not appear in sys_audit depending on the platform's logging configuration for attachment access; the attacker frequently completes the operation without triggering an alert.

The defense is twofold: restrict who can interact with the attachment API at all (via this property), and audit the existing attachment surface for content that is more sensitive than the role-restriction allows.

How to fix it

The remediation is one property change plus a follow-on audit.

Step 1 — Set the property. Choose a role appropriate to your environment. Common choices:

Apply via System Properties:

glide.attachment.role = attachment_writer

(or your custom role name)

Step 2 — Audit role assignment. With the new role in place, only users who hold that role can interact with attachments. Audit which users need the role and grant it explicitly:

// Background Script — grant attachment_writer to specific users
// (run only after determining which users need the role)
var grant = new GlideRecord('sys_user_has_role');
grant.initialize();
grant.user = '<USER_SYSID>';
grant.role = '<ATTACHMENT_WRITER_ROLE_SYSID>';
grant.insert();

Step 3 — Audit existing attachments. The property change controls future attachment access; existing attachments uploaded under the unrestricted regime remain in sys_attachment and sys_attachment_doc. Audit the existing content for sensitive material:

// Background Script — sample existing attachments by table
var byTable = {};
var gr = new GlideRecord('sys_attachment');
gr.query();
while (gr.next()) {
    var t = gr.getValue('table_name') || '(none)';
    byTable[t] = (byTable[t] || 0) + 1;
}
var tables = Object.keys(byTable).sort();
for (var i = 0; i < tables.length; i++) {
    gs.print(tables[i] + ': ' + byTable[tables[i]]);
}

Review the distribution. Attachments on hr_case, sn_hr_core_case, or any custom HR table are PII candidates. Attachments on change_request may contain operational sensitivities. Audit these specifically.

Step 4 — Pair with file-type and MIME restrictions. The role restriction controls who can interact with attachments; complementary properties restrict what types of files can be uploaded:

Set both to defense-in-depth values. The role restriction is the primary control; the file-type controls are the secondary layer.

How to verify the fix

/*
 * Verify nowisor-attachment-role-restriction
 * Read-only, safe for production.
 * Confirms glide.attachment.role is set to a non-public role.
 */
(function verifyAttachmentRole() {
    var SENTINEL = '__NOT_REGISTERED__';
    var prop = 'glide.attachment.role';
    var value = gs.getProperty(prop, SENTINEL);

    if (value === SENTINEL) {
        gs.print('[FAIL] ' + prop + ' is NOT REGISTERED.');
        gs.print('       Set to a non-public role.');
    } else if (value === '' || value.toLowerCase() === 'public') {
        gs.print('[FAIL] ' + prop + ' = "' + value + '" (unrestricted).');
        gs.print('       Set to a non-public role (e.g., attachment_writer).');
    } else {
        gs.print('[PASS] ' + prop + ' = "' + value + '". Attachment access restricted.');
    }

    // Companion: file-type controls (informational)
    gs.print('');
    gs.print('Companion attachment controls:');
    gs.print('  glide.attachment.extensions = ' + gs.getProperty('glide.attachment.extensions', SENTINEL));
    gs.print('  glide.security.file.mime_type.validation = ' + gs.getProperty('glide.security.file.mime_type.validation', SENTINEL));
})();

Re-run the nowisor scan after applying the fix. The check should no longer produce a finding.

What to do next

The attachment surface is part of the broader data-access cluster:

For organizations with GDPR-significant attachment content, the nowisor advisor product is being built to correlate the attachment finding with the parent-record ACL audit — surfacing the specific tables where the attachment role restriction is the primary control protecting PII (because the parent-record ACLs are over-permissive). Audit your attachment surface →