Hello,
We recently bumped dependencies and are getting this error in our staging env.
I tried to find anything on the topic but could not.
Any help where to start would really be appreciated.
Something went wrong
Trace ID: 000000000000000099c90818591d36d8
There was an error invoking the function - Disallowing path manipulation attempt
Error: Disallowing path manipulation attempt
at escapeParameter (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:740:23)
at route (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:767:19)
at _callee$ (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56679:75)
at tryCatch (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56666:1062)
at Generator.<anonymous> (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56666:3012)
at Generator.next (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56666:1699)
at asyncGeneratorStep (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56668:103)
at _next (/tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56669:194)
at /tmp/tunnel-7-aJnqlPs5QVHp/ProtectedFieldHandler.js:56669:364
at new Promise (<anonymous>)
We simply get data using this small code:
const getDataFromJira = async (url) => {
try {
const response = await api.asUser().requestJira(route`${url}`);
return await response.json();
} catch (error) {
console.log("getDataFromJira error: ", error);
throw error;
}
};
Can you tell us what is in the url
variable you’re sending into the route function?
The route
function is meant to be used at the point where you are constructing the URL from its parts, incorporating the user input into it. For example:
const url = route`/rest/api/3/issue/${issueKey}`;
await api.asUser().requestJira(url);
Instead of:
const url_bad = `/rest/api/3/issue/${issueKey}`; // bad
await api.asUser().requestJira(route`${url_bad}`);
When route
is called, it can check for possible path manipulation attempts (e.g. issueKey
coming from the user as ../../../evil_api_call
) and escape or block them properly.
If URL is constructed separately, route
has no way of knowing which parts might have been manipulated by the user, so it might throw this error as a false positive.
I suggest rewriting your getDataFromJira
function to accept the result of calling route
, and move the route
wherever the URLs are being constructed.
3 Likes
Thanks a lot for the answer, that was the problem, this seems to been allowed before but checking the change log, there has been some updates around this CWE. Great answer!
Above solution is not working for me. Any other solutions?
Sorry to hear that. Can you please show your code and what is happening?
Yeah sure. thanks for the reply
Defining resolver at the backend part
resolver.define("MAKE_API", async (req) => {
const { url, method, body } = req?.payload;
const options = {
method: method,
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(body)
}
const apiUrl = route`${url}`
const response = await api?.asUser()?.requestJira(apiUrl, options);
const data = await response?.json();
return data ? data : [];
})
Below is the code where i am invoking the resolver from frontend side
const GET_CURRENT_USER = async () => {
const result = await invoke('GET_INFO', { key: '__info' })
const response = await invoke('MAKE_API', {
url: `${USER}?accountId=${result?.user?.id}`, // Here USER = '/rest/api/3/user'
method: 'GET',
body: undefined
})
return response
}
@GaneshXDev First of all, you don’t need to use invoke
for this code as you can call requestJira
from the frontend directly.
If you have more involved logic, please follow the advice above:
- Only pass the necessary information to the backend (in your case
result.user.id
).
- Construct only the endpoint you actually need on the backend, starting with
/rest/api/3/user
.
Otherwise a malicious user can manipulate the url
into an entirely different call with unintended effects.
1 Like
Thanks @AlexeyKotlyarov , Better I will go with requestJira
from frontend side.
Hi @AlexeyKotlyarov
In terms of calling requestJira directly instead of using invoke does this apply also to older versions of api/ui? In addition, will the use of invoke trigger the path manipulation error?
Many thanks
Rob
@RobertHarkin Best create a new thread with your specific problem - I’ll answer but I can only guess what your use case is.
[does] calling requestJira
[…] apply to older versions of api/ui?
If you want to contact Jira from the UI, it’s easier to do directly and you should do so! But also update to the latest @forge/api
as that has all the recent bugfixes and enhancements.
Will the use of invoke
trigger the path manipulation error?
Not by itself. In the original question the problem was calling route
on user-supplied input.
1 Like
A side note, you can use
import { assumeTrustedRoute } from '@forge/api'
whose signature is
export declare function assumeTrustedRoute(route: string): Route;
So get a route from a string.
As stated in the name of the function you assume the string route can be trusted !
Thanks @AlexeyKotlyarov. This post helped me resolve my issues.
@FabienLydoire thanks for this, yes I was aware but wanted to avoid using this. Ended up refactoring all of my API calls and they are now compliant and a lot neater than what I inherited.
Thanks again all!
1 Like