Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defense against prototype pollution and supply chain attacks #412

Open
22 of 23 tasks
kriskowal opened this issue Sep 2, 2020 · 15 comments
Open
22 of 23 tasks

Defense against prototype pollution and supply chain attacks #412

kriskowal opened this issue Sep 2, 2020 · 15 comments
Projects

Comments

@kriskowal
Copy link

kriskowal commented Sep 2, 2020

At @Agoric, we’ve begun investigating how compatible CosmJS is with SES such that projects using CosmJS can use tools like SES and LavaMoat to mitigate supply chain and prototype pollution attacks.

To evaluate whether a module and its transitive dependencies can be initialized under SES, I’ve locally run the following script in each of the CosmJS library packages. These are the packages that all have a single entry-module named ./build/index.js.

require("ses/lockdown");
lockdown();
console.log(require("./build/index.js"));

This provides some basic assurance that these libraries could be used in a project using SES. Likely incompatibilities usually arise when a library depends on a shim or polyfill, and these can usually be fixed by using the corresponding “ponyfill”, like colors/safe instead of colors. (Though I would note, CosmJS depends much more heavily on the equivalent ansi-colors module that does not perform any prototype attacks monkey-patching.)

  • encoding
  • math
  • proto-signing
  • utils
  • tendermint-rpc
  • stargate
  • launchpad
  • crypto
  • cosmwasm

The following depend on a broken ponyfill, observable-symbol/ponyfill, which we haved worked with Ben Lesh to fix. This fix comes in a new major version, so an explicit upgrade should get the remaining libraries working.
benlesh/symbol-observable#48

  • json-rpc
  • socket
  • stream

Of the two applications, faucet and cli, the faucet appears to work with the SES lockdown snippet at the head of its bin.

#!/usr/bin/env node
require("ses/lockdown");
lockdown();
  • faucet
  • cli

The CLI runs into this mysterious error, far far from any likely cause:

  cosmjs/node_modules/ast-types/lib/types.js:281
                      throw new Error("missing name");
                      ^

  [Error <Object <[Object: null prototype] {}>>: missing name
    at Object.from (cosmjs/node_modules/ast-types/lib/types.js:281:27)
    at cosmjs/node_modules/ast-types/lib/types.js:247:71
    at Array.map (<anonymous>)
    at or (cosmjs/node_modules/ast-types/lib/types.js:247:37)
    at default_1 (cosmjs/node_modules/ast-types/def/core.js:267:25)
    at use (cosmjs/node_modules/ast-types/fork.js:47:31)
    at Array.forEach (<anonymous>)
    at Object.default_1 [as default] (cosmjs/node_modules/ast-types/fork.js:14:10)
    at Object.<anonymous> (cosmjs/node_modules/ast-types/main.js:18:24)
    at Module._compile (internal/modules/cjs/loader.js:1201:30)]

This is a great place to start. From this position, we would ideally add SES lockdown to the testing aparatus for each of these packages, so every pull request against them would be verified to remain compatible.

To this end, there are a number of ways that Jasmine and Karma are themselves not yet ready to run under environmental lockdown, largely because they use the infamous colors package, which in addition to monkey-patching String.prototype upon initialization, provides a “themes” feature that enables users to indirectly punch String.prototype at runtime.

Karma should work with this proposed and accepted fix to use colors/safe instead. It would be nice if it used ansi-colors just to reduce duplication among your transitive dependencies, but harmless otherwise.
karma-runner/karma#3548

  • proposed changes
  • landed
  • released (requires karma > 5.2.1)
  • integrated in cosmjs

Jasmine itself is largely compatible, because the only primordial it modifies is globalThis, and SES lockdown leaves this as an exercise to the user.

Jasmine Test Reporter makes uses of colors themes.
To overcome this obstacle, we would need either an alternate test reporter plugin or a major version bump and an architecture more closely aligned with dependency injection. I’ve proposed the changes. The author finds them amenable. Work would need to be planned.
bcaudan/jasmine-spec-reporter#528

  • proposed design
  • implemented design
  • landed
  • released
  • integrated in cosmjs

The nature of SES compatibility exploration is that it is easier to keep than to obtain. There may be further obstacles behind these first exceptions I’ve encountered, but overall, it seems CosmJS is very nearly already compatible with SES and could encourage users to use it (and LavaMoat) to protect their applications from these kinds of attack.

@webmaster128
Copy link
Member

Thanks a lot for all the effort @kriskowal. Happy to support this work where possible.

For the observable-symbol update we need staltz/xstream#312. For the merged patch in karma, we need a release > 5.2.1.

@kriskowal
Copy link
Author

kriskowal commented Sep 20, 2020

I’m delighted to share, jasmine-test-reporter@6 relieves the dependency on String.prototype pollution from colors. There is a minor API change, where the color theme must be expressly provided to the reporter.

@kriskowal
Copy link
Author

