Skip to content

Commit b0faf25

Browse files
committed
chore: path validation before policy check
1 parent 6b73b08 commit b0faf25

File tree

1 file changed

+21
-38
lines changed

1 file changed

+21
-38
lines changed

packages/appkit/src/plugins/files/plugin.ts

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,12 @@ export class FilesPlugin extends Plugin {
9898
}));
9999
}
100100

101-
/** Whether a volume has a policy attached. */
102-
private _hasPolicy(volumeKey: string): boolean {
103-
return typeof this.volumeConfigs[volumeKey]?.policy === "function";
104-
}
105-
106101
/**
107102
* Extract user identity from the request.
108103
* Falls back to `getCurrentUserId()` in development mode.
109104
*/
110105
private _extractUser(req: express.Request): FilePolicyUser {
111-
const userId = req.header("x-forwarded-user");
106+
const userId = req.header("x-forwarded-user")?.trim();
112107
if (userId) return { id: userId };
113108
if (process.env.NODE_ENV === "development") {
114109
logger.warn(
@@ -167,8 +162,6 @@ export class FilesPlugin extends Plugin {
167162
path: string,
168163
resourceOverrides?: Partial<FileResource>,
169164
): Promise<boolean> {
170-
if (!this._hasPolicy(volumeKey)) return true;
171-
172165
let user: FilePolicyUser;
173166
try {
174167
user = this._extractUser(req);
@@ -553,14 +546,14 @@ export class FilesPlugin extends Plugin {
553546
): Promise<void> {
554547
const path = req.query.path as string;
555548

556-
if (!(await this._enforcePolicy(req, res, volumeKey, "read", path))) return;
557-
558549
const valid = this._isValidPath(path);
559550
if (valid !== true) {
560551
res.status(400).json({ error: valid, plugin: this.name });
561552
return;
562553
}
563554

555+
if (!(await this._enforcePolicy(req, res, volumeKey, "read", path))) return;
556+
564557
try {
565558
const result = await this.execute(
566559
async () => connector.read(getWorkspaceClient(), path),
@@ -616,15 +609,15 @@ export class FilesPlugin extends Plugin {
616609
): Promise<void> {
617610
const path = req.query.path as string;
618611

619-
if (!(await this._enforcePolicy(req, res, volumeKey, opts.mode, path)))
620-
return;
621-
622612
const valid = this._isValidPath(path);
623613
if (valid !== true) {
624614
res.status(400).json({ error: valid, plugin: this.name });
625615
return;
626616
}
627617

618+
if (!(await this._enforcePolicy(req, res, volumeKey, opts.mode, path)))
619+
return;
620+
628621
const label = opts.mode === "download" ? "Download" : "Raw fetch";
629622
const volumeCfg = this.volumeConfigs[volumeKey];
630623

@@ -698,15 +691,15 @@ export class FilesPlugin extends Plugin {
698691
): Promise<void> {
699692
const path = req.query.path as string;
700693

701-
if (!(await this._enforcePolicy(req, res, volumeKey, "exists", path)))
702-
return;
703-
704694
const valid = this._isValidPath(path);
705695
if (valid !== true) {
706696
res.status(400).json({ error: valid, plugin: this.name });
707697
return;
708698
}
709699

700+
if (!(await this._enforcePolicy(req, res, volumeKey, "exists", path)))
701+
return;
702+
710703
try {
711704
const result = await this.execute(
712705
async () => connector.exists(getWorkspaceClient(), path),
@@ -736,15 +729,15 @@ export class FilesPlugin extends Plugin {
736729
): Promise<void> {
737730
const path = req.query.path as string;
738731

739-
if (!(await this._enforcePolicy(req, res, volumeKey, "metadata", path)))
740-
return;
741-
742732
const valid = this._isValidPath(path);
743733
if (valid !== true) {
744734
res.status(400).json({ error: valid, plugin: this.name });
745735
return;
746736
}
747737

738+
if (!(await this._enforcePolicy(req, res, volumeKey, "metadata", path)))
739+
return;
740+
748741
try {
749742
const result = await this.execute(
750743
async () => connector.metadata(getWorkspaceClient(), path),
@@ -774,15 +767,15 @@ export class FilesPlugin extends Plugin {
774767
): Promise<void> {
775768
const path = req.query.path as string;
776769

777-
if (!(await this._enforcePolicy(req, res, volumeKey, "preview", path)))
778-
return;
779-
780770
const valid = this._isValidPath(path);
781771
if (valid !== true) {
782772
res.status(400).json({ error: valid, plugin: this.name });
783773
return;
784774
}
785775

776+
if (!(await this._enforcePolicy(req, res, volumeKey, "preview", path)))
777+
return;
778+
786779
try {
787780
const result = await this.execute(
788781
async () => connector.preview(getWorkspaceClient(), path),
@@ -918,17 +911,15 @@ export class FilesPlugin extends Plugin {
918911
const dirPath =
919912
typeof req.body?.path === "string" ? req.body.path : undefined;
920913

921-
if (
922-
!(await this._enforcePolicy(req, res, volumeKey, "mkdir", dirPath ?? "/"))
923-
)
924-
return;
925-
926914
const valid = this._isValidPath(dirPath);
927915
if (valid !== true) {
928916
res.status(400).json({ error: valid, plugin: this.name });
929917
return;
930918
}
931919

920+
if (!(await this._enforcePolicy(req, res, volumeKey, "mkdir", dirPath)))
921+
return;
922+
932923
try {
933924
const settings: PluginExecutionSettings = {
934925
default: FILES_WRITE_DEFAULTS,
@@ -963,24 +954,16 @@ export class FilesPlugin extends Plugin {
963954
): Promise<void> {
964955
const rawPath = req.query.path as string | undefined;
965956

966-
if (
967-
!(await this._enforcePolicy(
968-
req,
969-
res,
970-
volumeKey,
971-
"delete",
972-
rawPath ?? "/",
973-
))
974-
)
975-
return;
976-
977957
const valid = this._isValidPath(rawPath);
978958
if (valid !== true) {
979959
res.status(400).json({ error: valid, plugin: this.name });
980960
return;
981961
}
982962
const path = rawPath as string;
983963

964+
if (!(await this._enforcePolicy(req, res, volumeKey, "delete", path)))
965+
return;
966+
984967
try {
985968
const settings: PluginExecutionSettings = {
986969
default: FILES_WRITE_DEFAULTS,

0 commit comments

Comments
 (0)