ember-cli / ember-cli-preprocess-registry

MIT License
1 stars 13 forks source link

No way to block a child addon from loading #26

Open jamesarosen opened 6 years ago

jamesarosen commented 6 years ago

I have an addon, parent, that has as a dependency, another addon, insecure-child. I'd like to include parent in my application, but insecure-child has an unpatched security problem, so I'd like to block it. (It's critical only to parts of parent that my application doesn't use.)

Things I've tried:

Blacklist

// my-app/ember-cli-build.js
let app = new EmberApp(defaults, {
  addons: { blacklist: ['insecure-child'] }
})

ember-cli throws an exception saying that child is not found.

Monkey-Patch shouldIncludeChildAddon

// my-ap/ember-cli-build.js
const EmberAddon = require('ember-cli/lib/models/addon')
const shouldIncludeChildAddon = EmberAddon.prototype.shouldIncludeChildAddon
EmberAddon.prototype = function(child) {
  return child.name === 'insecure-child' ? false : shouldIncludeChildAddon.call(this, child)
}

This doesn't work because ember-cli-preprocessor-registry runs before ember-cli-build loads.

Configurable child blacklist

If I control parent, I can override shouldIncludeChildAddon there. My first instinct was

// parent/index.js
config(environment, appConfig) {
  this.addonBlacklist = (appConfig.parent.addons || {}).blacklist || []
}

shouldIncludeChildAddon(child) {
  return !this.addonBlacklist.includes(child.name)
}

The problem with this is that shouldIncludeChildAddon is called before config is called. I could call this.parent.config(), but I don't have an environment to pass it.

jamesarosen commented 6 years ago

I ended up doing this:

// parent/index.js
const shouldExcludeInsecureChild = process.env.EXCLUDE_INSECURE_CHILD === 'true'

init() {
  if (shouldExcludeInsecureChild) return
  if (this.parent.addonPackages['insecure-child'] != null) return
  console.warn(`
WARNING: in v2.0, parent will change insecure-child to an optionalDependency.
If you want to use insecure-child, add it to your project's package.json as a dependency.
If you do not want to use insecure-child, set EXCLUDE_INSECURE_CHILD to "true"
  `)
}

shouldIncludeChildAddon(child) {
  return child.name !== 'insecure-child' || !shouldExcludeInsecureChild
}