Thanks a lot for all the effort @kriskowal. Happy to support this work where possible.

For the observable-symbol update we need staltz/xstream#312. For the merged patch in karma, we need a release > 5.2.1.

I’ve taken the liberty to propose this change with staltz/xstream#315

@kriskowal
Copy link
Author

@webmaster128
Copy link
Member

webmaster128 commented Sep 24, 2020

most, another dependency of xstream, needs an observable-symbol version bump. https://github.com/cujojs/most

This is just a devDependency of xstream. Does this really matter for as as users of xstream?

@kriskowal
Copy link
Author

This is just a devDependency of xstream. Does this really matter for as as users of xstream?

I suspect that it will be hard to land the version bump to xstream without also bumping most, since these presumably need to agree for xstream tests to pass. I could be mistaken.

@kriskowal
Copy link
Author

Ben Lesh released symbol-observable@2.0.2 this morning with new TypeScript definitions.

I’ve posted a change for MostJS that brings it up to speed with symbol-observable and switches it to use the ponyfill so it too can be used under SES. cujojs/most#541

@kriskowal
Copy link
Author

And, attempting to upgrade xstream, evidently I forgot to add ponyfill.d.ts to the files mask in package.json. Turning the crank again: benlesh/symbol-observable#51

@kriskowal
Copy link
Author

kriskowal commented Oct 2, 2020

Summary of what’s happened so far:

  • The karma test runner released with a fix for SES compatibility refactor: use colors/safe karma-runner/karma#3548
  • The jasmine-spec-reporter released a major upgrade with SES compatibility Use colors/safe bcaudan/jasmine-spec-reporter#538
  • symbol-observable@2.0.3 has been released. This version can run under SES with some small changes to how it’s used. CosmJS uses this through its dependency on xstream, which in turn uses most, which is only dependent upon it to the extent it’s necessary to pass its own tests. Once these dependencies use the new version, we’ll be able to upgrade them in CosmJS which will make CosmJS combine well with SES. xstream in particular needed TypeScript support for the symbol-observable change.
  • I have an open change to most in review at Use Symbol.observable “ponyfill” cujojs/most#541. This entailed an upgrade for symbol-observable, changes to how the library uses symbol-observable, and an additional dependency on globalthis to facilitate that.
  • I have a draft change to xstream chore(deps): Upgrade symbol-observable to version 2 staltz/xstream#315 This is pending a release of most with the above changes, and will require a similar treatment as the change to most.

The pending work, in steps, is:

  1. Await a new release of most. I anticipate no further work.
  2. Finish integrating most into xstream and await a new release.
  3. Upgrade the new xstream in cosmjs packages and propose changes. At this point cosmjs is SES compatible.
  4. Upgrade the karma and jasmine-spec-reporter dependencies of cosmjs and propose changes. At this point, cosmjs will have continuous verification of SES compatibility.

@webmaster128
Copy link
Member

@kriskowal could you double check karma and jasmine-spec-reporter. I think I updated them after your patched.

@kriskowal
Copy link
Author

@webmaster128 I’ll be sure to. The next, and I presume last, step is for me to propose a change that adds SES to the test scaffold to confirm that CosmJS is now SES-compatible and to prove against regressions going forward.

@willclarktech willclarktech added this to To do in CosmJS via automation Oct 20, 2020
@willclarktech willclarktech moved this from To do to In progress in CosmJS Oct 20, 2020
@webmaster128
Copy link
Member

@kriskowal what do you mean by "test scaffold"? Would it be possible for us to pick up your work from here or does this require some work in the SES-shim repo?

@kriskowal
Copy link
Author

@webmaster128 There’s an opportunity in the jasmine-test-runner scripts in each package to import a module early in initialization that in turn imports ses and calls lockdown(). This would be the final step to ensuring that all of CosmJS can be executed in a SES programming environment, that is, with immutable shared prototypes.

@willclarktech
Copy link
Contributor

Investigating the error from the @cosmjs/cli package, I believe it’s introduced by the recast dependency because this line causes the error to happen even if the babylon parser options are removed:

https://github.com/cosmos/cosmjs/blob/4b7a060/packages/cli/src/async.ts#L9

Looking into recast a little bit, I had a hunch the problem might come from their dependency on private (https://github.com/benjamn/private), but I tried updating recast to the latest version which doesn’t have that dependency any more (but does have a new dependency on tslib - https://github.com/microsoft/tslib) and the problem remained.

@webmaster128
Copy link
Member

The missing name that the error complains about has those 3 different values when running without SES:

[Function: default_1]
Function name: string | number | boolean | null | undefined
Function name: number >= 1
Function name: number >= 0

This does not make much sense to me. Why is string | number | boolean | null | undefined a name, which looks like a TypeScript type? Why is number >= 1 a name which looks like a function body.

I guess this requires a larger debugging session.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
CosmJS
To do
Development

No branches or pull requests

3 participants