-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Conversation
Thanks for taking the time to open a PR!
|
Test summaryRun details
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
patches/bytenode+1.3.7.dev.patch
Outdated
new file mode 100644 | ||
index 0000000..314eeee | ||
--- /dev/null | ||
+++ b/node_modules/bytenode/lib/compileFile.js |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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"
patches/bytenode+1.3.7.dev.patch
Outdated
+ * @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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
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
cypress-documentation
?type definitions
?