fix: set display_errors=Off in production PHP files#1146
Conversation
- admin/problem_df_change.php: wrap hlist processing in braces and apply array_map intval - admin/contest_add.php: same fix for hlist bypass of intval protection
- Replace string interpolation '$user_id' in SQL with ? placeholder - Pass $user_id as bound parameter to pdo_query() - Fixes both the main query and the discuz_conn branch
…n files - aiapi/cron.php: display_errors On -> Off - admin/problem_del.php: display_errors On -> Off - admin/user_import.php: display_errors On -> Off - admin/offline_import.php: error_reporting(E_ALL) -> error_reporting(0)
There was a problem hiding this comment.
Pull request overview
This PR aims to harden production behavior by disabling PHP error display in several entry-point scripts, reducing the risk of leaking stack traces/paths to end users. It also includes additional SQL-injection-related changes in a few admin/login flows.
Changes:
- Turn
display_errorsoff in multiple production PHP scripts (cron/admin tools). - Change
admin/offline_import.phpto disable all error reporting. - Add SQL injection mitigations (parameterized query in Discuz login;
intvalsanitization forIN (...)ID lists in admin pages).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| trunk/web/include/login-discuz.php | Switch Discuz user lookup to a parameterized query. |
| trunk/web/aiapi/cron.php | Disable display_errors for cron execution. |
| trunk/web/admin/user_import.php | Disable display_errors for admin import tool. |
| trunk/web/admin/problem_df_change.php | Sanitize hlist IDs via intval before using in IN (...). |
| trunk/web/admin/problem_del.php | Disable display_errors for admin delete operation. |
| trunk/web/admin/offline_import.php | Disable display_errors and set error_reporting(0). |
| trunk/web/admin/contest_add.php | Sanitize hlist IDs via intval before using in IN (...). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $pieces = explode(",",$plist); | ||
| $pieces = array_unique($pieces); | ||
| if($pieces[0]=="")unset($pieces[0]); | ||
| // 安全修复:每个ID元素强制intval,防止SQL注入 | ||
| $plist = implode(",", array_map('intval', $pieces)); |
There was a problem hiding this comment.
array_map('intval', $pieces) 会把空字符串/非数字项转成 0;当 hlist 含有多余逗号/空白时(如 "1,,2"),最终 $plist 可能包含 0。建议在转换前先 trim 并过滤掉空项与 <=0 的值,再生成 IN 列表字符串。
| $pieces = explode(",",$plist); | |
| $pieces = array_unique($pieces); | |
| if($pieces[0]=="")unset($pieces[0]); | |
| // 安全修复:每个ID元素强制intval,防止SQL注入 | |
| $plist = implode(",", array_map('intval', $pieces)); | |
| $pieces = explode(",", $plist); | |
| $cleanPieces = array(); | |
| foreach ($pieces as $p) { | |
| $p = trim($p); | |
| if ($p === '') continue; | |
| $val = intval($p); | |
| if ($val > 0) { | |
| $cleanPieces[] = $val; | |
| } | |
| } | |
| $cleanPieces = array_unique($cleanPieces); | |
| if (!empty($cleanPieces)) { | |
| // 安全修复:每个ID元素强制intval,防止SQL注入,并过滤空值和非正数 | |
| $plist = implode(",", $cleanPieces); | |
| } else { | |
| $plist = ""; | |
| } |
| // 安全修复:使用参数化查询防止 SQL 注入 | ||
| $sql="select password,salt,username from ".$discuz_db.".uc_members where username=?"; | ||
| $result=pdo_query($sql, $user_id); |
There was a problem hiding this comment.
PR 标题/描述聚焦于生产环境关闭 display_errors,但本次改动还包含多处 SQL 注入相关“安全修复”(如本文件的参数化查询,以及 admin/problem_df_change.php、admin/contest_add.php 的 ID 列表处理)。为避免审阅/回滚困难,建议更新 PR 标题与描述覆盖这些安全改动,或拆分为单独 PR。
| $row = $result[0]; | ||
| if($discuz_conn){ | ||
| mysql_select_db($discuz_db,$discuz_conn); | ||
| $result=pdo_query($sql,$discuz_conn); | ||
| $result=pdo_query($sql, $user_id); | ||
|
|
There was a problem hiding this comment.
这里在拿到 $row 后又在 if($discuz_conn) 内重复执行了一次相同查询,但第二次的 $result 没有被使用,且 mysql_select_db() 也不会影响 pdo_query() 使用的 PDO 连接。建议要么删除这次重复查询/多余的 mysql_* 连接判断,要么在 if 分支内用独立的 PDO 连接(使用 discuz_* 配置)执行查询并用其结果更新 $row。
| ini_set("display_errors", "Off"); //set this to "On" for debugging ,especially when no reason blank shows up. | ||
| error_reporting(E_ALL); | ||
| ini_set("display_errors", "Off"); // 生产环境应关闭调试 | ||
| error_reporting(0); // 禁止显示任何错误信息 |
There was a problem hiding this comment.
将 error_reporting(0) 用于生产会同时关闭错误记录/上报(不仅仅是不显示),会显著降低线上问题排查能力。若目标只是防止错误输出泄露,建议保留 error_reporting(E_ALL)(或项目约定级别)并仅关闭 display_errors,同时确保由 php.ini/容器配置负责 log_errors。
| error_reporting(0); // 禁止显示任何错误信息 | |
| error_reporting(E_ALL); // 保留错误上报,仅关闭错误输出 |
| $pieces = explode(",",$plist); | ||
| $pieces = array_unique($pieces); | ||
| if($pieces[0]=="") unset($pieces[0]); | ||
| $plist=implode(",",$pieces); | ||
| // 安全修复:每个ID元素强制intval,防止SQL注入 | ||
| $plist = implode(",", array_map('intval', $pieces)); |
There was a problem hiding this comment.
array_map('intval', $pieces) 会把空字符串/非数字项转成 0;如果 hlist 里包含多余逗号(如 "1,,2")或空白,最终 $plist 可能包含 0,导致写入的 IN 列表出现无意义/潜在误操作项。建议在 intval 前先 trim 并过滤掉空项与 <=0 的值(例如 array_filter),再 implode。
Fix Debug Settings in Production
问题
4个PHP文件在生产环境开启
display_errors,可能导致 PHP 错误信息、堆栈跟踪、文件路径等敏感信息泄露给用户。修复
aiapi/cron.phpdisplay_errors "On"→"Off"admin/problem_del.phpdisplay_errors "On"→"Off"admin/user_import.phpdisplay_errors "On"→"Off"admin/offline_import.phperror_reporting(E_ALL)→error_reporting(0)