SEC: MultiMC 整合包 PreLaunch/Wrapper 写入设置并在启动时执行 #8

Open
opened 2026-11-09 14:23:45 +00:00 by layue13 · 0 comments
Owner

调研编号:扫描 2026-11-09 / G4

现象

用户安装 MultiMC 格式整合包时,若包配置声明 OverrideCommands,启动器会把包内的 PreLaunchCommand / WrapperCommand 原样写入实例的 GameSettings;之后启动该实例时,DefaultLauncher 用 ProcessBuilder 执行预启动命令,并把 Wrapper 拼进启动命令行。整合包来自不可信输入,导入即可在本机执行包指定的命令。

危害类与优先级

  • 危害类:SEC
  • 优先级:p0

证据(生效源码)

  • 载体:TDLM/HMCL + 分支 origin/main + pin/commit bdacd654734c3665995a8c779da34139b9bdf373
  • 位置:HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java:317-329(安装写入)、:350-363(更新写入);HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java:84-85(Wrapper)、:689-692(PreLaunch 执行)
  • 关键原文:
// ModpackHelper.java:317-329
if (c.isOverrideCommands()) {
    setting.getOverrideProperties().addAll(List.of(
            GameSettings.PROPERTY_COMMAND_WRAPPER,
            GameSettings.PROPERTY_PRE_LAUNCH_COMMAND
    ));
    setting.commandWrapperProperty().setValue(Objects.requireNonNullElse(c.getWrapperCommand(), ""));
    setting.preLaunchCommandProperty().setValue(Objects.requireNonNullElse(c.getPreLaunchCommand(), ""));
}

if (c.isOverrideJavaArgs()) {
    setting.getOverrideProperties().add(GameSettings.PROPERTY_JVM_OPTIONS);
    setting.jvmOptionsProperty().setValue(Objects.requireNonNullElse(c.getJvmArgs(), ""));
}
// ModpackHelper.java:350-363(更新路径同样写入)
private static void applyCommandAndJvmSettings(MultiMCInstanceConfiguration c, GameSettings.Instance setting) {
    if (c.isOverrideCommands()) {
        setting.getOverrideProperties().addAll(List.of(
                GameSettings.PROPERTY_COMMAND_WRAPPER,
                GameSettings.PROPERTY_PRE_LAUNCH_COMMAND
        ));
        setting.commandWrapperProperty().setValue(Lang.nonNull(c.getWrapperCommand(), ""));
        setting.preLaunchCommandProperty().setValue(Lang.nonNull(c.getPreLaunchCommand(), ""));
    }
    // ...
}
// DefaultLauncher.java:84-85
if (StringUtils.isNotBlank(options.getWrapper()))
    res.addAllWithoutParsing(StringUtils.tokenize(options.getWrapper(), getEnvVars(nativeFolder)));
// DefaultLauncher.java:689-692
if (StringUtils.isNotBlank(options.getPreLaunchCommand())) {
    ProcessBuilder builder = new ProcessBuilder(StringUtils.tokenize(options.getPreLaunchCommand(), getEnvVars(nativeFolder))).directory(runDirectory.toFile());
    builder.environment().putAll(getEnvVars(nativeFolder));
    SystemUtils.callExternalProcess(builder);
}
  • 上游状态:未修

触发与复现

  • 触发条件:安装带 OverrideCommands 与非空 PreLaunch/Wrapper 的 MultiMC 整合包,再启动该实例;默认流程可达,无需额外权限。
  • 复现程度:静态推演(调用链:整合包配置 → GameSettings → ProcessBuilder / 启动命令行)
  • 包内相关性:模块 n/a(启动器)/sides client/默认配置可达 是

落点

  • 主仓:TDLM/HMCL → HMCL/.../ModpackHelper.java:317;协同消费侧 HMCLCore/.../DefaultLauncher.java:689
  • 协同:无

范式

引证

  1. 生效源码 permalink(写入)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java#L317-L329
  2. 生效源码 permalink(更新写入)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java#L350-L363
  3. 生效源码 permalink(Wrapper)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java#L84-L85
  4. 生效源码 permalink(PreLaunch 执行)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java#L689-L692
  5. 范式 G4 — https://git.potatolab.uk/TDLM/mc-defect-patterns/raw/commit/12d2ebdc7a87175f936c2a67083be567e0e94301/sec/G4-信任边界.md

来源

  • 线索类型:内部代码审查(无外部报障)
  • 可解析指针:ModpackHelper.java:317-329;DefaultLauncher.java:689-692;commit bdacd654734c3665995a8c779da34139b9bdf373
  • 来源标签:origin/scan
