T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/generate_qt_code.js:430
- Finding
- Unvalidated Mapping Data Enables Path Traversal and Generated-Code Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_qt_code.js`, lines 430–780 **Vulnerability Type**: Path traversal, arbitrary file overwrite, and generated-code injection **Risk Level**: High **Category**: T09: Insecure Skill Coding Practices ### Vulnerable Code The generator derives output filenames directly from the attacker-controllable `form.name` value: ```js function generateFormHeader(form) { const className = form.name; const lowerName = className.toLowerCase(); const headerContent = `#ifndef ${className.toUpperCase()}_H #define ${className.toUpperCase()}_H #include <QWidget> namespace Ui { class ${className}; } class ${className} : public QWidget { Q_OBJECT public: explicit ${className}(QWidget *parent = nullptr); ~${className}(); private slots: ${form.events.map(event => `void ${event.handler}();`).join('\n ')} private: Ui::${className} *ui; // Control member variables ${form.controls.map(control => `QWidget *${control.name}; // WinForms type: ${control.type}`).join('\n ')} }; #endif // ${className.toUpperCase()}_H `; const headerPath = path.join(options.output, `include/${lowerName}.h`); fs.writeFileSync(headerPath, headerContent); } ``` The same unvalidated value is used to construct source-file paths and C++ source code: ```js function generateFormSource(form) { const className = form.name; const lowerName = className.toLowerCase(); const sourceContent = `#include "${lowerName}.h" #include "ui_${lowerName}.h" #include <QMessageBox> #include <QDebug> ${className}::${className}(QWidget *parent) : QWidget(parent) , ui(new Ui::${className}) { ui->setupUi(this); setupUi(); setupConnections(); } void ${className}::setupConnections() { ${form.events.map(event => ` // ${event.control}.${event.event} -> ${event.handler} connect(${event.control}, &${getQtSignalForEvent(event.event)}, this, &${className}::${ev ...[truncated 3896 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Enforce a strict mapping schema** - Validate the complete JSON document before generation. - Require arrays and properties to have expected types. - Reject unknown fields where practical. - Impose reasonable limits on string lengths and collection sizes. 2. **Restrict generated identifiers** - Permit class, control, event-handler, and project names only when they match an appropriate identifier policy, such as: ```js const cppIdentifier = /^[A-Za-z_][A-Za-z0-9_]*$/; ``` - Reject path separators, traversal components, null bytes, control characters, newlines, and platform-reserved filenames. 3. **Enforce output-directory containment** - Resolve the output root and every destination to absolute paths. - Verify that each destination remains inside the intended root before writing: ```js const outputRoot = path.resolve(options.output); function safeOutputPath(relativePath) { const destination = path.resolve(outputRoot, relativePath); const expectedPrefix = outputRoot + path.sep; if (!destination.startsWith(expectedPrefix)) { throw new Error(`Output path escapes project directory: ${relativePath}`); } return destination; } ``` - Use the helper for every generated file. 4. **Apply context-specific escaping** - Escape C++ string literals separately from C++ comments and identifiers. - Escape XML text and attribute values using an XML library rather than string interpolation. - Quote and validate CMake values according to CMake syntax. - Do not assume that a single generic escaping function is safe for all output contexts. 5. **Reduce downstream execution risk** - Mark imported mapping and analysis files as untrusted in documentation. - Require users to review generated CMake and source files before building. - Avoid automatically invoking build tools on newly generated projects. ...[truncated 349 chars]
