{"id":15282779,"url":"https://github.com/wikimedia/mediawiki-tools-phan-securitycheckplugin","last_synced_at":"2025-04-05T19:13:57.329Z","repository":{"id":57080688,"uuid":"109834832","full_name":"wikimedia/mediawiki-tools-phan-SecurityCheckPlugin","owner":"wikimedia","description":"Mirror of https://gerrit.wikimedia.org/g/mediawiki/tools/phan/SecurityCheckPlugin See https://www.mediawiki.org/wiki/Developer_access for contributing","archived":false,"fork":false,"pushed_at":"2025-03-07T20:59:20.000Z","size":2781,"stargazers_count":25,"open_issues_count":0,"forks_count":4,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-05T19:13:32.990Z","etag":null,"topics":["phan","security-audit","static-analysis","taint-analysis"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wikimedia.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-07T12:47:28.000Z","updated_at":"2025-04-04T04:51:14.000Z","dependencies_parsed_at":"2024-02-02T02:32:04.006Z","dependency_job_id":"799704aa-9efe-4dd0-9cae-4a147b358e12","html_url":"https://github.com/wikimedia/mediawiki-tools-phan-SecurityCheckPlugin","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wikimedia%2Fmediawiki-tools-phan-SecurityCheckPlugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wikimedia%2Fmediawiki-tools-phan-SecurityCheckPlugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wikimedia%2Fmediawiki-tools-phan-SecurityCheckPlugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wikimedia%2Fmediawiki-tools-phan-SecurityCheckPlugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wikimedia","download_url":"https://codeload.github.com/wikimedia/mediawiki-tools-phan-SecurityCheckPlugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247386266,"owners_count":20930619,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["phan","security-audit","static-analysis","taint-analysis"],"created_at":"2024-09-30T14:39:52.846Z","updated_at":"2025-04-05T19:13:57.306Z","avatar_url":"https://github.com/wikimedia.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Phan Security Check Plugin\n===============================\n\nThis is a plugin to [Phan] to try and detect security issues\n(such as [XSS]). It keeps track of any time a user can modify\na variable, and checks to see that such variables are\nescaped before being output as html or used as an sql query, etc.\n\nIt supports generic PHP projects, and it also has a dedicated mode\nfor MediaWiki code (analyzes hooks, HTMLForms and Database methods).\n\nA [web demo] is available.\n\nUsage\n-----\n\n### Install\n\n    $ composer require --dev mediawiki/phan-taint-check-plugin\n\n### Usage\nThe plugin can be used in both \"manual\" and \"standalone\" mode. The former is the best\nchoice if your project is already running phan, and almost no configuration is needed.\nThe latter should only be used if you don't want to add phan to your project, and is not\nsupported for MediaWiki-related code. For more information about Wikimedia's use of this\nplugin see https://www.mediawiki.org/wiki/Phan-taint-check-plugin.\n\n#### Manual\nYou simply have to add taint-check to the `plugins` section of your phan config. Assuming\nthat taint-check is in the standard vendor location, e.g.\n` $seccheckPath = 'vendor/mediawiki/phan-taint-check-plugin/';`, the file to include is\n`\"$seccheckPath/GenericSecurityCheckPlugin.php\"` for a generic project, and\n`\"$seccheckPath/MediaWikiSecurityCheckPlugin.php\"` for a MediaWiki project.\n\nAlso, make sure that quick mode is disabled, or the plugin won't work:\n```php\n   'quick_mode' =\u003e false\n```\n\nYou should also add `SecurityCheck-LikelyFalsePositive` and\n`SecurityCheck-PHPSerializeInjection` to `suppress_issue_types` (the latter\nhas a high rate of false positives).\n\nThen run phan as you normally would:\n\n    $ vendor/bin/phan -d . --long-progress-bar\n\nRunning phan with `--analyze-twice` will catch additional security issues that\nmight go unnoticed in the normal analysis phase. A known limitation of this is that\nthe same issue might be reported more than once with different caused-by lines.\n\n#### Standalone\nYou can run taint-check via:\n\n    $ ./vendor/bin/seccheck\n\nYou might want to add a composer script alias for that:\n\n```json\n  \"scripts\": {\n     \"seccheck\": \"seccheck\"\n  }\n```\n\nNote that false positives are disabled by default.\n\n\nPlugin output\n-------------\n\nThe plugin will output various issue types depending on what it\ndetects. The issue types it outputs are:\n\n* `SecurityCheck-XSS`\n* `SecurityCheck-SQLInjection`\n* `SecurityCheck-ShellInjection`\n* `SecurityCheck-PHPSerializeInjection` - For when someone does `unserialize( $_GET['d'] );`\n  This issue type seems to have a high false positive rate currently.\n* `SecurityCheck-CUSTOM1` - To allow people to have custom taint types\n* `SecurityCheck-CUSTOM2` - ditto\n* `SecurityCheck-DoubleEscaped` - Detecting that HTML is being double escaped\n* `SecurityCheck-RCE` - Remote code execution, e.g. `eval( $_GET['foo'] )`\n* `SecurityCheck-PathTraversal` - Path traversal, e.g. `require $_GET['foo']`\n* `SecurityCheck-ReDoS` - Regular expression denial of service (ReDoS), e.g. `preg_match( $_GET['foo'], 'foo')`\n* `SecurityCheck-LikelyFalsePositive` - A potential issue, but probably not.\n  Mostly happens when the plugin gets confused.\n\nThe severity field is usually marked as `Issue::SEVERITY_NORMAL (5)`. False\npositives get `Issue::SEVERITY_LOW (0)`. Issues that may result in server\ncompromise (as opposed to just end user compromise) such as shell or sql\ninjection are marked as `Issue::SEVERITY_CRITICAL (10)`.\nSerializationInjection would normally be \"critical\" but its currently denoted\nas a severity of NORMAL because the check seems to have a high false positive\nrate at the moment.\n\nYou can use the `-y` command line option of Phan to filter by severity.\n\nHow to avoid false positives\n----------------------------\n\nIf you need to suppress a false positive, you can put `@suppress NAME-OF-WARNING`\nin the docblock for a function/method. Alternatively, you can use other types of\nsuppression, like `@phan-suppress-next-line`. See phan's readme for a complete\nlist.\nThe `@param-taint` and `@return-taint` (see \"Customizing\" section) are also very useful\nwith dealing with false positives.\n\nNote that the plugin will report possible XSS vulnerabilities in CLI context. To avoid them,\nyou can suppress `SecurityCheck-XSS` file-wide with `@phan-file-suppress` in CLI scripts, or\nfor the whole application (using the `suppress_issue_types` config option) if the application only\nconsists of CLI scripts. Alternatively, if all outputting happens from an internal function, you\ncan use `@param-taint` as follows:\n```php\n  /**\n   * @param-taint $stuffToPrint none\n   */\n  public function printMyStuff( string $stuffToPrint ) {\n    echo $stuffToPrint;\n  }\n```\n\nWhen debugging security issues, you can use:\n```\n'@phan-debug-var-taintedness $varname';\n```\nthis will emit a `SecurityCheckDebugTaintedness` issue containing the taintedness of `$varname`\nat the line where the annotation is found. Note that you have to insert the annotation in a string\nliteral; comments will not work. See also phan's `@phan-debug-var` annotation.\n\nNotable limitations\n-------------------\n### General limitations\n\n* When an issue is output, the plugin tries to include details about what line\n  originally caused the issue. Usually it works, but sometimes it gives\n  misleading/wrong information\n* The plugin won't recognize things that do custom escaping. If you have\n  custom escaping methods, you must add annotations to its docblock so\n  that the plugin can recognize it. See the Customizing section.\n* Phan does not currently have an API for accessing subclasses for a given class.\n  Therefore the SecurityCheckPlugin cannot accommodate certain data flows for\n  subclasses that should obviously be considered tainted. The workaround for this\n  is to mark any relevant subclass functions as `@return-taint html`.\n\n### MediaWiki specific limitations\n* With pass by reference parameters to MediaWiki hooks,\n  sometimes the line number is the hook call in MediaWiki core, instead of\n  the hook subscriber in the extension that caused the issue.\n* The plugin can only validate the fifth (`$options`) and sixth (`$join_cond`)\n  of MediaWiki's `IDatabase::select()` if its provided directly as an array\n  literal, or directly returned as an array literal from a `getQueryInfo()`\n  method.\n\nCustomizing\n-----------\nThe plugin supports being customized, by subclassing the [SecurityCheckPlugin]\nclass. For a complex example of doing so, see [MediaWikiSecurityCheckPlugin].\n\nSometimes you have methods in your codebase that alter the taint of a\nvariable. For example, a custom html escaping function should clear the\nhtml taint bit. Similarly, sometimes phan-taint-check can get confused and\nyou want to override the taint calculated for a specific function.\n\nYou can do this by adding a taint directive in a docblock comment. For example:\n\n```php\n/**\n * My function description\n *\n * @param string $html the text to be escaped\n * @param-taint $html escapes_html\n */\nfunction escapeHtml( $html ) {\n}\n```\n\nMethods also inherit these directives from abstract definitions in ancestor interfaces, but not from concrete implementations in ancestor classes.\n\nTaint directives are prefixed with either `@param-taint $parametername` or `@return-taint`. If there are multiple directives they can be separated by a comma. `@param-taint` is used for either marking how taint is transmitted from the parameter to the methods return value, or when used with `exec_` directives, to mark places where parameters are outputted/executed. `@return-taint` is used to adjust the return value's taint regardless of the input parameters.\n\nThe type of directives include:\n* `exec_$TYPE` - If a parameter is marked as `exec_$TYPE` then feeding that parameter a value with `$TYPE` taint will result in a warning triggered. Typically you would use this when a function that outputs or executes its parameter\n* `escapes_$TYPE` - Used for parameters where the function escapes and then returns the parameter. So `escapes_sql` would clear the sql taint bit, but leave other taint bits alone.\n* `onlysafefor_$TYPE` - For use in `@return-taint`, marks the return type as safe for a specific `$TYPE` but unsafe for the other types.\n* `$TYPE` - if just the type is specified in a parameter, it is bitwised AND with the input variable's taint. Normally you wouldn't want to do this, but can be useful when `$TYPE` is `none` to specify that the parameter is not used to generate the return value. In an `@return` this could be used to enumerate which taint flags the return value has, which is usually only useful when specified as `tainted` to say it has all flags.\n* `array_ok` - special purpose flag to say ignore tainted arguments if they are in an array.\n* `allow_override` - Special purpose flag to specify that that taint annotation should be overridden by phan-taint-check if it can detect a specific taint.\n\nThe value for `$TYPE` can be one of `htmlnoent`, `html`, `sql`, `shell`, `serialize`, `custom1`, `custom2`, `code`, `path`, `regex`, `sql_numkey`, `escaped`, `none`, `tainted`. Most of these are taint categories, except:\n* `htmlnoent` - like `html` but disable double escaping detection that gets used with `html`. When `escapes_html` is specified, escaped automatically gets added to `@return`, and `exec_escaped` is added to `@param`. Similarly `onlysafefor_html` is equivalent to `onlysafefor_htmlnoent,escaped`.\n* `none` - Means no taint\n* `tainted` - Means all taint categories except special categories (equivalent to `SecurityCheckPlugin::YES_TAINT`)\n* `escaped` - Is used to mean the value is already escaped (To track double escaping)\n* `sql_numkey` - Is fairly special purpose for MediaWiki. It ignores taint in arrays if they are for associative keys.\n\nThe default value for `@param-taint` is `tainted` if it's a string (or other dangerous type), and `none` if it's something like an integer. The default value for `@return-taint` is `allow_override` (Which is equivalent to `none` unless something better can be autodetected).\n\nInstead of annotating methods in your codebase, you can also customize\nphan-taint-check to have builtin knowledge of method taints. In addition\nyou can extend the plugin to have fairly arbitrary behaviour.\n\nTo do this, you override the `getCustomFuncTaints()` method. This method\nreturns an associative array of fully qualified method names to an array\ndescribing how the taint of the return value of the function in terms of its\narguments. The numeric keys correspond to the number of an argument, and an\n'overall' key adds taint that is not present in any of the arguments.\nBasically for each argument, the plugin takes the taint of the argument,\nbitwise AND's it to its entry in the array, and then bitwise OR's the overall\nkey. If any of the keys in the array have an EXEC flags, then an issue is\nimmediately raised if the corresponding taint is fed the function (For\nexample, an output function). The EXEC flags don't work in the 'overall' key.\n\nFor example, [htmlspecialchars] which removes html taint, escapes its argument and returns the\nescaped value would look like:\n\n```php\n'htmlspecialchars' =\u003e [\n\t( self::YES_TAINT \u0026 ~self::HTML_TAINT ) | self::ESCAPED_EXEC_TAINT,\n\t'overall' =\u003e self::ESCAPED,\n];\n```\n\nEnvironment variables\n---------------------\n\nThe following environment variables affect the plugin. Normally you would not\nhave to adjust these.\n\n* `SECURITY_CHECK_EXT_PATH` - Path to directory containing\n  `extension.json`/`skin.json` when in MediaWiki mode.\n  If not set assumes the project root directory.\n* `SECCHECK_DEBUG` - File to output extra debug information (If running from\n  `shell`, `/dev/stderr` is convenient)\n\nLicense\n-------\n\n[GNU General Public License, version 2 or later]\n\n[web demo]: https://doc.wikimedia.org/mediawiki-tools-phan-SecurityCheckPlugin/master/demos/\n[Phan]: https://github.com/phan/phan\n[XSS]: https://en.wikipedia.org/wiki/Cross-site_scripting\n[SecurityCheckPlugin]: src/SecurityCheckPlugin.php\n[MediaWikiSecurityCheckPlugin]: MediaWikiSecurityCheckPlugin.php\n[htmlspecialchars]: https://secure.php.net/htmlspecialchars\n[GNU General Public License, version 2 or later]: COPYING\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwikimedia%2Fmediawiki-tools-phan-securitycheckplugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwikimedia%2Fmediawiki-tools-phan-securitycheckplugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwikimedia%2Fmediawiki-tools-phan-securitycheckplugin/lists"}