Security concerns about SoftOne WebServices: clientID validation & unintended Advanced JS exposure

73 views
Skip to first unread message

dobromi...@gmail.com

unread,
Jan 22, 2026, 12:40:18 PM (13 days ago) Jan 22
to Softone Developers Network

Hello everyone,

I’d like to raise a few questions/concerns regarding the security behavior of SoftOne Web Services, specifically around calling Advanced JavaScript methods via:

https://....oncloud.gr/s1services/JS//

1) clientID validation behavior (and session lifetime)

In our Advanced JavaScript modules that are intended to be exposed as web services, we validate the request like this at the beginning of every method:

function checkClientId(obj) { return obj && obj.clientID && obj.clientID.length > 10; }

And then:

if (!checkClientId(obj)) return { success: false, error: "Authentication failed due to invalid credentials." };

This works fine, but I’d like to better understand how SoftOne validates clientID internally:

  • Is clientID fully validated server-side (i.e. the call is rejected before JavaScript execution), or is it simply “checked for presence” and then the session is validated only when X.* functions are called?

  • Is there an official way to validate clientID (or session) without calling a real method?

  • How is session invalidation expected to work?

A related issue we noticed:

  • A clientID remains valid even after the user is deactivated, or even after the user’s password has been changed.

    • Is this expected behavior?

    • Is there a recommended way to force existing clientID sessions to become invalid when a user is deactivated or their password changes?

2) Calling JS functions that are NOT intended for Web Services

We also have other Advanced JavaScript modules that are not intended to be callable via Web Services at all (they are designed to run inside a form, where context variables exist, e.g. FINDOC, etc.).

Example URL format:

https://....oncloud.gr/s1services/JS/CustomClients.CUSTOM_LINSUPDOC/ON_LINLINES_PRICE

When calling this URL directly via HTTP, the response is an error like “FINDOC is undefined”, which suggests that the JavaScript function is being executed even though:

  • no clientID was provided

  • and the function is not meant to be exposed externally

My expectation is that such functions should not execute at all when invoked by direct HTTP request (especially without authentication).

Questions:

  • Is it expected that any Advanced JS function can be triggered via /s1services/JS/<Module>/<Function> even if it was never designed as a webservice?

  • Is there a recommended way to restrict which JS methods are callable externally (allowlist / blocklist)?

  • How do you secure internal JS modules to ensure they can only execute in the intended context (inside forms) and not via external HTTP calls?

Any clarification or best-practice guidance would be greatly appreciated, especially around:

  • correct clientID validation patterns

  • session invalidation behavior

  • restricting/unexposing internal JavaScript functions from HTTP access

Thanks in advance!
Dobromir

Νίκος Μάλιακκας

unread,
Jan 22, 2026, 5:03:07 PM (12 days ago) Jan 22
to Softone Developers Network

There is not currently a way to lock the use of Advanced JavaScript modules for use only inside modules. It would be a security improvement if we had that option.

Workaround: Use complex package and module names for internal usage so it would be difficult for someone to guess the package and module names.

If you definitely want to secure some function in the internal modules that is doing serious work outside the module it is supposed to run in, you can seal it by checking if the first argument has the property "clientID" or "service" and stop the execution. 

This seems somewhat unsecure at first, but it is a good way if you design APIs for importing/exporting data and you don't want to give API users access via the web services login process. You can then make your own validation process inside the functions and be sure that you didn't expose all the web services to the other API users (if they used the login process).

The way you handle the process seems to be the official one by Softone: If the call has a clientID property, it will be validated first and if OK, the function will be executed. Your response to seal the function is to check if the first argument has a clientID property and that it is big enough to be a valid one.

As of the session invalidation, there is an expiration time in the web services accounts settings. If you don't provide one, the clientID  will probably last until the end of the fiscal period.

Dobromir Mateev

unread,
Jan 22, 2026, 5:47:09 PM (12 days ago) Jan 22
to so...@googlegroups.com

Thanks for the workaround suggestion to “seal” internal functions by detecting clientID / service in the first argument and stopping execution.


However, we have a practical case where the function is an event handler (e.g. ON_LINLINES_PRICE) and it doesn’t receive any arguments at all when executed inside SoftOne (it relies on the form context like FINDOC, etc.).


Example:


.../s1services/JS/CustomClients.CUSTOM_LINSUPDOC/ON_LINLINES_PRICE


When called directly via HTTP, it still “starts executing” and fails only later because context variables are missing.


Do you have any code examples / best practices for protecting such functions that don’t receive an obj argument?


For example, is there any reliable way to detect:

  • that the function is executed via /s1services/JS/... HTTP request

  • vs executed inside the SoftOne UI runtime as a real event handler?


Any pattern or snippet would be very helpful.


I agree that using complex package/module/function names can reduce guessing attempts (security-by-obscurity), but the problem is that some of our clients (e.g. financial institutions) run regular security audits and penetration tests.


Even if the names are hard to guess, the fact that internal modules are callable externally at all is something that will likely fail a more comprehensive assessment.


