Skip to content

fix: guard identifier lookups against object prototype collisions - #1519

Open
mah1104ahm wants to merge 4 commits into
OpenFn:mainfrom
mah1104ahm:fix/identifier-prototype-collisions
Open

fix: guard identifier lookups against object prototype collisions#1519
mah1104ahm wants to merge 4 commits into
OpenFn:mainfrom
mah1104ahm:fix/identifier-prototype-collisions

Conversation

@mah1104ahm

@mah1104ahm mah1104ahm commented Aug 31, 2026

Copy link
Copy Markdown

Short Description

Closes #1513.

Prevents workflow step, edge, adaptor, and linker identifiers such as constructor and __proto__ from colliding with inherited JavaScript object properties.

Implementation Details

  • require own properties when reading job errors and edge conditions;
  • define arbitrary identifiers as own enumerable data properties;
  • keep autoinstall paths in a Map internally while preserving the existing object return type;
  • add regression tests for the three reported collision failures;
  • add patch changesets for runtime, engine-multi, and ws-worker.

QA Notes

  • focused regressions: 72 passed;
  • type checks passed for runtime, engine-multi, and ws-worker;
  • full affected-package suites passed (ws-worker: 365 enabled tests);
  • full monorepo build passed using pnpm 10.32.1.

One ws-worker Sentry timing assertion failed on the first broad run, passed in isolation, and the complete ws-worker rerun passed. It is outside the changed paths.

AI Usage

  • I have used Claude Code
  • I have used another model
  • I have not used AI

AI-assisted development tools supported issue analysis, implementation, regression testing, and verification. The submitted changes were validated through the test and build evidence above.

@mah1104ahm
mah1104ahm force-pushed the fix/identifier-prototype-collisions branch from 22ca652 to e975cd2 Compare August 31, 2026 15:09

@josephjclark josephjclark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution @mah1104ahm but I don't love these changes.

I'm broadly in favour of using more maps and fewer objects for indexes - although it's tricky for us because maps don't serialize and sometimes they can be a pain.

But I'm not convinced that the underlying issue is ever going to cause users a problem in production. I can run steps called constructor and __proto__ without any problems.

Maybe you can give me and @elias-ba (the original reporter) a bit of time to discuss the original issue, and we'll come back to you

Comment thread integration-tests/worker/package.json Outdated
"start": "docker run worker-integration-tests",
"test": "pnpm clean && npx ava -s --timeout 2m",
"test:cache": "npx ava -s --timeout 2m"
"test": "pnpm clean && npx ava -s --timeout 4m",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this change was added here? We do have a few flaky tests but I'm not aware that timeout is the issue. Please revert.

import { AutoinstallError } from '../errors';
import ExecutionContext from '../classes/ExecutionContext';

const hasOwn = (target: object, key: PropertyKey) =>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called just twice in this file. I see no reason to alias it - please just do eg context.versions.hasOwnProperty(name)

if (!context.versions[name]) {
context.versions[name] = [];
if (!hasOwn(context.versions, name)) {
Object.defineProperty(context.versions, name, {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But name here is always an adaptor name. It should always be of the form @openfn/language-x. This will never conflict.

});
});

test('autoinstall supports an adaptor named constructor', async (t) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good test - this fails on main. It's a bit of a strech of a use-case because I can't ever see is trying to use a key like this as an adaptor name - but it validates the fix and proves that using a map rather than object is a better approach here

Then again, wouldn't hasOwnProperty here be a neater fix than using the map?

// autoinstall.ts
if (!context.versions[name]) {
      context.versions[name] = [];
    }

job.linker ??= {};
// @ts-ignore
job.linker[name] = paths[adaptor!];
Object.defineProperty(job.linker, name, {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But constructor is perfeclyl safe to write to an object? Not sold we need this complication

export const conditions: Record<string, string> = {
on_job_success: 'Boolean(!state?.errors?.[upstreamStepId] ?? true)',
on_job_failure: 'Boolean(state?.errors && state.errors[upstreamStepId])',
on_job_success:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just run tests on __proto__ and constructor as step names and the conditions seem to evaluate fine. This diff makes the compiled significantly harder to read (which is a problem when we ever get to debugging).

Are we sure this fix is needed?

},
});

t.deepEqual(Object.keys(workflow.steps), ['__proto__']);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this only fails on the object.keys call, which is a bit artificial. Runs actually seem to work perfectly well with __proto__ as a step name (and tbh I don't have a lot of sympathy for users wishing to do this!)

@mah1104ahm

mah1104ahm commented Sep 3, 2026 via email

Copy link
Copy Markdown
Author

@mah1104ahm

mah1104ahm commented Sep 3, 2026 via email

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Guard id lookups against built-in object properties

2 participants