Protection
What the platform protects the person and their data from, how exactly, and what stays the person's responsibility.
Introduction
The document describes the threats the platform takes into account and the measures of protection. The document is neither a security certificate nor a legal opinion.
1 The border of the model
The platform works on the person's computer, one person per instance. The person may be anyone, not necessarily a programmer, and uses not only their own modules but others' too. A module counts as trusted code: the person added it themselves and starts it themselves. A module works with the rights of the same WSL user.
It follows that:
- O.G.A.S. is not a sandbox for modules;
- the field
permissions_infoin the manifest is information from the author, not a limit; - a module can read and change any files the person can reach and go to the network. The Windows disks are mounted in WSL as
/mnt/<disk>, so the Windows documents are within a module's reach too; - a malicious or substituted module can get access to all these data;
- a module from another person is as dangerous as any downloaded program.
A separate OS process protects the other parts from a failure of a module but takes no rights away from it.
2 Protected resources
- the files of modules;
- manifests and recorded versions;
- the documents of graphs and pulpits;
- input data;
- the result files of runs;
- journals and diagnostic data;
- the settings of the platform and of the person;
- the outside services and files the person can reach;
- one-time launch tokens of functions (inner connection marks, not secrets of the person);
- the session token of the window (the inner mark of the connection of the window to the function
ui, valid until the function stops); - the state of long modules;
- the computer key and the letter key of the profile (section 8).
Keys to services, tokens and other secrets of the person and their modules are of value to the person and the module, but the platform does not dispose of them: it does not keep, give out or manage them. The only keys the platform holds itself are the computer key and the letter key of the profile: by them it signs parcels and opens letters (section 8); it does not keep the main key of the profile. The launch token of a function is kept only in memory and is not passed to a module. Where and how to keep their secrets, the person or the author of a module decides, and answers for it themselves.
3 Threats and measures
3.1 A malicious module (T-01)
Threat: a module reads files, sends data to the network, starts programs or changes the system.
Measure: before the first making or installing of a module the workshop warns once per session: a module works with the rights of the user, there is no sandbox. There is no actual limit.
Remaining risk: high. The platform does not suit untrusted modules. A person without training cannot judge someone else's module by its code. So before adding the platform shows what exactly comes: the name, the size, what the module will download, the print, and whether such a module is already there (process.inspect, Building, installing and maintenance, 5.6). The platform does not show the rights of a module: there is no sandbox, and such rights would be a deception.
3.2 Another program poses as a function (T-02)
Threat: another program on the same computer tries to talk to the kernel as a function of the platform.
Measure: a Unix socket with mode 0600 on the Linux file system (not on a Windows disk), the check SO_PEERCRED — the uid of the instance and the pid of the started function, a one-time launch token in OGAS_LAUNCH_TOKEN, a required introduction (handshake) as the first message. A module does not get the token and does not connect to the socket; when a module is started, the environment is cleaned. This does not protect against trusted code of the same person.
Remaining risk: a program started by the same person can use everything that person can reach. The platform does not promise protection from the owner of the machine.
3.3 A path beyond its own folder (T-03)
Threat: a document names a path beyond the allowed folder.
Measure: relative paths are counted from the folder of the owner of the document; .. and absolute paths are refused; the borders of the folder are checked; arbitrary paths in methods are forbidden. A path in the data folder is in addition resolved through links: the deepest existing part of the path must stay inside the data folder, otherwise path_outside_root. A consequence: a symbolic link inside the data folder leading outside does not work — runs on another disk are made through --data-dir or mounting, not by a link. The platform does not resolve the installation folder through links: the person assembled it themselves, and a module put in by a link is an ordinary working device. There is one exception in the data folder — a program a function asks to start from there (command_base: data of core.process.spawn): the folders on its path are checked through links, and the program itself may be a link outside and must lead to a file. So the interpreter of the environment of a process is started — a link to the Python the environment was made from — when the data folder lies outside the installation folder; inside it the path is counted from the installation folder, where links are not resolved anyway. The environment does not travel with a program: a pack does not carry it, and .venv is installed by the function of modules on its own side.
Remaining risk: between the check and the writing there is a gap: a link can be substituted exactly at that moment. Writing goes by replacing a file, not by writing through a link, so a substitution leads to a refusal or to a file inside the folder, but there is no strict proof. By the model of trust a module works with the person's rights anyway (T-01).
3.4 A damaged protocol (T-04)
Threat: wrong JSON, a line too long, debugging text mixed with the protocol in stdout, a hung channel.
Measure: UTF-8, one message per line, a line length limit of 4 MiB, bounded queues, a separate stream stderr, a limit on waiting time, the answer Parse error and a controlled closing of the channel.
Remaining risk: that lines are put together from parts correctly and that an overflowing queue is refused is confirmed only by end-to-end checks.
3.5 A secret got into the journal (T-05)
Threat: a module writes a secret to stdout or stderr, or a secret ends up in a result and gets into the journal.
Measure: the platform adds no secrets of its own; a module keeps its own in the file .env of its folder, which does not go when the module is handed over (Modules, section 9); the size of the data of a packet in JSON is limited, big data go as result files. Journals, documents and the socket of the instance are made with mode 0600: other users of the machine do not read them.
Remaining risk: high. The platform cannot reliably recognise secrets in arbitrary output of a trusted module. Refusing settings whose name holds secret, password, token, api_key, apikey or private_key catches only obvious names: a key with another name, for example openai_key, will be written into the settings file as an ordinary value.
3.6 An outside action was done twice (T-06)
Threat: after a failure a step sends a letter, a request or a record again.
Measure: a constant operation_id of the step, the declaration of the module idempotent / non_idempotent / unknown, the person's decision if the outcome of the step is unknown.
Remaining risk: a module may wrongly declare itself safe for a retry; the platform cannot check the meaning of its work.
3.7 Installing dependencies (T-07)
Threat: a malicious or substituted Python package runs its code while the environment is installed.
Measure: installing only by an explicit command, as a separate OS process the platform watches, from the common requirements.txt of the process, gathered from the requirements of its modules; the source and versions are shown if the installer reports them.
Remaining risk: installing packages is running someone else's code with the person's rights. There is no check of signatures or reputation. The person's proxy variables, if set, the functions and modules get as they are, and a proxy address with a name and password in it is seen by a module too: a module is trusted code (3.1), and installing without them in a network with a way out only through a proxy is impossible.
3.8 Overloading the platform with work (T-08)
Threat: an endless loop, a huge packet, an overflowing stdout or stderr, many OS processes, endless restarts.
Measure: limits on the length of a line, queues, the size of a result file, the number of rounds of a loop, time, the number of OS processes and the number of restarts in a row.
A module has no limit of memory and processor load. The reasons: a module is trusted code of the person themselves or taken by them from another; prlimit and cgroups v2 in WSL behave in a particular way and need checking on the target machine; with one run at a time the culprit is seen at once.
Remaining risk: high and accepted. A module with a memory leak will take the whole WSL virtual machine (half of the RAM by default) and stop the whole platform; only the time limit of the module timeout_ms and stopping the run help.
3.9 A document damaged while written (T-09)
Threat: a failure during writing leaves half a JSON or an inconsistent set of files of a process.
Measure: a temporary file, fsync of the file, the former file into .bak through rename, fsync of the folder, a generation number and a check that generation N is complete, otherwise a rollback to N−1.
Remaining risk: how fsync, rename and the WSL file system behave needs checking on the target machine.
3.10 The window of the platform and its port (T-10)
Threat: the function ui waits for a connection over TCP on 127.0.0.1. A Windows or WSL program could connect instead of the window and in its name start runs, change settings, install modules, stop the instance. A window page with content from the network would widen the possibilities of an attack.
Measure:
- only
127.0.0.1; a free port at each start (ui.window.port= 0); - the session token — 256 bits from
/dev/urandom, new at each start of the function; the window gets it on the command line; - the first message of a connection is
ui.window.hellowith the token; the tokens are compared in constant time, so that the token cannot be guessed by the speed of the answer. On a mismatch — the errorui_window_unauthorizedand closing. There is one window: a new one pushes out the former; function.handshakeand all kernel methods exceptcore.status,core.health,core.space,core.event.subscribeandcore.shutdownare closed to the window; the rest —method_not_allowed. Documents, starting modules and publishing events stay with the functions;- the page is built into the executable file of the window; the rule
default-src 'self'forbids loading anything from outside, there are no outside scripts and no pages from the network in the window; - the WebView2 debugging tools (
ui.window.devtools_port) are off by default and marked as a development mode.
Remaining risk: the token is seen on the command line of the window process by any program of the same Windows user, and such a program can connect with this token. The exchange over 127.0.0.1 is not encrypted. With the debugging port on, any local program controls the window page. The platform does not promise protection from code of the same person — as in T-02.
3.11 A request of a repeated start (T-11)
Threat: a start with a verb that needs the workshop leaves the working instance a note run/launch.json in the data folder and wakes it with a signal (The make-up of the platform, 3.6.3). A program of the same user could leave such a note itself and make the instance make a call the person did not ask for.
Measure:
- by a note the instance carries out only a verb its register describes as needing the workshop, and only with the arguments the register gives this verb; the verbs of a run and of installing are not carried out by a note;
- a note is read once and deleted; an unreadable one, one of another format, and one that lay longer than half a minute is not carried out;
- the note is open only to the user, like the rest of the data folder;
- the delivery has one such verb: it shows the face of a program, and the program is switched on, as when started by its shortcut.
Remaining risk: a program of the same user can open the face of any program of the person and so switch it on — it can do the same by starting the shortcut. The platform does not protect against programs of the same user (section 1).
3.12 A picture of the pulpit (T-12)
Threat: a picture of the pulpit comes from others' hands — with a process handed over or from a downloaded file. A file under the name of a picture may turn out not to be a picture; an SVG may carry a script and links outside; the file name or the path of a transfer may point beyond the folder of the pulpit; a link in the folder may, on a transfer, pull any file of the machine into the pack.
Measure:
- a picture is taken and given only by the function of the pulpit (File formats, 7.2): the name is one file name with an ending from a closed list, without folders; the file must begin the way a file of its kind does and be no larger than the setting
canvas.image_max_bytes; - the window shows a picture only as an image — by an address with the data inside, without going to the network: scripts in SVG are not run, outside links are not loaded; the content policy of the page does not allow anything else (The workshop, section 3);
- the identifier of a process and the paths of a transfer that came in a call are checked: one folder name and a path inside the data folder;
- links in the folder of the pulpit are not read and not carried, a half-written file is not seen;
- an own look of an element is data: the document
ogas.look/1with a closed list of fields, and pictures checked like any picture of the pulpit; there is no code, no scripts and no links beyond its folder in it, and the folder of a look is taken only whole.
Remaining risk: the parsing of the image itself is done by WebView2; the platform does not close a vulnerability of its PNG, JPEG, GIF or WebP parser.
3.13 A file of a process (T-13)
Threat: a file the person gives a process — a picture, sound, video, any file (File formats, section 16) — may turn out not to be what it is called; the name in a call or the field of a reference may point beyond the process folder; a file may be huge or abandoned halfway.
Measure:
- a file is taken and given only by the function of the graph (
process.file.put,process.file.read): the name is one file name, not hidden and without folders; only a file fromfiles/of the process or from the results of a named run is read, the path is inside this folder, a link of the file system is not read; - a file is no larger than the setting
graph.file_max_bytes; parts go in order, a missed or repeated one is refused, what is half-written is cleared after a day; a file is given to a run only while it is going; - the window shows a picture, sound and video only by a
blob:address it makes itself from the content read, and no larger than 64 MiB; the policy of the page lets addresses with the data inside andblob:for pictures, onlyblob:for sound and video, and the network is not touched; - a text file the window shows as words: it reads its beginning, no more than 256 KiB, and puts it out as text, not as markup;
- a file the person opens with a Windows program or shows in its folder the window program takes with the same
process.file.readand puts a copy into its folder inside the Windows temporary folder: the name is a simple file name, without folders, without Windows device names; the copy is no larger than 512 MiB. Only a kind that is looked at, listened to or read is opened — a picture, sound, video, PDF, text, document — by the ending of the name; a program, a script, a shortcut, a page and everything unknown are never opened — the check is made by the window program itself, not by the page (ui_window_open_refused, Error codes); such a file can only be shown in Explorer, and what to do with it, the person decides.
Remaining risk: the parsing of a picture, sound and video is done by WebView2, as for a picture of the pulpit; a module gets a file as a result file and parses it itself (Modules, section 6). An opened file is parsed by the Windows program that opened it, with its own errors: a document with a flaw in it will act on that program; the ending of the name, not the content, decides which program opens it.
3.14 Downloaded from a source (T-14)
Threat: a source — the O.G.A.S. showcase, Hugging Face, Civitai or a site the person named themselves — or someone on the way to it gives the wrong thing: a file with a name leading beyond the folder, a file larger than promised or endless, substituted content, a neural network in a format that runs code when read (.bin, .pt, .pth, .ckpt, .pkl — saved through pickle), a program or module that does anything with the person's rights. A search request leaves the computer and tells the source what the person is looking for.
Measure:
- the function of sources goes to the network only at the person's command: a search — at a button, a download — after the person has seen the files, their size and licence; it searches and downloads nothing by itself, and the window says that the request goes to the site of the source;
- only
https, and redirects only tohttps; a showcase in a file on this computer (file:) can name files only on this same computer; the platform knows no keys and no signing in to the site of a source: a network for which the source demands signing in or agreeing to terms is not downloaded, and the person sees why; - the name of each file that came from the network is checked: a relative path of ordinary names, without
.., without hidden ones and without device names; it is written only inside the folder of its downloaddownloads/<download>/, first into a temporary file beside, and takes its place by renaming when it is downloaded and checked; - the size is known in advance and compared: a download larger than the setting
sources.max_gibor than the free room does not begin; a file that grew beyond what the source declared is cut off; - the SHA-256 checksum is compared when the source names it — at the O.G.A.S. showcase it is required for each file, at Hugging Face large files have it, at Civitai the files of a model; when it does not match, the file is deleted and the download refuses (
source_hash_mismatch); - files that run code when read are marked in the list and are not chosen by themselves; if what is found has
.safetensors, those are chosen; - the picture of a found thing for a tile the function of sources takes only from the address the source named for this thing in the last search, not from an address the window named; no larger than 2 MiB; it takes it only if the first bytes are PNG, JPEG, WebP or GIF; it gives it to the window as data, and the window shows it as an image without going to the network, like a picture of the pulpit (3.12);
- a downloaded network takes its place in the folder of networks through its owner — the function of modules — under the name the person gave, and does not replace an existing one; a downloaded program and module lie in
downloads/and are taken in like things brought in a folder:process.inspectandmodule.inspectshow what will come and ask about trust (3.1); - only the showcase on ogas.space counts as checked — the address begins with
https://ogas.space/— and only if its signature by the site key holds (8.5); if the signature does not hold or is missing, the refusal issource_signature_bad, and the library shows nothing of such a showcase; any other showcase, the O.G.A.S. showcase moved by the setting to another address or into a file too, is marked in the library «nobody checked it», and a program and module from it the platform takes in only after a question of trust with the address of the showcase — every time, even if in this session the person has already said they trust modules; a program asks the same, because it brings modules; a piece of interface is data, not code: it is taken in without the question of trust, but only if its containers and elements pass the rules of the pulpit (canvas.piece.import).
Remaining risk: the showcase of ogas.space is signed by the site key, and its files are pinned by checksums inside the signed showcase: taking the server substitutes neither the showcase nor the files. A leak of the site key from the computer of the author of the site would — until a version of the platform with a new key. Other showcases, Hugging Face and Civitai are not signed: the authenticity of their files is checked only by a checksum named by the same source — a substituted source will substitute it too. A module and a program from a source are someone else's code with the person's rights (3.1). A network in the safetensors format runs no code, but a module that reads it may read it unsafely. The platform shows the licence of what is downloaded and does not check it: keeping it is the person's business.
3.15 Parcels and the site (T-15)
Threat: someone else passes for the person's profile; a seized server of ogas.space slips the platform a false showcase, board of requests, reviews, states of sendings or letters; a flood of parcels swamps the site; a parcel smuggles an executable file or leads a path out of its folder on the computer of the author of the site; parcels of one person are linked to each other through the site.
Measure:
- every parcel is signed by the computer key the main key of the profile vouched for and named in the card; without the main key one cannot sign for the profile, and the platform does not keep the main key; «Revoke all computers but this one» leaves one computer on the site, and a lost one, even one that never sent anything, signs no more (8.1);
- everything the platform reads from ogas.space is taken only if its signature by the site key holds; the name of the file is part of the signature, so one signed file cannot be passed off as another (8.5);
- letters are sealed by the letter key of their reader: the server, the author of the site and any reader of the site see only sealed bytes;
- a parcel leaves only at the person's command, after they saw what leaves; before sending, the platform does a counting task — a flood of parcels costs much, and there is no registration;
- into an offered thing the platform puts no environments, cache,
.envsecrets, runs, node memory or executable files; a module not in Python goes as sources with a lock file of its dependencies; the paths of a thing are relative, of plain names, without..and hidden ones; - the site shows no keys of profiles, and links an incognito parcel neither to its profile nor to other parcels (8.6).
Remaining risk: the author of the site sees whose profile stands behind each parcel, incognito ones too. A stolen computer signs for the profile until the main key revokes all computers but one's own; it keeps the letter key and can read letters that came before a new profile. Whoever lost both the key file and the recovery code loses the profile: nobody can restore it. A signature does not make a thing safe: the author of the site reads the code but may miss what is hidden, and the dependencies are not in the parcel — the environment installs them (3.7).
4 Required measures of implementation
- do not keep secrets of the platform's own in the source code: the platform owns none;
- do not pass the launch token of a function to a module;
- do not accept a command whose sender or owner is named wrongly;
- do not pass the variables
OGAS_LAUNCH_TOKENandOGAS_SOCKETto a module; - check the version of the contract before the function begins to work;
- check the size of input data before allocating much memory for it;
- limit
stdoutandstderrand do not let the reading threads hang on each other; - do not write protocol data to the
stderrof a function without a mark; - do not consider the output of a module safe;
- do not write whole large data of packets and values of settings with secret names into the journal;
- save documents whole;
- warn about the model of trust before making, installing and adding a module;
- forget the launch token after the function has ended;
- do not switch on taking connections from outside by default: the port of the window is only
127.0.0.1and only with the session token; - do not give the window kernel methods outside the closed list;
- do not keep the main key of the profile: after the profile is made or a computer joined, it is forgotten;
- take no file from ogas.space whose signature by the site key does not hold.
5 The model of trust
5.1 One person per instance
There is no journal of the person's actions. An instance serves one person, there are no roles, and what happened is seen in the journal of events, the checkpoints and core.jsonl. A separate journal «who did what» is needed where there are several people — together with roles and remote access.
There is no sign-in by password. There are no remote calls. A function proves itself to the kernel with the launch token and the entry in the register. The window proves itself to the function ui with the session token (T-10); this is a connection mark, not a sign-in of the person.
The kernel admits a function to work when the following match:
- a known
function_id; - the launch token;
- the version of the contract;
- the list of commands allowed to it;
- the
process_handlebelongs to this function.
A module cannot call writing a document, stopping the instance or other kernel methods.
5.2 There is no network access
Reaching the platform over the network is impossible. An open entry would inevitably be found, and protecting it reliably is hard.
6 Personal data
The platform sends out only parcels — at the person's command and after showing what leaves (section 8). By itself it only reads signed files of the site ogas.space: at start, if the settings profile.check_on_start and sources.check_on_start are on, otherwise by the button «Check»; the site learns only the address it is read from, as with any visitor. A module may send data: it is trusted code with the person's rights.
The journals keep as little of the content of packets as possible: instead of copies of big data there are references in them. How long to keep the journals, when to delete them and what the law of this or that country demands is not defined.
7 Updates and the origin of code
An update is replacing the executable files. They have no signature, so the authenticity of the executable files, modules and Python packages is not guaranteed.
In development:
- the versions of Rust dependencies are pinned in
Cargo.lock; - licences are checked: an outside package whose licence the platform cannot take, and a package of the platform without its own licence, do not pass
make ci(scripts/third_party.py --check); the delivery carries the list of outside packages with the texts of their licences; - the needed versions of Python packages are pinned in the
requirements.txtof modules; - changes of manifests are reviewed;
- secrets are kept out of the repository;
- the paths inside an export of a process and the prints of modules are checked when added;
- the versions of the kernel, functions and modules are written into the diagnostic information.
Ready programs, modules and updates of programs and of the platform are released on the site ogas.space. Its showcase is signed by the site key (8.5); the executable files of an update of the platform are not. What the platform does with what is downloaded from a source, and what it does not promise — 3.14.
The platform does not become a store of secrets.
8 The profile, parcels and the signature of the site
The profile is what the person signs everything the platform sends to ogas.space with; the signature of the site is what the author of the site signs everything the platform reads from there with. The owner of the profile, parcels and letters is the function profile; of the showcase — the function sources. The formats — File formats, section 21.
8.1 The keys of the profile
Table 1 — The keys of the profile
| Key | What it is | Where it lives | What for |
|---|---|---|---|
| main | Ed25519 | with the person: as the recovery code on paper and as the key file where they decided; the platform does not keep it | make the profile, join and revoke a computer, change and delete the profile |
| computer | Ed25519, random | the data folder of the function profile, for the user only |
sign parcels; the main key vouched for it |
| letter | X25519, derived from the main one | the same place | open letters; the same on every computer of the profile |
The secret parts of the keys never leave the computer. The public parts of the main key and the computer key travel in every parcel: by them the program of the author of the site checks the signature. They are not shown to the public.
8.2 The recovery code
The code is the main key (32 bytes) and two bytes of its SHA-256, written as 55 signs of the Crockford base32 alphabet in groups of five. When typed in, the letter O reads as zero, I and L as one. A code whose check bytes do not hold is refused (key_code_bad), not read as another key.
8.3 The key file
The key file holds the code. With a password, the code is encrypted by XChaCha20-Poly1305 under a key Argon2id derives from the password; without a password the code lies in the file as it is, and the file has to be kept like the code itself. A wrong password — the refusal key_password_bad.
8.4 What is signed by which key
The main key signs by itself: the card of the profile — in it, it names the computer the card came from — the revocation of computers and the deletion of the profile, and also the vouching for the computer key. The site takes the signature only of computers the main key named in a card. The other parcels are signed by the computer key. The signature is over the bytes of the body of the parcel as they are.
8.5 The signature of the site
Every file the platform reads from ogas.space lies beside its signature <name>.sig — an Ed25519 signature over the line ogas.site/1, the name of the file and its bytes. The public parts of the site keys are written in the common code of the platform; a new site key comes out with a new version of the platform. A file without a signature, or with one that does not hold, is not taken (site_signature_bad, for the showcase — source_signature_bad), and nothing of it is shown.
8.6 Who sees what
Table 2 — Who sees what
| What | The public on the site | The author of the site | Who else |
|---|---|---|---|
| the card of the profile | after the author of the site looked at it | yes | — |
| the keys of the profile | no | the public parts | the secret ones — only the owner |
| a review, a request, «I'll do it», what was made | after the author of the site looked at it, with the name or «incognito» | yes, and whose profile | — |
| a bug report | only what happens and the version, if the author of the site put it under the thing | whole | the author of the thing — whole, without the reporter's name |
| the author's answer to a review | under the review, after the author of the site looked at it | yes | the one who wrote the review sees it in their sendings |
| a new review of a thing | the review — after the author of the site looked at it | yes | the author of the thing — by a notice in the platform |
8.7 When the platform turns to the site
It sends — only at the person's command. It reads — at a command, or at start if the setting profile.check_on_start (one's sendings and letters) or sources.check_on_start (a new version of the platform) is on; both are on by default and seen in the settings.