So from a governance / compliance perspective, it would be a big improvement if SoftOne could support an option to explicitly mark JS modules or methods as:

  • “callable only inside SoftOne”

  • “callable only via Web Services”

  • or allowlist/blocklist at module/function level


For “read-only” needs (exposing data from the database), we already use an external .NET Web API with OAuth, and we query the database directly. This is fast, reliable, and easy to secure.


But when we need to create documents in SoftOne, we currently do:

  • front-facing .NET Web API (OAuth secured)

  • which then calls SoftOne via /s1services/JS/...

  • which internally creates documents using Advanced JS


This works, but it is:

  • relatively slow

  • more complex than desired

  • and the exposure of internal JS modules remains a security concern regardless


So the unresolved issue remains: any internal module (even event handlers) can still be triggered externally, and that will likely be raised by any serious penetration test.


Thanks again for the guidance.

If anyone has working examples for securing “argument-less” event handler functions like ON_LINLINES_PRICE, I’d really appreciate it.


Best regards,

Dobromir




--
Softone Developers Network group.
To post to this group, send email to so...@googlegroups.com
---
Λάβατε αυτό το μήνυμα επειδή έχετε εγγραφεί σε ένα θέμα στην ομάδα "Softone Developers Network" στις Ομάδες Google.
Για να απεγγραφείτε απ' αυτό το θέμα, επισκεφτείτε τη διεύθυνση https://groups.google.com/d/topic/soft1/pNZ7y_wizkA/unsubscribe.
Για να απεγγραφείτε απ' αυτή την ομάδα και όλα τα θέματά της, στείλτε ένα μήνυμα ηλεκτρονικού ταχυδρομείου στη διεύθυνση soft1+un...@googlegroups.com.
Για να δείτε αυτή τη συζήτηση, επισκεφτείτε το https://groups.google.com/d/msgid/soft1/c8f59fd9-9456-4edf-acbf-ee3446e0687dn%40googlegroups.com.

Νίκος Μάλιακκας

unread,
Jan 23, 2026, 5:25:48 AM (12 days ago) Jan 23
to Softone Developers Network
I tried the following
Στιγμιότυπο οθόνης 2026-01-23 115638.pngΣτιγμιότυπο οθόνης 2026-01-23 115527.png

The arguments variable inside a function is referring to an array of the parameters/arguments passed inside the function.
If the function is not supposed to have parameters,  then typeof arguments[0] should be undefined.
Check it with the ON_EventName functions to see what is passed when used inside and when called outside from ws.

Another workaround to secure the AdvJs used inside softone is to separate declarations and events into different modules  .
So inside a form we would have:
lib.include("MyComplexPackageName.MyComplexModuleNameDeclarations");
lib.include("MyComplexPackageName.MyComplexModuleNameEventHandlers");

So if anyone tries to just call a ws function on the EventHandlers the function will run but probably fail because it will miss the declarations of the variables used inside it.
Nevertheless, I support you in your proposal to be able to categorize the Module's usability. Function level I suppose is very difficult  -they can be created on the fly while the code runs, so how can you prevent them before they exist?
Also, restricted access to some Packages/Modules on a web account would be appreciated.

vlado...@gmail.com

unread,
Jan 23, 2026, 7:23:31 AM (12 days ago) Jan 23
to Softone Developers Network

X.FORM can be used as a mechanism to protect Advanced JavaScript functions from being invoked externally.

For example, you can check whether (X.FORM != "").

The X.FORM variable is always populated when Advanced JavaScript (AJS) is executed by SoftOne, even if the code is defined at the module level.

When a form context exists (i.e. X.FORM has a value), it indicates that the execution was triggered internally by SoftOne (for example, from within a form).

In this case, the execution of ON_FINDOC_SERIES() can be wrapped with a condition such as:

if (X.FORM != "") { ... }

This ensures that the function is executed only when it is called within a valid form context.



BR,

dobromi...@gmail.com

unread,
Jan 23, 2026, 7:47:00 AM (12 days ago) Jan 23
to Softone Developers Network
Thank you for the suggestions Nikos and Vlado ! 

Νίκος Μάλιακκας

unread,
Jan 24, 2026, 6:29:56 AM (11 days ago) Jan 24
to Softone Developers Network
Vlado's suggestion is much better since X.FORM is "module aware" and in web services there is no module in X.
Combining the suggestions, a good approach would be:

function isNotCalledFromInsideSoftone(){
    return X.FORM == "" || (typeof arguments[0] !== "undefined" && arguments[0].hasOwnProperty("clientID"));
}

//usage
function ON_FINDOC_SERIES(){
    if (isNotCalledFromInsideSoftone(arguments)) return;
    //uncomment the next line to check
    //X.WARNING("This function was called from inside Softone.");
    // rest of your code
}

I think this seals both functions that are supposed to run only in a form and also functions that we don't want to expose to the web services.
I have tested it inside a form. Can you check if it works both ways and share the result?
Reply all
Reply to author
Forward
0 new messages