**调研编号**:扫描 2026-11-09 / G4 ## 现象 用户安装 MultiMC 格式整合包时,若包配置声明 `OverrideCommands`,启动器会把包内的 `PreLaunchCommand` / `WrapperCommand` 原样写入实例的 `GameSettings`;之后启动该实例时,`DefaultLauncher` 用 `ProcessBuilder` 执行预启动命令,并把 Wrapper 拼进启动命令行。整合包来自不可信输入,导入即可在本机执行包指定的命令。 ## 危害类与优先级 - 危害类:`SEC` - 优先级:`p0` ## 证据(生效源码) - 载体:`TDLM/HMCL` + 分支 `origin/main` + pin/commit `bdacd654734c3665995a8c779da34139b9bdf373` - 位置:`HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java:317-329`(安装写入)、`:350-363`(更新写入);`HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java:84-85`(Wrapper)、`:689-692`(PreLaunch 执行) - 关键原文: ```java // ModpackHelper.java:317-329 if (c.isOverrideCommands()) { setting.getOverrideProperties().addAll(List.of( GameSettings.PROPERTY_COMMAND_WRAPPER, GameSettings.PROPERTY_PRE_LAUNCH_COMMAND )); setting.commandWrapperProperty().setValue(Objects.requireNonNullElse(c.getWrapperCommand(), "")); setting.preLaunchCommandProperty().setValue(Objects.requireNonNullElse(c.getPreLaunchCommand(), "")); } if (c.isOverrideJavaArgs()) { setting.getOverrideProperties().add(GameSettings.PROPERTY_JVM_OPTIONS); setting.jvmOptionsProperty().setValue(Objects.requireNonNullElse(c.getJvmArgs(), "")); } ``` ```java // ModpackHelper.java:350-363(更新路径同样写入) private static void applyCommandAndJvmSettings(MultiMCInstanceConfiguration c, GameSettings.Instance setting) { if (c.isOverrideCommands()) { setting.getOverrideProperties().addAll(List.of( GameSettings.PROPERTY_COMMAND_WRAPPER, GameSettings.PROPERTY_PRE_LAUNCH_COMMAND )); setting.commandWrapperProperty().setValue(Lang.nonNull(c.getWrapperCommand(), "")); setting.preLaunchCommandProperty().setValue(Lang.nonNull(c.getPreLaunchCommand(), "")); } // ... } ``` ```java // DefaultLauncher.java:84-85 if (StringUtils.isNotBlank(options.getWrapper())) res.addAllWithoutParsing(StringUtils.tokenize(options.getWrapper(), getEnvVars(nativeFolder))); ``` ```java // DefaultLauncher.java:689-692 if (StringUtils.isNotBlank(options.getPreLaunchCommand())) { ProcessBuilder builder = new ProcessBuilder(StringUtils.tokenize(options.getPreLaunchCommand(), getEnvVars(nativeFolder))).directory(runDirectory.toFile()); builder.environment().putAll(getEnvVars(nativeFolder)); SystemUtils.callExternalProcess(builder); } ``` - 上游状态:未修 ## 触发与复现 - 触发条件:安装带 `OverrideCommands` 与非空 PreLaunch/Wrapper 的 MultiMC 整合包,再启动该实例;默认流程可达,无需额外权限。 - 复现程度:静态推演(调用链:整合包配置 → GameSettings → ProcessBuilder / 启动命令行) - 包内相关性:模块 n/a(启动器)/sides `client`/默认配置可达 是 ## 落点 - 主仓:`TDLM/HMCL` → `HMCL/.../ModpackHelper.java:317`;协同消费侧 `HMCLCore/.../DefaultLauncher.java:689` - 协同:无 ## 范式 - 命中范式:G4 信任边界(https://git.potatolab.uk/TDLM/mc-defect-patterns/raw/commit/12d2ebdc7a87175f936c2a67083be567e0e94301/sec/G4-信任边界.md;contents?ref=12d2ebd 已验证,本仓 /src/ 页对部分路径 404 故给 raw) ## 引证 1. 生效源码 permalink(写入)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java#L317-L329 2. 生效源码 permalink(更新写入)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java#L350-L363 3. 生效源码 permalink(Wrapper)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java#L84-L85 4. 生效源码 permalink(PreLaunch 执行)— https://git.potatolab.uk/TDLM/HMCL/src/commit/bdacd654734c3665995a8c779da34139b9bdf373/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java#L689-L692 5. 范式 G4 — https://git.potatolab.uk/TDLM/mc-defect-patterns/raw/commit/12d2ebdc7a87175f936c2a67083be567e0e94301/sec/G4-信任边界.md ## 来源 - 线索类型:内部代码审查(无外部报障) - 可解析指针:`ModpackHelper.java:317-329`;`DefaultLauncher.java:689-692`;commit `bdacd654734c3665995a8c779da34139b9bdf373` - 来源标签:`origin/scan`
layue13 added the
priority
p0
area/security
type
security
origin/scan
labels 2026-11-09 14:23:45 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: TDLM/HMCL#8