endo icon indicating copy to clipboard operation
endo copied to clipboard

removeProperties doesn't clean props of anonIntrinsics?

Open warner opened this issue 6 years ago • 5 comments

[edit 2020-09-15 @kriskowal]

@erights has volunteered to verify that the below issue is no longer a problem.


@dtribble and I were looking at removeProperties.js, and noticed that we build and add the anonIntrinsics to the whitetable, but then clean() is called on the global object. Since these intrinsics are (by definition) not reachable by recursive property lookup on the global, clean() will never visit them, so any whitelist settings that might delete their properties won't ever get applied. This could lead to a surprise if e.g. TC39 adds a new unsafe property to AsyncFunction.

(this is unrelated to freezing the primordials, because in hardenPrimordials.js we re-generate the anonIntrinsics and attach them to a root object, which we then deep-freeze along with everything reachable from the global)

One fix might be to change the end of removeProperties to also clean everything on the anonIntrinsics list:

clean(global);
Object.getOwnPropertyNames(intr).forEach(name => clean(intr[name]));

Another might be to rearrange the whole clean/freeze pathway to create a single object that makes all intrinsics (named and anonymous) available in a hierarchy that mirrors the whitelist table, and use it both for cleaning and freezing. This table might then be useful to construct the "fringe" set that a standalone harden() might need.

warner avatar Feb 15 '19 20:02 warner

I thought that we created a new root object containing both global and anonIntrinsics, so that all primordials would be reached by simple navigation starting there.

erights avatar Feb 16 '19 06:02 erights

hardenPrimordials is where we create that root object (https://github.com/Agoric/SES/blob/a33cb8952b243dfd863c1df9c32f20dfadf4715c/src/bundle/hardenPrimordials.js#L6), so we're freezing everything. But removeProperties (https://github.com/Agoric/SES/blob/a33cb8952b243dfd863c1df9c32f20dfadf4715c/src/bundle/removeProperties.js#L164) walks the global object, which doesn't include the anonIntrinsics.

warner avatar Feb 16 '19 10:02 warner

@erights Is this still an issue? If not, please close.

Tartuffo avatar Jan 21 '22 00:01 Tartuffo

I need to take a look. I can imagine making this mistake, and it could be a severe problem. Leave open and with the "security blocker" label until then.

erights avatar Jan 21 '22 07:01 erights

@erights This does not have an area label that is covered by our weekly tech / planning meetings. Can you assign the proper label? We cover: agd, agoric-cosmos, amm, core economy, cosmic-swingset, endo, getrun, governance, installation-bundling, metering, run-protocol, staking, swingset, swingset-runner, token economy, ui, wallet, zoe, zoe contract

Tartuffo avatar Feb 03 '22 16:02 Tartuffo

I believe this program confirms the appropriate behavior:

import 'ses';

// getAnonymousIntrinsics uses a utility function to construct an arguments
// object, since it cannot have one of its own and also be a const export.
function makeArguments() {
  // eslint-disable-next-line prefer-rest-params
  return arguments;
}

const calleeDesc = Object.getOwnPropertyDescriptor(makeArguments(), 'callee');

lockdown();

console.log(Object.isFrozen(calleeDesc.get)); // true

Adding a test to close this out.

kriskowal avatar Jan 09 '24 02:01 kriskowal