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

Support for flags & options protection #908

Merged
merged 35 commits into from Jun 11, 2023

Conversation

ericcornelissen
Copy link
Owner

@ericcornelissen ericcornelissen commented May 30, 2023

Closes #452
Relates to #911

Summary

Add support for protection against flag/option injection through a new flagProtection option. The option will extend escaping and quoting functionality with extra protection against flag/option injection. That is, it aims to protect against an attacker, for example, providing an attack string such as --verbose to gain extra information about the target system.

It should be noted that it is considered to provide 100% flag protection in practice. The reason for this is that what is considered a flag/option is specific to the implementation of the target software. This is as opposed to other escaping done by this software, which is shell specific. The name was chosen to reflect this, it only provides "protection" but isn't perfect. The protection only protects against common flag/option strings on the given platform.

Flag protection is disabled by default as enabling it is considered a breaking change.

Update `index.{d.ts,js}` with updated documentation and types for
supporting the "escaping" of flags and options. Because it won't be
really "escaping" (i.e. "escaping" `--foobar` as `\-\-foobar` is
ineffective) the option is instead named "flagProtection", because
it protects against flag(/option) injection.

The default value for this option will be `false`. First and foremost
because `true` would border on being a breaking change from my point
of view. Secondly (and relatedly), it's not obvious that this is always
necessary. For example, per `docs/tips.md`, using the "--" option would
be preferable. That being said, defaulting to `true` should be
reconsidered in a future major version release as a "secure by default"
consideration.

Some changes to the tests are included as a way to show what expected
is. These tests are created at the integration level following the fact
that so far there's only API design (implementation is unknown, so unit
tests are not yet possible to create; end-to-end is less applicable
given their current nature, though not out of the question for the
future). Note that, lacking an update to the library implementation,
these new tests are currently expected to fail (consider this a TDD
commit :)).

Lastly, the `shescapeOptions` arbitrary  has been updated in accordance
with the changes to the API.
@ericcornelissen ericcornelissen added the enhancement New feature or request label May 30, 2023
@github-actions github-actions bot added the test Relates to testing label May 30, 2023
@ericcornelissen ericcornelissen marked this pull request as draft May 30, 2023 20:11
@codecov
Copy link

codecov bot commented May 30, 2023

Codecov Report

Merging #908 (144a025) into main (55abe54) will not change coverage.
The diff coverage is 100.00%.

@@            Coverage Diff            @@
##              main      #908   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            5         5           
  Lines          470       513   +43     
=========================================
+ Hits           470       513   +43     
Flag Coverage Δ
integration-MacOS 98.44% <100.00%> (+0.14%) ⬆️
integration-Ubuntu 98.44% <100.00%> (+0.14%) ⬆️
integration-Windows 98.44% <100.00%> (+0.14%) ⬆️
unit 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
index.js 100.00% <100.00%> (ø)
src/main.js 100.00% <100.00%> (ø)

There seems to be no need to implement the execution of the function at
the level of the platform-specific implementation as it would be the
same for every implementation.
Add fixtures covering Windows functionality.

Also, add a sneaky scenario that's currently unhandled. In the first and
last added fixtures the start of the flag is after a character that
Shescape removes when escaping. This isn't handled by the current
implementation so these tests is expected to fail.
src/main.js Outdated Show resolved Hide resolved
Update the `getQuoteFunction` interface to return a pair of functions, 1
to escape and 1 to quote, instead of a single function. Update all
implementations and corresponding tests in accordance with this
interface change.

The reason for this can be found in the changes to `main.js`, where, if
flag protection is enabled, the process is:
1. Escape the arg
2. Apply flag protection to the arg
3. Quote the arg
Which is the only valid process.

This iterates on the changes in [1], where `escapeForQuoted` functions
were inlined into to `quoteArg` functions. Instead of reverting this,
this keeps the quoting related functionality scoped to the
`getQuoteFunction` implementation. This keeps `getEscapeFunction`
simpler and also avoids the invalid `options` value
`{interpolation:true,quoted:true}`.

--
1. abaf4be
@ericcornelissen ericcornelissen marked this pull request as ready for review June 7, 2023 19:50
It seems to be required to perform flag protection both before and after
escaping. This is because:
- Before: escaping might escape flag-relevant characters (most likely
  when `interpolation:true`, as evidenced by the failing integration
  tests on Windows prior to this change).
- After: escaping might strip leading characters which could result in
  flag-relevant characters appearing at the start of the string.
Revert the previous commit and instead test what happens if the
problematic escape is removed for PowerShell. This will fail the unit
tests (and thus most of the CI), but fuzzing should still run in the CI
which is what I'm most interested in here.

For reference, see [1] where the escape being removed here was
originally added.

--
1. fcba4ee
Switch from a platform wide `stripFlagPrefix` fn to a shell-specific one
because the implementation for PowerShell appears to have to be unique.
This is somewhat unfortunate as the protection mechanism shouldn't be
shell specific since flags are not something determined by the shell but
rather by the program, which is more of a system-level thing (or,
arguably, a global thing).

Further refactoring could be explored to see if the idea that flag
protection is system wide can be re-encoded in the source code.

Reverts the part of [1] that wasn't itself a revert of an earlier commit

--
1. 875127e
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jun 11, 2023
@ericcornelissen ericcornelissen added the pending This cannot be worked on yet label Jun 11, 2023
@ericcornelissen ericcornelissen removed the pending This cannot be worked on yet label Jun 11, 2023
@ericcornelissen ericcornelissen merged commit 6fe552d into main Jun 11, 2023
63 checks passed
@ericcornelissen ericcornelissen deleted the 452-escape-flags-and-options branch June 11, 2023 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request test Relates to testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support escaping flags & options
1 participant