Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
198 commits
Select commit Hold shift + click to select a range
c01030c
Fix assertions with empty lists
danog Feb 18, 2025
cf4ff04
Fixes
danog Feb 18, 2025
f00bf24
Update configuration.md: Adding `--config=` cli parameter
ThomasLandauer Feb 24, 2025
18b2792
Merge pull request #11332 from ThomasLandauer/patch-1
orklah Feb 24, 2025
432992d
Merge branch '6.x'
danog Feb 25, 2025
2a2ac99
Refactor taints to use bitmaps
danog Feb 26, 2025
0dc132a
Finalize
danog Feb 26, 2025
4f8725e
Finalize
danog Feb 26, 2025
ac46aa8
Cleanup
danog Feb 26, 2025
ce1513b
Cleanup
danog Feb 27, 2025
aeab154
Cleanup
danog Feb 27, 2025
4230cf5
Simplify
danog Feb 27, 2025
4a44d55
Cleanup
danog Feb 27, 2025
fffe341
Cleanup
danog Feb 27, 2025
0d7f3c5
Cleanup
danog Feb 27, 2025
e632fba
Fix
danog Feb 27, 2025
f65e027
More cleanup
danog Feb 27, 2025
69894e9
Merge remote-tracking branch 'origin/6.x' into fix_empty_list_assertions
danog Feb 27, 2025
487feb3
Merge remote-tracking branch 'origin/6.x' into refactor_taints
danog Feb 27, 2025
6ea418c
Simplify
danog Feb 27, 2025
17d2d23
Fix
danog Feb 27, 2025
aeaf0b0
Cleanup
danog Feb 27, 2025
eceba2e
Performance refactoring
danog Feb 28, 2025
babe8b2
More detailed progress
danog Mar 1, 2025
26941e1
Merge remote-tracking branch 'origin/6.x'
danog Mar 1, 2025
990f62d
Merge branch 'master' into more_detailed_progress
danog Mar 1, 2025
9e6f458
Cleanup
danog Mar 1, 2025
38dd471
Add phase
danog Mar 1, 2025
f53ac98
Merge remote-tracking branch 'origin/master' into fix_empty_list_asse…
danog Mar 1, 2025
006c6f9
Completely remove TCallableKeyedArray
danog Mar 1, 2025
b85ef08
Finalize
danog Mar 1, 2025
501ac30
cs-fix
danog Mar 1, 2025
9d01727
fix
danog Mar 1, 2025
8c3dcc1
Cleanup
danog Mar 1, 2025
2732086
Fix
danog Mar 1, 2025
35254a0
Finalize
danog Mar 3, 2025
c899331
Cleanup
danog Mar 3, 2025
0235c91
Cleanup
danog Mar 3, 2025
0ba7380
Merge pull request #11349 from danog/more_detailed_progress
danog Mar 3, 2025
7073da1
Cleanup
danog Mar 3, 2025
580d343
Fix
danog Mar 3, 2025
d504ad6
Fixes
danog Mar 3, 2025
47dd35c
Merge remote-tracking branch 'origin/master' into fix_empty_list_asse…
danog Mar 3, 2025
9fea7f4
Fixes
danog Mar 3, 2025
470c722
cs-fix
danog Mar 3, 2025
d737814
Fixes
danog Mar 3, 2025
f2a6d9f
Fixes
danog Mar 3, 2025
682ee44
Bump upgrading
danog Mar 3, 2025
be92afa
Merge pull request #11312 from vimeo/fix_empty_list_assertions
danog Mar 3, 2025
8982e90
Merge remote-tracking branch 'origin/master' into refactor_taints
danog Mar 3, 2025
5f0d74e
Finalize refactoring
danog Mar 4, 2025
a032b3d
Finalize
danog Mar 4, 2025
eeff979
Finalize
danog Mar 4, 2025
a4f8a56
Finalize
danog Mar 4, 2025
1179930
Bump docs
danog Mar 4, 2025
b01faad
Finalize
danog Mar 4, 2025
1b83acb
Final performance fix
danog Mar 4, 2025
bf39498
Finalize
danog Mar 5, 2025
aa23279
Fixes
danog Mar 5, 2025
bda7a57
cs-fix
danog Mar 5, 2025
b513b32
Tmp
danog Mar 7, 2025
53d4113
Fix
danog Mar 7, 2025
fd5d042
fix
danog Mar 7, 2025
e04dda9
Fixes
danog Mar 10, 2025
abcfaab
Fixes
danog Mar 10, 2025
0e7c2d4
Fix
danog Mar 10, 2025
0f32350
Bump upgrading
danog Mar 10, 2025
f78967c
Fix
danog Mar 10, 2025
1cf2511
Fixes
danog Mar 10, 2025
e26e62d
Fix
danog Mar 10, 2025
399383b
Fix
danog Mar 10, 2025
89f9112
Improvement
danog Mar 10, 2025
1844ba5
Fix
danog Mar 11, 2025
f10a077
Finalize
danog Mar 11, 2025
91a1699
cs-fix
danog Mar 11, 2025
caafc3c
Revert
danog Mar 11, 2025
cd56571
Huge performance improvements for taint analysis
danog Mar 11, 2025
d8c2f85
Merge remote-tracking branch 'origin/6.x'
danog Mar 11, 2025
8fd8a6d
Merge branch '6.x'
danog Mar 14, 2025
a547fb2
Merge branch '6.x'
danog Mar 14, 2025
1d0a40f
Temp
danog Mar 14, 2025
709c533
Tmp
danog Mar 14, 2025
a5e986e
Merge branch '6.x'
danog Mar 14, 2025
5410d6d
Improve docs
danog Mar 14, 2025
cb13824
Merge branch '6.x'
danog Mar 16, 2025
a845b95
Merge branch '6.x'
danog Mar 16, 2025
0c70d4a
Bump docs
danog Mar 16, 2025
3749ca1
Merge branch '6.x'
danog Mar 16, 2025
17a3e71
Merge pull request #11361 from vimeo/6.x
danog Mar 16, 2025
6e43ce9
Fix issue with tags
danog Mar 16, 2025
354b4d4
Merge branch '6.x'
danog Mar 16, 2025
0169764
Allow concatenation between (string|int) and similar types
haas-dtv Mar 20, 2025
e3beb9a
Update psalm-baseline.xml
haas-dtv Mar 20, 2025
a780287
Merge remote-tracking branch 'origin/6.x'
danog Mar 20, 2025
196d854
Do not tag latest for beta
danog Mar 20, 2025
83dea78
Merge branch '6.x'
danog Mar 20, 2025
55eda49
Merge remote-tracking branch 'origin/6.x'
danog Mar 20, 2025
198a2f0
Add unit tests for string concatenation with other types
haas-dtv Mar 20, 2025
514e954
Merge pull request #11364 from haas-dtv/fix/11337
danog Mar 20, 2025
3b05c1e
Show progress when merging thread results
danog Mar 21, 2025
8f57c57
Merge pull request #11374 from vimeo/progress_merge
danog Mar 21, 2025
c5d7f9f
Push internal stub images as well
danog Mar 21, 2025
185ffdf
Improve
danog Mar 21, 2025
4330f8f
Improve
danog Mar 21, 2025
c05fc3a
Split stub build
danog Mar 21, 2025
260ef97
Merge branch '6.x'
danog Mar 25, 2025
fc232c4
fix
danog Mar 25, 2025
27ea071
Fix
danog Mar 25, 2025
0041745
Fixes
danog Mar 26, 2025
a4b3760
Don't remove composer
danog Mar 26, 2025
abc0b1b
Minor output tweak
danog Mar 26, 2025
379308b
Merge branch '6.x'
danog Mar 26, 2025
794c6a3
Merge branch '6.x'
danog Mar 27, 2025
0987ad1
Fix
danog Mar 27, 2025
2f8ed4d
Merge branch '6.x'
danog Mar 27, 2025
b2f3b4e
Add number of threads to progress output
danog Mar 28, 2025
0b0f648
Merge branch '6.x'
danog Mar 28, 2025
162a7ea
Merge remote-tracking branch 'origin/6.x'
danog Mar 28, 2025
1a38fd2
Merge branch '6.x'
danog Mar 31, 2025
1288d7a
Merge branch '6.x'
danog Mar 31, 2025
566c36d
Allow using normal, taint and dead code analysis together
danog Mar 31, 2025
9f3db57
Cleanup
danog Mar 31, 2025
80634b1
Cleanup
danog Apr 1, 2025
ecf88fe
Cleanup
danog Apr 1, 2025
99fab47
Cleanup
danog Apr 1, 2025
4c9bbe3
Cleanup
danog Apr 1, 2025
77068bd
fixes
danog Apr 1, 2025
b93f8c6
fixes
danog Apr 1, 2025
f23d802
fixes
danog Apr 1, 2025
542f3f2
Fixes
danog Apr 1, 2025
15e5c41
Fixes
danog Apr 1, 2025
e7d6d58
cs-fix
danog Apr 1, 2025
6f9adae
cs-fix
danog Apr 1, 2025
6f06359
Fixes
danog Apr 1, 2025
8c09879
Finalize
danog Apr 1, 2025
ee1ac48
Cleanup
danog Apr 4, 2025
a8e33b2
Fix
danog Apr 4, 2025
ccab28e
Fixes
danog Apr 4, 2025
76d7f4a
Fixes
danog Apr 4, 2025
5e164b6
Fixes
danog Apr 4, 2025
412ec04
Fixes
danog Apr 4, 2025
a7981eb
fix
danog Apr 4, 2025
97ef9fa
Fixes
danog Apr 4, 2025
5080c96
FInal fixes
danog Apr 4, 2025
bf7a130
Fix
danog Apr 4, 2025
c6b1bfa
Bump
danog Apr 4, 2025
3675b84
Merge pull request #11384 from vimeo/combined_analysis
danog Apr 4, 2025
5028292
Fix taint flow resolution progress
danog Apr 9, 2025
c65b0f0
Add debug symbols
danog Apr 9, 2025
60639b1
Always run taint analysis by default
danog Apr 21, 2025
50a49bf
Fixes
danog Apr 21, 2025
ac7ce8c
fix
danog Apr 21, 2025
c697053
Merge pull request #11399 from danog/always_run_taint_analysis
danog Apr 21, 2025
9875722
Merge branch '6.x'
danog Apr 21, 2025
18d1bc9
Tweak taint flow resolution progress
danog Apr 21, 2025
9b0b4bd
Tweak
danog Apr 21, 2025
4785514
Merge branch '6.x'
danog May 3, 2025
02b64e9
Merge branch '6.x'
danog May 4, 2025
533776c
Bump
danog May 5, 2025
c24dfbc
Merge branch '6.x'
danog May 6, 2025
8506dfc
Merge branch '6.x'
danog May 6, 2025
006d924
Use all composer autoloaders when resolving paths
danog May 6, 2025
9bcb365
Fix paratest runs with default PHP unlike all other scripts
kkmuffme May 15, 2025
7b3d945
bump
danog May 20, 2025
e581f13
Merge pull request #11441 from kkmuffme/patch-2
danog May 21, 2025
933d658
Merge branch '6.x'
danog May 21, 2025
8034a0e
Fix test
danog May 21, 2025
85908d5
Merge branch '6.x'
danog May 21, 2025
00137b6
Improve
danog May 22, 2025
6d671f6
Merge branch '6.x'
danog May 23, 2025
7037d27
Merge remote-tracking branch 'origin/6.x'
danog May 26, 2025
a26475c
Cleanup baseline
danog May 26, 2025
ad4b7b6
Merge branch '6.x'
danog May 29, 2025
6670889
Sort specializations
danog Jun 1, 2025
6f86339
Avoid tainting issues with first-class callables
danog Jun 30, 2025
950074c
Merge branch '6.x'
danog Jun 30, 2025
cd7da86
Merge branch '6.x'
danog Jul 4, 2025
6719100
Merge branch '6.x'
danog Jul 8, 2025
6f60963
Merge branch '6.x'
danog Jul 8, 2025
24cb508
Merge branch '6.x'
danog Jul 14, 2025
cdceda0
Bump schema
danog Jul 14, 2025
e097491
Merge remote-tracking branch 'origin/6.x'
danog Dec 4, 2025
27ba76f
Add new link taint type
danog Dec 4, 2025
0df8d68
Revert, already covered by ssrf
danog Dec 4, 2025
11a4015
Merge branch '6.x'
danog Dec 8, 2025
e66308f
Merge branch '6.x'
danog Dec 10, 2025
0d998c1
Merge branch '6.x'
danog Dec 23, 2025
10d1dd5
Fixup tests
danog Dec 23, 2025
1b20d9c
Merge branch '6.x'
danog Dec 23, 2025
b09282f
Make sure conditional taints aren't registered directly
danog Dec 23, 2025
047d5cc
Fix conditional taints
danog Dec 23, 2025
df97201
Fixup order
danog Dec 23, 2025
e66ca99
Merge pull request #11628 from danog/fix_conditional_taints
danog Dec 23, 2025
b8ffc19
Ensure taints have no holes
danog Dec 23, 2025
f69d1a8
Merge remote-tracking branch 'origin/6.x'
danog Dec 23, 2025
353cb38
Skip virtual nodes during manipulation
danog Dec 23, 2025
6008da5
Bump
danog Dec 23, 2025
671ce3a
cs-fix
danog Dec 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,63 @@
# Upgrading from Psalm 6 to Psalm 7

