Skip to content

Commit

Permalink
Merge pull request #9712 from weseek/fix/161421-prevent-installation-…
Browse files Browse the repository at this point in the history
…outside-the-plugin-directory

fix:  Prevent GrowiPlugin from being downloaded outside the plugin directory
  • Loading branch information
yuki-takei authored Mar 11, 2025
2 parents 60deb84 + e885dce commit 0edd954
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@ export class GrowiPluginService implements IGrowiPluginService {

// if not exists repository in file system, download latest plugin repository
for await (const growiPlugin of growiPlugins) {
const pluginPath = path.join(PLUGIN_STORING_PATH, growiPlugin.installedPath);
const organizationName = path.join(PLUGIN_STORING_PATH, growiPlugin.organizationName);
let pluginPath :fs.PathLike|undefined;
let organizationName :fs.PathLike|undefined;
try {
pluginPath = this.joinAndValidatePath(PLUGIN_STORING_PATH, growiPlugin.installedPath);
organizationName = this.joinAndValidatePath(PLUGIN_STORING_PATH, growiPlugin.organizationName);
}
catch (err) {
logger.error(err);
continue;
}
if (fs.existsSync(pluginPath)) {
continue;
}
Expand Down Expand Up @@ -301,22 +309,34 @@ export class GrowiPluginService implements IGrowiPluginService {
}

try {
const growiPluginsPath = path.join(PLUGIN_STORING_PATH, growiPlugins.installedPath);
await deleteFolder(growiPluginsPath);
await GrowiPlugin.deleteOne({ _id: pluginId });
}
catch (err) {
logger.error(err);
throw new Error('Failed to delete plugin repository.');
throw new Error('Failed to delete plugin from GrowiPlugin documents.');
}

let growiPluginsPath: fs.PathLike | undefined;
try {
await GrowiPlugin.deleteOne({ _id: pluginId });
growiPluginsPath = this.joinAndValidatePath(PLUGIN_STORING_PATH, growiPlugins.installedPath);
}
catch (err) {
logger.error(err);
throw new Error('Failed to delete plugin from GrowiPlugin documents.');
throw new Error('The installedPath for the plugin is invalid, and the plugin has already been removed.');
}

if (growiPluginsPath && fs.existsSync(growiPluginsPath)) {
try {
await deleteFolder(growiPluginsPath);
}
catch (err) {
logger.error(err);
throw new Error('Failed to delete plugin repository.');
}
}
else {
logger.warn(`Plugin path does not exist : ${growiPluginsPath}`);
}
return growiPlugins.meta.name;
}

Expand Down Expand Up @@ -402,6 +422,17 @@ export class GrowiPluginService implements IGrowiPluginService {
return entries;
}

private joinAndValidatePath(baseDir: string, ...paths: string[]):fs.PathLike {
const joinedPath = path.join(baseDir, ...paths);
if (!joinedPath.startsWith(baseDir)) {
throw new Error(
'Invalid plugin path detected! Access outside of the allowed directory is not permitted.'
+ `\nAttempted Path: ${joinedPath}`,
);
}
return joinedPath;
}

}


Expand Down
17 changes: 16 additions & 1 deletion apps/app/src/server/service/import/overwrite-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {
Types, type Document,
} from 'mongoose';

import loggerFactory from '~/utils/logger';

const logger = loggerFactory('growi:service:import:overwrite-function');


const { ObjectId } = Types;

Expand All @@ -21,6 +25,10 @@ export type OverwriteFunction = (value: unknown, ctx: { document: Document, prop
* @see https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-cast
*/
export const keepOriginal: OverwriteFunction = (value, { document, schema, propertyName }) => {
if (value == null) {
return value;
}

// Model
if (schema != null && schema.path(propertyName) != null) {
const schemaType = schema.path(propertyName);
Expand All @@ -30,7 +38,14 @@ export const keepOriginal: OverwriteFunction = (value, { document, schema, prope
// ref: https://github.com/Automattic/mongoose/blob/6.11.4/lib/schema/array.js#L334
document.schema = schema;

return schemaType.cast(value, document, true);
try {
return schemaType.cast(value, document, true);
}
catch (e) {
logger.warn(`Failed to cast value for ${propertyName}`, e);
// return original value
return value;
}
}

// _id
Expand Down

0 comments on commit 0edd954

Please sign in to comment.