Skip to content

feat: analyze expressions for safety#127

Merged
woodruffw merged 8 commits into
mainfrom
ww/safe-expressions
Nov 7, 2024
Merged

feat: analyze expressions for safety#127
woodruffw merged 8 commits into
mainfrom
ww/safe-expressions

Conversation

@woodruffw
Copy link
Copy Markdown
Member

@woodruffw woodruffw commented Nov 5, 2024

WIP, needs tests.

This will improve template-injection's precision by allowing it to filter expressions that are "safe," i.e. can't produce arbitrary input-derived code regardless of how they're executed.

For now, as "safe" expression is defined as:

  1. Any primitive (null, number, string, etc.)
  2. !{expr}
  3. {expr} == {expr} and {expr} != {expr}
  4. Any other binary expression where both the LHS and RHS are themselves safe per cases 1-3

Notably, this means that some expressions that contain code or can be evaluated to code will be considered safe, since that code will effectively be static within those expressions and not derived from user input (i.e. context accesses).

@woodruffw woodruffw added the enhancement New feature or request label Nov 5, 2024
@woodruffw woodruffw self-assigned this Nov 5, 2024
@carlocab
Copy link
Copy Markdown

carlocab commented Nov 5, 2024

For now, as "safe" expression is defined as:

  1. Any primitive (null, number, string, etc.)

Wait, aren't strings unsafe? Or am I misunderstanding what you mean by a primitive string here?

@woodruffw
Copy link
Copy Markdown
Member Author

Wait, aren't strings unsafe? Or am I misunderstanding what you mean by a primitive string here?

I mean something like this:

${{ 'foo' }}

That will expand to foo in whatever context it appears in, which means it might be code. But it isn't attacker injected code, since it's a literal string defined in the workflow itself and not in a context.

In other words, this PR removes positives like the following:

some-command ${{ some.condition && '--some-arg' || '' }}

...since some.condition influences the expansion, but the expansion itself is defined entirely by non-attacker controlled strings.

I could be convinced that this is a bad idea however, and instead consider string literals unsafe 🙂

should be the actual website, not just the repo
@carlocab
Copy link
Copy Markdown

carlocab commented Nov 5, 2024

I could be convinced that this is a bad idea however, and instead consider string literals unsafe 🙂

TBH I think erring on the side of false positives to minimize the possibility of false negatives at this stage is the better move. If you're certain that this doesn't increase the likelihood of false negatives, then it should be fine -- but I'd suspect one would want a large corpus of test data available to ensure this first.

@woodruffw
Copy link
Copy Markdown
Member Author

If you're certain that this doesn't increase the likelihood of false negatives, then it should be fine -- but I'd suspect one would want a large corpus of test data available to ensure this first.

I think it'll be fine, but yeah, I'll be adding a lot of tests to support this.

(There's a fine line here, but template-injection is specifically intended to catch injections of attacker-controlled input, not all possible ways an attacker can influence an expression. The latter is potentially a good separate audit to have.)

@woodruffw woodruffw merged commit fb8b696 into main Nov 7, 2024
@woodruffw woodruffw deleted the ww/safe-expressions branch November 7, 2024 04:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants