HowTo: Detection of (malicious) script components

The expressions? Yes. GH2 expression language is a merger of GH1 expression language and C#. I added support for certain codes that are not part of C# (like the factorial operator, various constants, and integer exponents), certain functions that most geometric scripting languages would expect to have directly available (cos(), acos(), sinh(), etc.), and the resolution of undeclared variables.

If an expression uses something which looks like a variable but it isn’t defined inside the code, then I use Roslyn to replace that variable with a function invoke which ultimately goes looking for that value inside the GH document. So if you have a slider somewhere called "ValueA" and your expression looks like this:

min(x + ValueA, x²)

it gets converted into:

return Grasshopper.Maths.Min(x + __resolver["ValueA"], Grasshopper.Maths.Raise(x, 2));

But of course you’d never see those transformations as a user.

1 Like

I can only speak for my use cases, but I don’t yet ever write scripts within GH, and rarely do I download anything like that, I only tend to download to study and learn the OEM and F4R plugin commands. So for me if I ran a .gh file and it warned “FYI this file contains non-OEM or trusted plugin scripts”, I would likely close/delete it and move on to the next learning opportunity. Whether that warning be in Rhino or the forum interface, either would be useful to me and not ignored.

This is something I also have been thinking about lately, and just bought two external HDD’s to redundantly backup my important (client) data, and stopped adding any plugins before I implemented that. But even that I imagine could be worked around if the malware just lurked for a few weeks while it waited to detect external drives being mounted.

I once lost all my work docs to ransomeware, thankfully it was only msoffice and pdf docs and not CAD docs!!! But I am always aware of this horrible possibility from that. Also slightly more paranoid because just audio-read Daemon by Daniel Suarez, highly recommended haha.

I like to think that this is a less risky forum as it’s based on 3D CAD instead of general programming, but still have to be vigilant.

Ideally you’d have a versioning+backup system in place, so that you can always return your files to the state they were in last October 12th. Or so that you can have two parallel branches of your files so you can experiment with something without risking any important data.

Basically, set up a git (or equivalent) repo for your projects. Storing the data off-site would also be good, fires and power spikes and burglary tend to affect hardware in the same region of spacetime, by distributing your data elsewhere you mitigate that risk. Of course you may have good reasons for not storing sensitive data on someone else’s server.

We disagree on the meaning of ‘useful’ here. The warning which would pop up doesn’t mean “something bad will likely happen if you open this file”, it means “the chances of something bad happening when opening this file just went from 0.00001% to 0.00002%”.

Agreed, I don’t know how to quantify usefulness, but do know that I’m not interested in downloading anything with custom scripts.

I did read your mention of expressions in gh2 AFTER my previous comment, so that changes it a bit, but I could easily look at an expression and if it’s some math I’d click trust but if something beyond my understanding in the expression I’d click don’t trust.

Obviously there are so many facets that are unknown unknowns to me, but just sharing my perspective FWIW.

And your perspective is welcome, thank you for making that effort.

I believe Excel had (has?) this protection where it would warn before opening files which contained scripts. I wonder how many perfectly good files were not opened because of it vs. how many bad files were not opened vs. how many bad files were opened anyway because of muscle-memory/misunderstandings.

1 Like

I’ve personally opened, opened with disabled macros (IIRC), and not opened excel files due to this, depending upon the origin and importance. It’s been a while since I mostly only use my own spreadsheets. Nice to have the choice though if it’s not too difficult to implement.

Downloaded .gh files are “blocked” in windows.
We can still use them no problem while them being “blocked”.

Maybe add a: “if file blocked” & “if contains c#/VB/python” then show a warning.
With options like “open with solver disabled” or “open with script components disabled”.

Production files will be set unblocked.

I can imagine how frustrating can be reading some thread that will result in new days of work, for a developer. This is just a fast opinion :upside_down_face:

Do you know an api to see if a file is blocked?

or… ensuring that Rhino/Gh runs fine on VM… :wink:

I’m not sure of how far that can protect anyone, but at least the forum-download-on-the-fly-stuff should be opened only sandboxed… no?

// Rolf

I do not.

But this was useful:

Seems like through powershell is possible to read that “ZoneId” that specify the source of the file.

This works fine for me. Manually referencing a system .dll is needed. Instructions inside. (5.3 KB)

also relevant:

1 Like

How do I tell Windows “Hey, from now on all changes I make to the file system and registry need to be undone when the Rhino application shuts down.”?

I don’t even think that’s possible during runtime. And once an app is sandboxed, any actual changes you make and save yourself will be undone as well.

Forgive me for stating the obvious.
We are talking two issues here. One is sandboxing, highly complicated. Two is, “Warning: Contains scripts, Cancel, Proceed with script locked/disabled, Caution to the wind!”. The second sounds much simpler to implement, but then again I’d have to follow a tut to write “hello world” in python :smiley:

EDIT: Ps. GH, empowered by the rest of its relatives, is my favorite collection of code of all time, so no worries either way on my end, keep up the great work.

public static bool CheckZoneIdentifier(string filepath)
            return NativeFs.CheckExists(filepath + ZoneFile);

        public static bool RemoveZoneIdentifier(string filepath)
            return NativeFs.Delete(filepath + ZoneFile);

private const string ZoneFile = ":Zone.Identifier";

using System;
using System.Runtime.InteropServices;
using Pancake.Dataset;
using Microsoft.Win32.SafeHandles;

