Giter Club home page Giter Club logo

crochet's Introduction

Crochet

NOTE: Crochet is in early stages of development, there will be a lot of breaking changes here as I figure out what kind of language fits the games I want to create, and how to generalise that.

Crochet is a tool designed for creating and remixing interactive media safely. It is best thought as targeting the domains of Interactive Fiction, Simulation Games, Software Verification, and Interactive/Live Language Tooling.

Documentation

The documentation books on Crochet are a work in progress, you can find them in the Crochet documentation website.

Currently there's:

  • A reference book, which discusses the concepts and design philosophy of Crochet;
  • A syntax cheatsheet, which just lists all syntactical forms with examples; and
  • A contribution book, which describes how to contribute to Crochet.

Installing Crochet

For now, you can install Crochet from npm. You want the @qteatime/crochet package with the experimental flag:

$ npm install @qteatime/crochet@experimental

You can also compile it from source:

$ git clone https://github.com/qteatime/crochet.git
$ cd crochet
$ npm install
$ node make build

See crochet --help (or ./node_modules/.bin/crochet --help if you've installed it locally) for usage information.

Playground

You can try programming interactively with the Playground. You can run with:

$ crochet playground <path/to/your/crochet.json>

For node projects you need to specify node as your Playground execution target, since the default is running the package in the browser:

$ crochet playground <path/to/your/crochet.json> --target node

You do need to specify a package because that's how Crochet tracks dependencies and capabilities. All code you type in the Playground will be executed in the context of the given package. And all dependencies of that package will be loaded first.

The Playground accepts both declarations and statements/expressions.

API Reference

You can get a reference documentation page on any package by using the docs command. E.g.:

$ crochet docs <path/to/crochet.core/crochet.json>

You'll be able to navigate through the documentation by accessing http://localhost:8080 in your browser.

Running packages

You can run a Crochet package on the terminal by using the run command. E.g.:

$ crochet run <path/to/your/crochet.json> -- argument1 argument2

Anything after -- is passed as the invocation arguments as-is to your package. You must provide a command called main: _, where the only parameter will be this list of command line arguments.

Web packages are currently run with the run-web command. This does not accept any invocation arguments:

$ crochet run-web <path/to/your/crochet.json>

You can provide a different port with --port 12345. Currently the server is started on port 8000, and Crochet does not try to find an available port if that one is taken.

Licence

Copyright (c) 2021 Niini
Licensed under the permissive MIT licence.

crochet's People

Contributors

cute-the-niini avatar robotlolita avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

crochet's Issues

`docs` command should not execute prelude expressions

The docs command should never execute any piece of Crochet code, as that is counter-intuitive (and will not work due to the VM not loading any capability or native module). Allowing it to execute preludes means that some packages are effectively undocumentable---the CLI will crash because the VM cannot complete the boot sequence---if they have any of those declarations.

Remove DSL

The idea of DSL was to better support embedded DSLs where users would have more control over how to interpret the syntax, but the syntax itself was fixed. It turned out to be cumbersome, and at the same time made it hard to provide good debugging tools for them, even with it being more static. Crochet will go down the path of having only external DSLs (properly integrated in the IDE, build system, and VM).

Support proper mutually-recursive definitions in Crochet

Crochet separates declarations from expressions to avoid imposing an evaluation order for declarations (and to allow analysis of shapes without security nightmares). However, as currently implemented, declarations are evaluated in the order they appear. This is particularly problematic for types for two reasons:

  1. It makes it harder to properly organise modules, leading to the current 0-types.crochet pattern; but more importantly
  2. It makes it impossible to declare recursive or mutually recursive types, and that makes field contracts often useless. Though this is mitigated by separating cases in a sum type into independent declarations.

Anyway, this should be fixed in the VM so it can conform to the (not yet described) language spec. The simple solution is to allow referring to non-existing definitions with a placeholder, and then replace the placeholder with the correct implementation once we've seen all of its dependencies. We do, however, expect to be able to know some things about the type in several declarations (e.g.: in order to sort commands), so this change has quite some annoying ripple effects.

Placeholder verification has confusing error messages

During the verification phase, if there are any placeholder entities that have not been fulfilled for the package, the package loader will stop with an error. Currently the error looks something like:

Cannot open <package> because it's lacking definitions for: <entity>...

This message lacks any indication of where these entities are used, forcing users to search for them. But it also does not suggest fixes. For example, forgetting to open a package's namespace and using types from that package would result in that message, but the fix would be to open the package's namespace, not to add a new local definition. Typos, similarly, should be reported as possible typos, not as a lacking definition.

Numeric representations with commas can generate unfortunate ambiguities

This happens because the debugging representation of values uses the locale formats, but not all of them go well with the rest of the syntax around debugging representations. E.g.:

>>> 3 hours + 8900 minutes | balanced-to: du-seconds
(duration from crochet.time) [
  days -> 0,
  hours -> 0,
  minutes -> 0,
  seconds -> 544,800,
  milliseconds -> 0
]

`for` iterations only work on lists

Underneath they're converted to _ flat-map: _ calls, however they always produce a list back, and thus cannot be used with other types.

E.g.: the following fails:

for X in #set from: [1, 2, 3, 4] do
  X + 1;
end

It should yield the set [2, 3, 4, 5] instead.

Support remote execution in the Playground

#71 has added a new interactive playground which should replace the previous command-line REPL, even for non-browser projects. However, currently it only supports running browser packages. Future versions of Crochet will completely abandon the command line, and this is blocking that :)

REPL attaches generated variables to the REPL environment

The REPL currently executes code in a single environment, which is reused across all subsequent REPL pieces of code. This usually works correctly, but some expressions, like A | b are compiled with intermediate generated variables, and these get attached to this single shared environment during the execution as well.

As a result, it's not possible to evaluate something like: #result ok: 1 | map: (_ + 1) | value; #result ok: 1 | map: (_ + 1) | value in sequence.

One thing that can be done is to just spawn a new environment to execute the code, then copy all non-generated variables up to the shared one. A generated variable will always have a $ character in its name, and such character is not valid in Crochet variable names.

Forbid construction of placeholder types

As a follow up on placeholder types for out-of-order definitions, we need to also forbid constructing placeholder types, since they don't actually make sense. We currently check for package consistency when loading, but that doesn't work with the playground, which loads definitions directly.

Packaging is broken

Packaging has been broken for a while. It does not consider transitive dependencies, and it knows not about capabilities and isolated filesystems (which it needs to maintain in order to make assets work). Packaging also does not really work for Node targets, meaning that you cannot build an executable from some Crochet package---this in turn makes it difficult to build the other necessary tooling.

Duplicated FFI entries do not cause an error

If a native module contains the following:

ffi.defun("hello", () => ffi.text("Hello!"));
ffi.defun("hello", () => ffi.text("Goodbye!"));

One would expect the second declaration to crash the loader with a "duplicate entry" error, but the declaration is silently ignored.

Move Crochet to qteatime organisation on npm

The Crochet project started on the origamitower organisation, but was later moved to the qteatime organisation here on GitHub, but the packages remain published to origamitower on npm. This causes unnecessary confusion and suspicion; the npm packages, the GitHub packages, and the official website should all share the same organisation name.

Reactions in simulation may be fired despite its preconditions being violated

When the simulation runs, it computes the list of reactions only once for the current turn. However, if a reaction causes any effect it might invalidate further reactions that have been scheduled to fire. This means that the reactions would be fired incorrectly.

Consider the tic-tac-toe example in this repository:

when X simulate-turn, if X won do
  fact state--won state;
  game log: "[X name] won!";
  game update;
end

when state--on-going state, X is player, if not (X won), not L at: C mark: empty do
  fact state--draw state;
  game log: "It's a draw!";
  game update;
end

Here, as part of the reaction to marking one of the cells, the game may either enter a winning or a draw condition. These separate reactions take care of that: if, at the end of one player's turn, the X won predicate succeeds, then we move the game to the winning state. But if we've exhausted all cells and found no winner, we move the game to the draw state---this further explicitness in checking for a winning condition is also necessary because Crochet does not guarantee any ordering between events.

Now, the second reaction is problematic. We have more than one player, so each player triggers a reaction here when the game reaches a draw state, because neither of them will have won. As a result of reaching a draw state we move the game to "state--draw", but we also cause effects that show this on screen. In the tic-tac-toe example, this causes It's a draw to be logged twice, because we run the reactions sequentially but we compute them eagerly, before we fire all of them.

The language could choose to not validate the preconditions after reactions, which would force users to rewrite their reactions with this in mind, and manually take care of multiple reactions firing. But that does not seem like a good direction, so it's quite likely that this will be solved by guaranteeing that reactions only fire if they're still valid.

Remove dynamic features from record type

Records are currently a "less useful" map type, they should be just an extensible record with no dynamic features. This will make it possible to extend dispatch to records as well, but it requires some work in converting some current misuses of records into uses of map.

The trusted base for Crochet is too big!

Currently all of the packages in the standard distribution are part of the trusted base. Packages in the trusted base get more powerful FFI access, construction and projection capabilities over intrinsic types, and are able to load native code without requiring a native capability.

This makes the surface of dangerous attacks in Crochet too large. Bugs in an otherwise innocuous package, such as crochet.text.regex, could allow malicious code to get access to all of this power, effectively subverting most of the runtime safety mechanisms in Crochet.

This won't be addressed for the first experimental release, as it requires significant amount of work around safe native code support, but it's important that people are aware of this issue.

Launcher needs to ask for capability grants for projects it opens

Currently it just grants some powerful capabilities to the root package, including native, which pretty much gets rid of all security measures Crochet could provide (there's a related issue of passing trusted FFIs to untrusted native modules here that also needs to be tackled) :/

crochet.core cannot be debugged with user-level tools

This is a really unfortunate consequence of packages not supporting mutual dependencies. Everything depends on crochet.core, including crochet.debug, consequently crochet.core cannot have any dependencies. Due to the strict capabilities on open coupled with dependencies, it's not possible for core to open the debugging package.

This will require some more thinking around both debugging tools and the roles of dependencies, capabilities, and provided services.

Also marginally related to #10.

Evaluation of long-running code happens in Playground's main thread

Currently the Playground runs both Node and Browser pieces of Crochet code in the main thread, which means that the Playground UI itself freezes in case the evaluation does not complete in reasonable amount of time. This is not acceptable for the stable release, but can be tolerated for the experimental releases. Fixing involves moving the kernels to an isolated worker.

Crochet should ensure that the realm is sealed

Currently, Crochet does not do any changes to JavaScript's semantics. But any JavaScript code loaded after Crochet might do so, because the intrinsic objects are globally mutable in the default realm. This means that even semantics Crochet relies on for correctness, and security assumptions it makes based on JavaScript's default semantics might turn out to be incorrect. This is not acceptable.

Of course, the problem is that Crochet can't just lock down the semantics on its own: for example, in the Browser it is the user who decides when to load Crochet, and at that point in time several other pieces of JS might have been loaded---they might even have been injected there by random extensions the user has installed. At that point there's nothing Crochet can do, because there's nothing it can realistically assume from the environment. On the other hand, if Crochet does manage to be the first thing loaded and then lock down the realm (to guarantee some base semantics), any code being loaded after that does not know this semantic change has taken place will not work, causing a fair amount of frustration to users. If Crochet uses a separate realm to load itself FFI suffers. There's no winning in this game. And the user that is embedding Crochet needs to be, unfortunately, aware of all of this complexity.

This is not currently considered a pressing issue because Crochet is in experimental release, however, in the presence of thirdy-party untrusted code, this makes Crochet vulnerable to silly JavaScript attacks like prototype pollution. This is, to some extent, the case with Crochet's trusted code base. Though Crochet keeps external dependencies on the runtime minimal, none of them have been verified, and should not be considered secure.

Absolute-positioned documents can be included outside of fixed-layout

This allows these documents to exist outside of their rightful boundary, which right now allows them to be confusing to the user (and hard to debug). Because interactive components are not a thing in the document language yet, this is a moderate issue, there are not enough compelling ways of using this for harmful attacks.

E.g.:

#document plain-text: "Annoying text"
  | position: (#doc-point2d x: 0 y: 0)

The `float` type name should specify its size

Non-size-suffixed type names should be reserved for arbitrary-precision types. If a type is bounded to a certain size, this should be reflected in its name. Doing so avoids confusing situations where people may not reason about the information bounds they're encoding in their programs, thus making programs unsafe.

Note that this also implies that a decimal type, which is arbitrary precision, must be provided by crochet.core.

Packages can add commands to types they don't own

This is an intended behaviour, so the aim of this ticket is not to remove it, but to add a bit more of controls to it so users can consent to it being done. Because packages can add commands to any type, they may be able to trick users into executing code that they would otherwise not do.

The issue is already mitigated with the use of capabilities. Even though, in theory, attackers can add commands to any types, and try to trick users into invoking their version of the command (likely a typo), they are still restricted in what they can do; they can do exactly what the capabilities granted to their package allows them to do. This reduces the amount of interesting attacks that can be done.

Problem with syntax highlight

Hi, I'm reading the Crochet documentation. I"m using the dark theme and string literals are displayed on a bright background which makes them hard to read, mainly on my phone. I would expect them appearing on a dark background instead.
image

Crochet is inaccessible

Crochet is currently not designed with accessibility in mind. What this means is that it will need to go through a redesign phase later to fix this (which will need to happen before a public release). This is otherwise just here to keep track of the issue.

Construction and projection capabilities are not checked

Crochet's entire set of security guarantees rely on being able to control which packages have access to which types, as well as what they can do with these types. Types represent capabilities. But there are some more fine-grained capabilities in a type: using a type has different security implications from constructing a type or projecting fields from a type. That's why Crochet defines these as distinct capabilities.

Capabilities are handled at a "package" level. So packages define a trust boundary. In the specified semantics, constructing and projecting capabilities are granted to the defining package. Meaning that if package A defines a type T, then only package A is able to use new T or TValue.field. This is currently unchecked, which leads to these expressions succeeding outside of A as well.

Known security issues

This is a meta-issue to keep track of the security issues that are currently known, but not deemed immediate enough to fix during the experimental Crochet phase. That doesn't mean these security issues aren't dangerous, though. And they do certainly pose a threat to pretty much all security guarantees Crochet can provide.

  • Node wrapper libraries don't use effects --- this makes it hard to provide safe experimentation with them.
  • No IR validation --- this means attackers are able to craft IR binaries where define operations can execute arbitrary code. What this means is that attacks abusing capabilities can take place at load time rather than run time. The launcher currently assumes loading a package is safe, making opening packages dangerous.
  • Non-audited dependencies --- the dependencies that make up Crochet's VM and tools have not been audited. It's possible that they contain undesirable code and capabilities.
  • Non-verified JS compiler --- Browser packages are generated with Browserify, which includes its own runtime and isn't a verified compiler. It's possible that Browserify introduces bugs that weren't present in the original source code.
  • Trusted FFI provided to non-TCB packages --- The trusted FFI would allow attackers to modify the VM semantics, and interact with the VM in unsupported ways. That said, native code isn't sandboxed at all to begin with, so there are bigger problems there.
  • Some TCB dependencies are not audited --- And we rely on package managers to install them. This makes the VM, runtime, and tools vulnerable to dependency hijacking.
  • Typed data supports dynamic projections --- If a piece of code uses X.[K] for their own internal typed structure, and K is provided by an attacker, they would be able to bypass projection capabilities and extract private data.
  • No provenance checks on packages --- Crochet relies on package names being unique and readily identifiable (traceable to a source), however there's nothing that enforces this today. As a result attackers can abuse this by setting the name of their package to anything and trick users into granting them capabilities.
  • Assets can be accessed by other packages --- Currently the URI for assets on the web includes no capabilities, so any package with the ability of making network requests can access other package's assets.
  • Sensitive data may be leaked with debug representations --- As long as Crochet's debugging tools are in this transitionary state from rudimentary JS pretty-printing to capability-aware representations in Crochet code, the JS pretty-printing part will leak possibly boxed/secret data to standard output and other debugging outputs.
  • Paths generated without semantic guarantees --- The assets code currently generates some paths without semantic guarantees about their composition. There might be cases where this results in paths that are unexpected. Also file systems are a mess so there's a lot else here that needs attention.

[] in an interpolation fails silently

Though all strings should be parsed as interpolations, if they have at least one hole expression in them, having [] causes the expression to be parsed as a literal string---not an interpolation---even if other holes are well-formed. The parser should be more strict here, commit to the interpolation grammar, and just issue an error in these cases.

E.g.:

"this [should be an interpolation] but the following [] causes it to be parsed as a literal string"

Due to how PEG's first valid choice semantics work, this also affects everything that cannot be parsed as an expression. "this is a [type]" will also fallback to a literal string...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.