Navigation Menu

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

fix: add column, line, and method check to integrity check #25094

Merged
merged 15 commits into from Dec 12, 2022

Conversation

ryanthemanuel
Copy link
Collaborator

User facing changelog

Integrity check will now fail if the column and line numbers are altered in the binary entry point.

Additional details

Previously, we would only check for column and line numbers in the entry point, but we can increase the strength of the integrity check by also checking for the specific column and line numbers of the executing code.

Steps to test

Ensure the tests pass on CI (especially the binary tests)

How has the user experience changed?

n/a

PR Tasks

  • Have tests been added/updated?
  • [na] Has the original issue (or this PR, if no issue exists) been tagged with a release in ZenHub? (user-facing changes only)
  • [na] Has a PR for user-facing changes been opened in cypress-documentation?
  • [na] Have API changes been updated in the type definitions?

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Dec 10, 2022

Thanks for taking the time to open a PR!

@cypress
Copy link

cypress bot commented Dec 10, 2022



Test summary

199 0 26 0Flakiness 0


Run details

Project cypress
Status Passed
Commit 8cebd44
Started Dec 12, 2022 8:29 PM
Ended Dec 12, 2022 8:38 PM
Duration 09:25 💡
OS Linux Debian -
Browser Chrome 106

View run in Cypress Dashboard ➡️


This comment has been generated by cypress-bot as a result of this project's GitHub integration settings. You can manage this integration in this project's settings in the Cypress Dashboard

@@ -2,6 +2,8 @@ const OrigError = Error
const captureStackTrace = Error.captureStackTrace
const toString = Function.prototype.toString
const callFn = Function.call
const filter = Array.prototype.filter
const startsWith = String.prototype.startsWith
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know why we create all these aliases in the first place instead of just doing tempError.filter(...) etc? It looks like something to do with the integrity check - how does comparing if (filter.call !== callFn) { verify the integrity?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We are protecting against the prototype call method on each of those functions being tampered with. So we want to make sure that they are still equal to the original function call prior to using them

new file mode 100644
index 0000000..314eeee
--- /dev/null
+++ b/node_modules/bytenode/lib/compileFile.js
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks hard to maintain - is there a bug in the library or we just needed a specific feature?

It is possible to write our own compileElectronCode, wrapping the bytenode library functionality, and put it in the monorepo (eg under scripts)? That seems like it'd be easier to maintain, long term, than patching the package.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The goal here is minimize the code that is in our entry point bundle in prod to prevent as much “dead code” that could be injected into as possible. Thus, I patched bytenode to split out the compilation (package time) from the loading (run time). It is definitely a little involved but I don’t think we are going to be updating that dependency very often.

// eslint-disable-next-line no-undef
fileName: [appPath, 'index.js'].join(PATH_SEP),
line: 1,
column: 2076,
Copy link
Member

Choose a reason for hiding this comment

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

what are the scenarios where this column number would change? new imports into the root file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This would change if our entry point file bundle changed at all. I don’t see that happening very frequently though and if it does, we will just update these numbers. The situations where we would update the entry point bundle is if this file changes: https://github.com/cypress-io/cypress/blob/develop/scripts/binary/binary-entry-point-source.js or if bytenode gets updated.

Copy link
Member

Choose a reason for hiding this comment

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

will this error provide insights into that column number or do we just fail and we'd have to manually verify?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What sort of insights would you expect? The error will let us know what that there was a difference and what the difference is (similar to what we were doing with file and function names previously).

Copy link
Member

Choose a reason for hiding this comment

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

sorry - i didn't remember what we were prev doing. I was just curious if this error outputs on any download or just during the build process

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This error will output when the binary is corrupted. So if a user tries to open Cypress with a bad binary, they will see "your code executed from column x instead of y"

+ * @param {string} [output] The output filename. (Deprecated: use args.output instead)
+ * @returns {Promise<string>} A Promise which returns the compiled filename
+ */
+ const compileFile = async function (args, output) {
Copy link
Member

Choose a reason for hiding this comment

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

Looks like compileFile & compileElectronCode are 1:1 with the "removed" code in this patch. Can we re-generate to only remove the extra methods? Also why does it matter if we remove the other methods? Any other impact beyond making it a scoped import vs a global?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I’ll regenerate this to make sure it’s cleaner. The main reason I want to remove as much as possible is to prevent “dead code” from being in the bundle that could be deleted and new code added in its place.

Copy link
Member

Choose a reason for hiding this comment

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

I didn't realize that the binary-cleanup script was being bundled and shipped with the binary. Thought it was only used for building the binary content.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's used for bundling but then reading the content that was bundled later as well.

Copy link
Member

Choose a reason for hiding this comment

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

Just so I understand, could you share where? Also do we need to maintain this require if it's only exporting the compileCode fn? https://github.com/cypress-io/cypress/blob/emily/delayed-ci/scripts/binary/binary-entry-point-source.js#L6

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The require actually includes this code as well, but as I'm thinking through this, since I'm patching anyway I can make this a little clearer: https://github.com/bytenode/bytenode/blob/master/lib/index.js#L252

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.

None yet

5 participants