Code search
Every script field on the instance, including the ones the platform's own search leaves out, and how the results page gets a token without putting it in a URL.
/code <text>, three characters minimum. Results open in a tab of their own. While you type, the
palette shows how many hits each table has, and each of those rows opens that table's list
filtered.
Which tables are searched
The instance's own Code Search configuration is read, not replaced: the search group and its tables, with each row's additional filter honoured. On a stock developer instance that is 31 tables.
That list is then unioned with a short set of our own, because the platform's configuration leaves out places where code genuinely lives:
sp_widget (server script, client script, link, CSS, template), sp_angular_provider,
sp_header_footer, sys_script_fix, sys_ws_operation, sys_script_email,
catalog_script_client, sc_cat_item_producer, sys_ui_context_menu.
Where both lists name a table, the platform wins: an admin editing that configuration made a deliberate choice. Our extras only contribute fields the platform did not list.
If the Code Search tables are not readable at all, because the plugin is not active, the fallback is the five obvious script tables plus those extras.
The field names in the extra set were each verified against a real instance rather than assumed. An unknown field's condition is silently dropped, so a query naming a field that does not exist returns the whole table. Searching for a nonsense value and getting every row back is the proof, and two candidate fields were rejected that way.
/code also shows the gap between what your instance's search group covers and what is worth
searching, and offers to close it. A table added to the group is then searched by ServiceNow's own
Code Search, for everyone.
How the results page gets a session
The results page runs on the extension's own origin. It cannot mint a ServiceNow CSRF token, and the token must never travel in a URL, where it would land in history, in the omnibox, and in screenshots.
So the page is opened with only the search term in its URL, and the token is handed over separately:
- The palette resolves this page's token and asks the worker to open the results page.
- The worker takes the instance from the sender's own origin, not from any field in the message, so a forged message cannot aim one instance's token at another. It checks that origin against the manifest, and stores the instance, the token and the term in session storage.
- The results page collects that hand-off exactly once, and it is removed as it is read. Past sixty seconds it is refused, with a message telling you to run the search again.
- The operation that collects it is not on the list a page may call, so only the extension's own page can take it.
Opening the results page cold is not a dead end: it can list the instances you have open plus the last one searched, and mint a token for the one you pick. If you are not signed in there, it says so and tells you what to do about it.
Why the results page uses GraphQL
One tab, every table at once. Over REST that is a count and a page per table, so forty tables would be eighty round trips. The GraphQL endpoint answers all of them in one request, with the row count beside the rows, measured at under two seconds on a developer instance.
The platform's failure mode here is unusual and worth knowing: a table GraphQL does not recognise is a schema error that nulls the whole response, not only that table's part. So a batch that comes back empty is halved and retried until the offending table is isolated and dropped, and the rest still answer.
Every request goes through the worker, which holds the host permission, rather than from the page.
If the extension is not present, /code falls back to opening the list of whichever table had the
most hits.