## Changed

- [BC] Taints are now *internally* represented by a bitmap (an integer), instead of an array of strings. Users can still use the usual string taint identifiers (including custom ones, which will be automatically registered by Psalm), but internally, the type of `Psalm\Type\TaintKind` taint types is now an integer.

- [BC] The maximum number of usable taint *types* (including both native taints and custom taints) is now equal to 32 on 32-bit systems and 64 on 64-bit systems: this should be enough for the vast majority of usecases, if more taint types are needed, consider merging some taint types or using some native taint types.

- [BC] `Psalm\Plugin\EventHandler\AddTaintsInterface::addTaints` and `Psalm\Plugin\EventHandler\RemoveTaintsInterface::removeTaints` now must return an integer taint instead of an array of strings (see the new [taint documentation](https://psalm.dev/docs/security_analysis/custom_taint_sources/) for more info).

- [BC] The type of the `$taints` parameter of `Psalm\Codebase::addTaintSource` and `Psalm\Codebase::addTaintSink` was changed to an integer

- [BC] Type of property `Psalm\Storage\FunctionLikeParameter::$sinks` changed from `array|null` to `int`

- [BC] Type of property `Psalm\Storage\FunctionLikeStorage::$taint_source_types` changed from `array` to `int`

- [BC] Type of property `Psalm\Storage\FunctionLikeStorage::$added_taints` changed from `array` to `int`

- [BC] Type of property `Psalm\Storage\FunctionLikeStorage::$removed_taints` changed from `array` to `int`

- [BC] The `startScanningFiles`, `startAnalyzingFiles`, `startAlteringFiles` of `Psalm\Progress\Progress` and subclasses were removed and replaced with a new `startPhase` method, taking a `Psalm\Progress\Phase` enum case.

- [BC] The `start` method was removed, use `expand`, instead; the progress is reset to 0 when changing the current phase.

- [BC] Method `doesTerminalSupportUtf8` of class `Psalm\Progress\Progress` became final

- [BC] Method debug() of class Psalm\Progress\Progress changed from concrete to abstract

- [BC] Method alterFileDone() of class Psalm\Progress\Progress changed from concrete to abstract

- [BC] Method expand() of class Psalm\Progress\Progress changed from concrete to abstract

- [BC] Method taskDone() of class Psalm\Progress\Progress changed from concrete to abstract

- [BC] Method finish() of class Psalm\Progress\Progress changed from concrete to abstract

- [BC] The return type of Psalm\Type::getListAtomic() changed from Psalm\Type\Atomic\TKeyedArray to the non-covariant Psalm\Type\Atomic\TKeyedArray|Psalm\Type\Atomic\TArray

- [BC] The return type of Psalm\Type::getListAtomic() changed from Psalm\Type\Atomic\TKeyedArray to Psalm\Type\Atomic\TKeyedArray|Psalm\Type\Atomic\TArray

- [BC] The return type of Psalm\Type::getNonEmptyListAtomic() changed from Psalm\Type\Atomic\TKeyedArray to the non-covariant Psalm\Type\Atomic\TKeyedArray|Psalm\Type\Atomic\TArray

- [BC] The return type of Psalm\Type::getNonEmptyListAtomic() changed from Psalm\Type\Atomic\TKeyedArray to Psalm\Type\Atomic\TKeyedArray|Psalm\Type\Atomic\TArray

- [BC] Class Psalm\Type\Atomic\TKeyedArray became final

- [BC] Class Psalm\Type\Atomic\TKeyedArray can only be created using the new `make` or `makeCallable` factory methods, the constructor was rendered private.

- [BC] Class Psalm\Type\Atomic\TCallableKeyedArray has been deleted, and replaced with a new `is_callable` flag in Psalm\Type\Atomic\TKeyedArray

- [BC] Class Psalm\Type\Atomic\TCallableInterface has been deleted, use `\Psalm\Type\Atomic::isCallableType()` instead

## Removed

- [BC] Constant Psalm\Type\Atomic\TKeyedArray::NAME_ARRAY was removed

- [BC] Constant Psalm\Type\Atomic\TKeyedArray::NAME_LIST was removed

- [BC] Psalm\Type\Atomic\TKeyedArray#__construct() was made private

# Upgrading from Psalm 5 to Psalm 6
## Changed

Expand Down
3 changes: 2 additions & 1 deletion bin/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ RUN set -eux; \
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
# https://github.com/docker-library/php/issues/272
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -g"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"

Expand Down Expand Up @@ -185,6 +185,7 @@ RUN set -eux; \
php --version

COPY bin/docker/docker-php-* /usr/local/bin/
ADD https://raw.githubusercontent.com/php/php-src/refs/heads/PHP-8.4/.gdbinit /root/.gdbinit

# This line invalidates cache when master branch changes
ADD https://github.com/vimeo/psalm/commits/master.atom /dev/null
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
"lint": "@php parallel-lint ./src ./tests",
"phpunit": [
"Composer\\Config::disableProcessTimeout",
"paratest -f --runner=WrapperRunner"
"@php paratest -f --runner=WrapperRunner"
],
"phpunit-std": [
"Composer\\Config::disableProcessTimeout",
Expand Down
2 changes: 1 addition & 1 deletion config.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
<xs:attribute name="skipChecksOnUnresolvableIncludes" type="xs:boolean" default="false" />
<xs:attribute name="sealAllMethods" type="xs:boolean" default="true" />
<xs:attribute name="sealAllProperties" type="xs:boolean" default="true" />
<xs:attribute name="runTaintAnalysis" type="xs:boolean" default="false" />
<xs:attribute name="runTaintAnalysis" type="xs:boolean" default="true" />
<xs:attribute name="usePhpStormMetaPath" type="xs:boolean" default="true" />
<xs:attribute name="allowInternalNamedArgumentCalls" type="xs:boolean" default="true" />
<xs:attribute name="allowNamedArgumentCalls" type="xs:boolean" default="true" />
Expand Down
106 changes: 53 additions & 53 deletions dictionaries/InternalTaintSinkMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,59 @@
// This maps internal function names to sink types that we don’t want to end up there

/**
* @var non-empty-array<string, non-empty-list<list<TaintKind::*>>>
* @var non-empty-array<string, non-empty-list<int-mask-of<TaintKind::*>>>
*/
return [
'exec' => [['shell']],
'create_function' => [[], ['eval']],
'file_get_contents' => [['file']],
'file_put_contents' => [['file']],
'fopen' => [['file']],
'unlink' => [['file']],
'copy' => [['file'], ['file']],
'file' => [['file']],
'link' => [['file'], ['file']],
'mkdir' => [['file']],
'move_uploaded_file' => [['file'], ['file']],
'parse_ini_file' => [['file']],
'chown' => [['file']],
'lchown' => [['file']],
'readfile' => [['file']],
'rename' => [['file'], ['file']],
'rmdir' => [['file']],
'header' => [['header']],
'symlink' => [['file']],
'tempnam' => [['file']],
'igbinary_unserialize' => [['unserialize']],
'ldap_search' => [[], ['ldap'], ['ldap']],
'mysqli_query' => [[], ['sql']],
'mysqli::query' => [['sql']],
'mysqli_real_query' => [[], ['sql']],
'mysqli::real_query' => [['sql']],
'mysqli_multi_query' => [[], ['sql']],
'mysqli::multi_query' => [['sql']],
'mysqli_prepare' => [[], ['sql']],
'mysqli::prepare' => [['sql']],
'mysqli_stmt::__construct' => [[], ['sql']],
'mysqli_stmt_prepare' => [[], ['sql']],
'mysqli_stmt::prepare' => [['sql']],
'passthru' => [['shell']],
'pcntl_exec' => [['shell']],
'pg_exec' => [[], ['sql']],
'pg_prepare' => [[], [], ['sql']],
'pg_put_line' => [[], ['sql']],
'pg_query' => [[], ['sql']],
'pg_query_params' => [[], ['sql']],
'pg_send_prepare' => [[], [], ['sql']],
'pg_send_query' => [[], ['sql']],
'pg_send_query_params' => [[], ['sql'], []],
'setcookie' => [['cookie'], ['cookie']],
'shell_exec' => [['shell']],
'system' => [['shell']],
'unserialize' => [['unserialize']],
'popen' => [['shell']],
'proc_open' => [['shell']],
'curl_init' => [['ssrf']],
'curl_setopt' => [[], [], ['ssrf']],
'getimagesize' => [['ssrf']],
'exec' => [TaintKind::INPUT_SHELL],
'create_function' => [0, TaintKind::INPUT_EVAL],
'file_get_contents' => [TaintKind::INPUT_FILE|TaintKind::INPUT_SSRF],
'file_put_contents' => [TaintKind::INPUT_FILE],
'fopen' => [TaintKind::INPUT_FILE],
'unlink' => [TaintKind::INPUT_FILE],
'copy' => [TaintKind::INPUT_FILE|TaintKind::INPUT_SSRF, TaintKind::INPUT_FILE],
'file' => [TaintKind::INPUT_FILE],
'link' => [TaintKind::INPUT_FILE, TaintKind::INPUT_FILE],
'mkdir' => [TaintKind::INPUT_FILE],
'move_uploaded_file' => [TaintKind::INPUT_FILE, TaintKind::INPUT_FILE],
'parse_ini_file' => [TaintKind::INPUT_FILE],
'chown' => [TaintKind::INPUT_FILE],
'lchown' => [TaintKind::INPUT_FILE],
'readfile' => [TaintKind::INPUT_FILE],
'rename' => [TaintKind::INPUT_FILE, TaintKind::INPUT_FILE],
'rmdir' => [TaintKind::INPUT_FILE],
'header' => [TaintKind::INPUT_HEADER],
'symlink' => [TaintKind::INPUT_FILE],
'tempnam' => [TaintKind::INPUT_FILE],
'igbinary_unserialize' => [TaintKind::INPUT_UNSERIALIZE],
'ldap_search' => [0, TaintKind::INPUT_LDAP, TaintKind::INPUT_LDAP],
'mysqli_query' => [0, TaintKind::INPUT_SQL],
'mysqli::query' => [TaintKind::INPUT_SQL],
'mysqli_real_query' => [0, TaintKind::INPUT_SQL],
'mysqli::real_query' => [TaintKind::INPUT_SQL],
'mysqli_multi_query' => [0, TaintKind::INPUT_SQL],
'mysqli::multi_query' => [TaintKind::INPUT_SQL],
'mysqli_prepare' => [0, TaintKind::INPUT_SQL],
'mysqli::prepare' => [TaintKind::INPUT_SQL],
'mysqli_stmt::__construct' => [0, TaintKind::INPUT_SQL],
'mysqli_stmt_prepare' => [0, TaintKind::INPUT_SQL],
'mysqli_stmt::prepare' => [TaintKind::INPUT_SQL],
'passthru' => [TaintKind::INPUT_SHELL],
'pcntl_exec' => [TaintKind::INPUT_SHELL],
'pg_exec' => [0, TaintKind::INPUT_SQL],
'pg_prepare' => [0, 0, TaintKind::INPUT_SQL],
'pg_put_line' => [0, TaintKind::INPUT_SQL],
'pg_query' => [0, TaintKind::INPUT_SQL],
'pg_query_params' => [0, TaintKind::INPUT_SQL],
'pg_send_prepare' => [0, 0, TaintKind::INPUT_SQL],
'pg_send_query' => [0, TaintKind::INPUT_SQL],
'pg_send_query_params' => [0, TaintKind::INPUT_SQL, 0],
'setcookie' => [TaintKind::INPUT_COOKIE, TaintKind::INPUT_COOKIE],
'shell_exec' => [TaintKind::INPUT_SHELL],
'system' => [TaintKind::INPUT_SHELL],
'unserialize' => [TaintKind::INPUT_UNSERIALIZE],
'popen' => [TaintKind::INPUT_SHELL],
'proc_open' => [TaintKind::INPUT_SHELL],
'curl_init' => [TaintKind::INPUT_SSRF],
'curl_setopt' => [0, 0, TaintKind::INPUT_SSRF],
'getimagesize' => [TaintKind::INPUT_SSRF],
];
4 changes: 3 additions & 1 deletion docs/running_psalm/command_line_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ Currently, Shepherd tracks type coverage (the percentage of types Psalm can infe

## Running Psalm faster

Psalm has a couple of command-line options that will result in faster builds:
To run Psalm up to 50% faster, use the [official docker image](https://psalm.dev/docs/running_psalm/installation/#docker-image).

Psalm also has a couple of command-line options that will result in faster builds:

- `--threads=[n]` to run Psalm’s analysis in a number of threads
- `--diff` which only checks files you’ve updated since the last run (and their dependents).
Expand Down
8 changes: 7 additions & 1 deletion docs/running_psalm/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ Configuration file may be split into several files using [XInclude](https://www.
</projectFiles>
```

## Different configuration file

You can also create a different configuration file, then run Psalm with:
```bash
vendor/bin/psalm --config=other-psalm-config.xml
```

## Optional &lt;psalm /&gt; attributes

Expand Down Expand Up @@ -393,7 +399,7 @@ When `true`, Psalm will treat all classes as if they had sealed properties, mean
>
```

When `true`, Psalm will run [Taint Analysis](../security_analysis/index.md) on your codebase. This config is the same as if you were running Psalm with `--taint-analysis`.
When `true` (the default), Psalm will run [Taint Analysis](../security_analysis/index.md) on your codebase. This config is the same as if you were running Psalm with `--taint-analysis`.

#### reportInfo

Expand Down
2 changes: 1 addition & 1 deletion docs/running_psalm/issues/TaintedFile.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ It could range from:
```php
<?php

$content = file_get_contents($_GET['header']);
$content = fopen($_GET['header'], "r");
echo $content;
```

Expand Down
2 changes: 1 addition & 1 deletion docs/running_psalm/plugins/plugins_type_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ More complex types can be constructed as follows. The following represents an as

``` php
new Union([
new TKeyedArray([
TKeyedArray::make([
'key_1' => new Union([new TString()]),
'key_2' => new Union([new TInt()]),
'key_3' => new Union([new TBool()])])]);
Expand Down
55 changes: 48 additions & 7 deletions docs/security_analysis/custom_taint_sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ You can define your own taint sources with an annotation or a plugin.

You can use the annotation `@psalm-taint-source <taint-type>` to indicate a function or method that provides user input.

In the below example the `input` taint type is specified as a standin for input taints as defined in [Psalm\Type\TaintKindGroup](https://github.com/vimeo/psalm/blob/master/src/Psalm/Type/TaintKindGroup.php).
In the below example the `input` taint type is specified as a standin for input taints as defined in [Psalm\Type\TaintKind](https://github.com/vimeo/psalm/blob/master/src/Psalm/Type/TaintKind.php).

```php
<?php
Expand All @@ -26,29 +26,70 @@ For example this plugin treats all variables named `$bad_data` as taint sources.
namespace Psalm\Example\Plugin;

use PhpParser\Node\Expr\Variable;
use Psalm\Codebase;
use Psalm\Plugin\EventHandler\AddTaintsInterface;
use Psalm\Plugin\EventHandler\Event\AddRemoveTaintsEvent;
use Psalm\Type\TaintKindGroup;
use Psalm\Type\TaintKind;

/**
* Add input taints to all variables named 'bad_data'
* Add input taints to all variables named 'bad_data' or 'even_badder_data'.
*
* RemoveTaintsInterface is also available to remove taints.
*/
class TaintBadDataPlugin implements AddTaintsInterface
{
private static int $myCustomTaint;
private static int $myCustomTaintAlias;
/**
* Must be called by the PluginEntryPointInterface (__invoke) of your plugin.
*/
public static function init(Codebase $codebase): void
{
// Register a new custom taint
// The taint name may be used in @psalm-taint-* annotations in the code.
self::$myCustomTaint = $codebase->getOrRegisterTaint("my_custom_taint");

// Register a taint alias that combines multiple pre-registered taint types
// Taint alias names may be used in @psalm-taint-* annotations in the code.
self::$myCustomTaintAlias = $codebase->registerTaintAlias(
"my_custom_taint_alias",
self::$myCustomTaint | TaintKind::ALL_INPUT
);
}

/**
* Called to see what taints should be added
*
* @return list<string>
* @return int A bitmap of taint from the IDs
*/
public static function addTaints(AddRemoveTaintsEvent $event): array
public static function addTaints(AddRemoveTaintsEvent $event): int
{
$expr = $event->getExpr();

if ($expr instanceof Variable && $expr->name === 'bad_data') {
return TaintKindGroup::ALL_INPUT;
return TaintKind::ALL_INPUT;
}

if ($expr instanceof Variable && $expr->name === 'even_badder_data') {
return self::$myCustomTaint;
}

if ($expr instanceof Variable && $expr->name === 'even_badder_data_2') {
return self::$myCustomTaintAlias;
}

if ($expr instanceof Variable && $expr->name === 'secret_even_badder_data_3') {
// Combine taints using |
return self::$myCustomTaintAlias | USER_SECRET;
}

if ($expr instanceof Variable && $expr->name === 'bad_data_but_ok_cookie') {
// Remove taints using & and ~ to negate a taint (group)
return self::$myCustomTaintAlias & ~TaintKind::INPUT_COOKIE;
}

return [];
// No taints
return 0;
}
}
```
2 changes: 1 addition & 1 deletion docs/security_analysis/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Psalm can attempt to find connections between user-controlled input (like `$_GET['name']`) and places that we don’t want unescaped user-controlled input to end up (like `echo "<h1>$name</h1>"` by looking at the ways that data flows through your application (via assignments, function/method calls and array/property access).

You can enable this mode with the `--taint-analysis` command line flag. When taint analysis is enabled, no other analysis is performed. To [ensure comprehensive results](https://github.com/vimeo/psalm/issues/6156), Psalm should be run normally prior to taint analysis, and any errors should be fixed.
You can enable this mode with the `--taint-analysis` command line flag.

Tainted input is anything that can be controlled, wholly or in part, by a user of your application. In taint analysis, tainted input is called a _taint source_.

Expand Down
1 change: 1 addition & 0 deletions examples/TemplateChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ private function checkWithViewClass(Context $context, array $stmts): void
$statements_source = new StatementsAnalyzer(
$view_method_analyzer,
new NodeDataProvider(),
false,
);

$statements_source->analyze($pseudo_method_stmts, $context);
Expand Down
Loading
Loading