Summary
mcpp new <name> currently has no single authoritative project-name contract. The name is used both as a filesystem path and as unescaped template data. This permits path escape and malformed generated projects; one valid-looking input can also make the command loop forever.
Reproduction
1. Template marker in the name hangs the command
mcpp new PROJECT
mcpp new myPROJECTname
The builtin scaffold repeatedly executes:
while ((pos = body.find("PROJECT")) != std::string::npos) {
body.replace(pos, 7, name);
}
When name itself contains PROJECT, the replacement result remains matchable. A controlled 500 ms run ended with ETIMEDOUT / SIGTERM; mcpp.toml had already been created, leaving a partial project.
The package-template renderer has the same general risk because inserted placeholder values are searched again by replace_all when they contain the placeholder token.
2. A name can escape the current directory
mkdir work
cd work
mcpp new ../escaped
Observed result: exit code 0 and the project was created at the parent directory (../escaped). Both builtin and package-template paths construct the destination as current_path() / name without requiring a single path component.
3. Template-unsafe names return success with invalid files
mcpp new 'bad"name'
mcpp new $'bad\tname'
Observed result: exit code 0. The generated TOML/C++ contains the value without escaping, for example:
The builtin scaffold also does not check the open/write status of mcpp.toml, src/main.cpp, tests/test_smoke.cpp, or .gitignore, so an incomplete write can still reach the success message and return 0.
Expected behavior
Before creating any directory, mcpp new should apply one shared validation contract to builtin and package templates:
- require a non-empty single path component;
- reject absolute paths, separators,
. / .., control characters, and platform-invalid names;
- either reject template-unsafe characters or provide context-safe escaping;
- render placeholders without rescanning inserted values;
- check every directory/file operation and return non-zero on incomplete output;
- avoid leaving a partial project after a failed render/write where practical.
The CLI should own this contract so VS Code and other clients do not need to copy internal template rules.
Suggested tests
PROJECT and myPROJECTname terminate and produce valid output or a clear validation error.
../escaped and an absolute path cannot create outside the working directory.
- quotes and C0/DEL controls cannot produce malformed TOML/C++.
- failed file writes return non-zero.
- the same name validation applies to builtin and package-shipped templates.
Environment and evidence boundary
- Runtime reproduction: locally available
mcpp 2026.8.5.2 on macOS ARM64.
- Current-source verification:
origin/main@fdad165 (v2026.8.8.2) still contains the same destination construction, unescaped builtin template replacement, and unchecked output streams.
Summary
mcpp new <name>currently has no single authoritative project-name contract. The name is used both as a filesystem path and as unescaped template data. This permits path escape and malformed generated projects; one valid-looking input can also make the command loop forever.Reproduction
1. Template marker in the name hangs the command
The builtin scaffold repeatedly executes:
When
nameitself containsPROJECT, the replacement result remains matchable. A controlled 500 ms run ended withETIMEDOUT/SIGTERM;mcpp.tomlhad already been created, leaving a partial project.The package-template renderer has the same general risk because inserted placeholder values are searched again by
replace_allwhen they contain the placeholder token.2. A name can escape the current directory
mkdir work cd work mcpp new ../escapedObserved result: exit code 0 and the project was created at the parent directory (
../escaped). Both builtin and package-template paths construct the destination ascurrent_path() / namewithout requiring a single path component.3. Template-unsafe names return success with invalid files
Observed result: exit code 0. The generated TOML/C++ contains the value without escaping, for example:
The builtin scaffold also does not check the open/write status of
mcpp.toml,src/main.cpp,tests/test_smoke.cpp, or.gitignore, so an incomplete write can still reach the success message and return 0.Expected behavior
Before creating any directory,
mcpp newshould apply one shared validation contract to builtin and package templates:./.., control characters, and platform-invalid names;The CLI should own this contract so VS Code and other clients do not need to copy internal template rules.
Suggested tests
PROJECTandmyPROJECTnameterminate and produce valid output or a clear validation error.../escapedand an absolute path cannot create outside the working directory.Environment and evidence boundary
mcpp 2026.8.5.2on macOS ARM64.origin/main@fdad165(v2026.8.8.2) still contains the same destination construction, unescaped builtin template replacement, and unchecked output streams.