feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: write script and args to temp file and run that - #78

Merged
nlf merged 3 commits into
mainfrom
nlf/file-first
Jun 21, 2022
Merged

feat: write script and args to temp file and run that#78
nlf merged 3 commits into
mainfrom
nlf/file-first

Conversation

@nlf

@nlfnlf commented Jun 15, 2022

Copy link
Copy Markdown
Contributor
  1. we now properly escape strings for shells instead of using the horribly incorrect JSON.stringify() approach
  2. rather than trying to build a string to pass to the shell that needs to be (in windows) double escaped, we can instead write the script and the singly escaped arguments to a file and run that file

i've done my best in spelunking through open issues and verifying this approach fixes our reported issues, though it's very likely there are more than these:

closes#31
closes#60
closesnpm/cli#3067
closesnpm/cli#3337
closesnpm/cli#3600
closesnpm/cli#3680
closesnpm/cli#4873
closesnpm/cli#4968
closesnpm/cli#5004

Comment threadlib/escape.js Fixed
@nlf
nlfforce-pushed the nlf/file-first branch 2 times, most recently from 10ae363 to d678908CompareJune 15, 2022 17:49
@nlf
nlf marked this pull request as ready for review June 15, 2022 18:55
@nlf
nlf requested a review from a team as a code ownerJune 15, 2022 18:55
Comment threadlib/escape.js
return `''`
}

if (!/[\t\n\r "#$&'()*;<>?\\`|~]/.test(input)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanna be sure it's intentional that we're only looking for certain whitespace characters, and not using \s. Will approve assuming this is intentional.

@nlfnlfJun 16, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it was meant to be a list of each individual character that causes us to need single quotes to avoid expansion/keep the argument in one piece, the switch could likely be made but i felt like this was more explicit and clear

@nlf
nlf merged commit 0a351e9 into mainJun 21, 2022
@nlf
nlf deleted the nlf/file-first branch June 21, 2022 18:38
@rhendric

Copy link
Copy Markdown

Did you test this with scripts that call executables from dependency packages? As we've discussed in the past, scripts that call executables like node require a different amount of argument escaping from scripts that call batch-file wrappers like what npm creates (used to create?) for, e.g., rimraf. I suspect putting the arguments into another batch file doesn't change this requirement, but I can't test that right this moment and I'm wondering if you did.

I still stand ready to assist with doing this the right way. The first step is still merging npm/exec#15, unless your plans have changed.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

Did you test this with scripts that call executables from dependency packages?

> npx node@16 -e 'console.log("hello^&")'
hello&
> npx cowsay "hello^&"
_________
< hello& >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

seems to be working right?

@rhendric

Copy link
Copy Markdown

Literal carets are the problem character here, and the problems sometimes don't show up until you try lots of them. Try npx cowsay "hello^^^^^^" and see if you get the same results as cowsay "hello^^^^^^" after installing cowsay. I know of trickier edge cases involving pipes and more advanced shell syntax, but if you pass that test I expect most users would consider the result good enough.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

oh interesting..

> npx cowsay "hello^^^^^^"
__________
< hello^^^ >
----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
> cowsay "hello^^^^^^"
_____________
< hello^^^^^^ >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

so you're right, we do still have the problem with shim scripts. thank you for the reminder!

the solution is to double up the escaping if the first thing we're calling is a batch file, right? i think it's likely we're not going to go down the road of re-escaping the script as defined in the package.json, but we can certainly grab the initial command and use that to trigger double escaping if we need to

@rhendric

Copy link
Copy Markdown

That'd be an improvement over this patch (which is already an improvement over the status quo), and quite possibly ‘good enough’. It is possible to write scripts for which this would do the wrong thing: consider "rimraf build & rimraf tmp & node regenerate.js"; the relevant command is node, which is not a batch file, and double escaping would be incorrect because rimraf is one. Another example: "node print-data.js | node this-script-accepts-args.js"; neither command in this pipeline is a batch file but any arguments to the second one need double escaping because of the pipe (and if that command were a batch file, they would need quadruple escaping!).

If you want to enable correct escaping for scripts like the above, a true solution requires parsing the syntax of the script, not to add escape characters to it necessarily, but to determine the level of escaping that terminal arguments would need. If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut.

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

If you think examples like the above are acceptably rare, then what you proposed is a reasonable shortcut

I think this is likely to be the case. We certainly get few enough complaints about extremely complicated scripts for me to not feel like this further parsing is necessary. At least not right now.

I'll have a pull request up that double escapes if the first command in the script resolves to a .cmd file in a few minutes

@nlf

nlf commented Jun 21, 2022

Copy link
Copy Markdown
ContributorAuthor

i pushed #80 which i think gets us "close enough" for now at least. let me know your thoughts, if you have a moment to review. i really appreciate your continued eyes on this problem. i think if this series of changes isn't good enough, then we'll be circling back to adopting and modifying puka, but i'm really hopeful this is enough for the 99%

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