namespace Pancake.Utility
    class NativeFs
        #region Dll Import
        [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool DeleteFile(string name);

        [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern IntPtr CreateFile(
            [In] string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            [In] IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            [In] IntPtr hTemplateFile

        private const uint GenericRead = 0x80000000;

        internal static bool CheckExists(string filepath)
            if (Config.IsMac)
                throw new PlatformNotSupportedException();

            using (var fHandle = new SafeFileHandle(
                CreateFile(filepath, GenericRead, 2, IntPtr.Zero, 3, 0, IntPtr.Zero),
                return !fHandle.IsInvalid;

        internal static bool Delete(string filepath)
            if (Config.IsMac)
                throw new PlatformNotSupportedException();

            return DeleteFile(filepath);

1 Like

Frequent backup is a fallback, but no protection mechanism. But of course, automated backup systems are part of a network and as such can also be infected. It further requires that you notice an attack. Most effective attacks are silent and not all are destructive.
You can also harm a company by collecting confidential data of any kind.

Since I always worked in R&D departments, I can tell that my company gets hundreds of serious attacks a year. Of course you cannot get protected against any of them, especially if its a professional attack, still all employees are getting frequently educated about how to prevent as much as possible by always by being defensive. E.g. Any person without a valid keycard could be social engineer, although its unlikely.

Being aware of potential attacks, is by no means a obstacle to work. Often defensive behaviour is just a little different way of behaving. In that keycard example, if somebody has no visible keycard you don’t let this person through a door. But you can inform someone in that area to pick that person up. Usually that person has to wait for 5 more minutes, but there is usually no problem with that.

It is the same by running a script like this. Just detecting a script and looking into it doesn’t require you to be an senior software developer. Also you only need to do that on data of unknown source. So if you get files from coworkers or common forum members there is probably no need to check.
In the end its like 10 seconds of extra work and you get a much higher protection compared to nothing. 99,99999% of all key card protected doors are never been reached by an true attacker, but still a single attack can cause strong damage.
I have just recently read that security experts estimated german companies losing 100 billion € a year by cyberattacks ( I personally don’t trust that estimation, but I also believe its a high number).

I think a definition-signing mechanism would be a useful thing; at least in that way you can identify the source of malicious code. People would also be much less likely to distribute malicious code if they knew they would be caught at it.


In theory I totally agree and its definitly not a bad idea! But in practise you cannot do much about it from a world wide perspective. You can bypass that and stay anonymous as well.
Also whats malware or not is also quite gray. Just think of all the data collection going on, which is not always a bad thing (error reporting etc).

I really think if a solution like I proposed gets a bit polished, that may already be sufficent. I think if you fly over all the code involved, even as a non programmer, it should be quite easy to filter whats related to geometry and whats doing maybe doing stupid things. And I mean the idea is just that you have a little bit of control allowing others not to hide code in a definitions in first place. I mean shouldn’t be a must, but for some people it gives an extra bit of security. And as I said, being potentially defensive is not wrong if you work in certain areas. If you download a definition from untrusted source why not having a quick look what it does before you run it? Nobody can be that lazy!

1 Like

Signing rhino content (with an id linked to the Rhino account, not a string) would not only be another layer of security, but would be a very interesting label for advanced searches, for intellectual property issues, for contacting the author and for user records. But well the case is that I don’t get the reason why some of you see as no valid solutions some layers of security when all you can do is to give partial solutions. At least some of you give me that feeling. If a hacker can’t get from Rhino content to someone’s pc, it can be done from a million other doors related with Rhino. Even you can have a script that connects to a server database, and you see the code it seems legitimate to download content because it is their purpose, then you are vulnerable again. So the point is, we all know that there are no perfect solutions, why not put in all possible layers of security? (within certain benefit/cost criteria).

The principle of least action also applies to user action. Some people short-circuit their minds reading code. It has happened to all of us at some point to short circuit our minds and press the button we didn’t want to. When you take a look at a code, it is very possible that your eye skips a critical line. If you see that the code are 4000 lines, you will prefer to take the risk unless you have reason to be suspicious. It is not a matter of being lazy or not, but of accepting that we all tend to apply the minimum action, the brain always tends to be economical, that’s why we prejudge and almost always fail or that’s why the brain invents anything to justify finishing earlier or that’s why the brain connects to the most usual muscle pattern instead of passing it a deductive filter. Not falling into this fundamental principle is something that machines are very good at. That is why this problem must be transferred as much as possible to the software (if we want to maximize security) and why as many layers of security as possible must be added, including the manual revision of the code or any other potentially hackable partial solution. Or perhaps a selection of partial solutions with a well studied pattern. But what is the problem with partial solutions to point out that it’s not good because it can be hacked? What makes black hackers to be hackers is precisely to break what others say can’t be broken. The user is made aware that it is not safe to download content from unknown sources or to put a password in a cluster and the responsibility of the developer is covered adding as much resistance as possible to minimize the risk. Software must to be designed for lazy, clumsy and stupid people, because it is more realistic to write better code than to expect better users.

I don’t know if you mean me by that. But I’m very pragmatic. I don’t like the idea to develop hours and hours, then offer it for free, when I exactly know someone misuses this anyway. I’m a fan of semi-automatisation. This is not only for true for Grasshopper but for many other things in life. There is so much overengineered going on for its purpose. Remember we are talking about zero protection as it is now, to find possible attacking vectors.

A simple script to detect script components helps me with that. Thats why I wanted to share that. I use that for any definition I have downloaded. And if it finds more than its obvious, I double check manually.
If we talk about signing definitions we add much more complexity to it with little benefit. I’m not against it. Nor I’m against scanning for File Operations and similar, but its just lots of work for minimal security gain.

Usually scripts are short in line-count. If you would find a large script you don’t understand, I would simply dismiss that, or trying to only pick the parts relevant for my understanding. Furthermore, missing a line of code is usually no problem, since malware usually needs more than that.
So its always about not overcomplicating things. And one more thing, it is true that humans are missing a lot , but tricking an automatic protection is also a problem, when users trust in their protection software too much. So having a sense for what can goes wrong is better than blindly trusting software.