vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.54k stars 659 forks source link

Tainting function input arguments #9419

Open chaosInTheWild opened 1 year ago

chaosInTheWild commented 1 year ago

Given a function that takes in an object and uses one of its attributes in a taint sink, is there any way to set it as a taint source assuming it contains parameters that are user-supplied?

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/56178218a0 ```php id; } } /** * @return void */ function test_func( WorkerClass $object): void { $post = exec($object["id"]); } ``` ``` Psalm output (using commit 1a2909e): No issues! ```
weirdan commented 1 year ago

Normally you would do it like this: https://psalm.dev/r/8d9ef2c87f

But Psalm doesn't seem to read taint taints on offsetGet() when you access it via [] operator.

For reference, the following should work (but doesn't): https://psalm.dev/r/615cfedf69

Your original snippet had too many problems to be used with taint analysis.

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/8d9ef2c87f ```php id; } } function test_func( WorkerClass $object): void { $post = exec($object->getId()); } ``` ``` Psalm output (using commit 1a2909e): ERROR: TaintedShell - 11:18 - Detected tainted shell code ```
https://psalm.dev/r/615cfedf69 ```php */ class WorkerClass implements ArrayAccess { public string $id = "example"; /** @psalm-taint-source input */ public function offsetGet($offset): string { return $this->id; } public function offsetSet($offset, $value): void { throw new RuntimeException; } public function offsetUnset($offset): void { throw new RuntimeException; } public function offsetExists($offset): bool { return true; } } function test_func( WorkerClass $object): void { $post = exec($object['id']); } ``` ``` Psalm output (using commit 1a2909e): No issues! ```
psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/615cfedf69 ```php */ class WorkerClass implements ArrayAccess { public string $id = "example"; /** @psalm-taint-source input */ public function offsetGet($offset): string { return $this->id; } public function offsetSet($offset, $value): void { throw new RuntimeException; } public function offsetUnset($offset): void { throw new RuntimeException; } public function offsetExists($offset): bool { return true; } } function test_func( WorkerClass $object): void { $post = exec($object['id']); } ``` ``` Psalm output (using commit 1a2909e): No issues! ```
weirdan commented 1 year ago

Is there any way to make Psalm detect the taint in this case?

Not yet, thus the enhancement label

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/615cfedf69 ```php */ class WorkerClass implements ArrayAccess { public string $id = "example"; /** @psalm-taint-source input */ public function offsetGet($offset): string { return $this->id; } public function offsetSet($offset, $value): void { throw new RuntimeException; } public function offsetUnset($offset): void { throw new RuntimeException; } public function offsetExists($offset): bool { return true; } } function test_func( WorkerClass $object): void { $post = exec($object['id']); } ``` ``` Psalm output (using commit 3af9ccd): No issues! ```