Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
twilio-functions-utils
Advanced tools
This lib was created with the aim of simplifying the use of serverless Twilio, reducing the need to apply frequent try-catches and improving context management, making it no longer necessary to return the callback() method in all functions.
npm install twilio-functions-utils
The lib provides a function useInjection
who returns a brand function for every execution. This returned function is ready to receive the Twilio Handler arguments and make them available as this
properties as this.request
, this.cookies
, this.twilio
and this.env
at the Function level.
The useInjection method takes two parameters. The first to apply as a handler and the last is an object of configuration options.
Must be writen in standard format, this will be your handler
function.
function createSomeThing (event) {
...
}
You can pass validateToken
equal true to force Flex Token validation using Twilio Flex Token Validator
useInjection(yourFunction,
{
validateToken: true
}
);
When using Token Validator, the Request body must contain a valid Token from Twilio Flex.
// Event
{
Token: "Twilio-Token-Here"
}
This captures the this object and prepare it for optimizing imports from Twilio Functions as Runtime.getFunctions()[path].path
.
The injected through handler function this
object.
The common way to import a function is like this:
// In other way the code with Twilio should be like this.
const { functionToImportName: functionThatUsesTwilio } = require(Runtime.getFunctions()['path-to-your-function'].path)
And with the useTwilioImport
function you should start doing like this:
export const yourHandlerFunction = async function (event) {
const { prop1, prop2 } = event;
const twilio = useTwilioImport(this);
const functionThatUsesTwilio = twilio(
TWILIO_TYPES.Functions, // Could be "TWILIO_TYPES.Assets"
'functionToImportName',
'path-to-your-function'
);
const result = await functionThatUsesTwilio({ [prop1]: prop2 });
When using this approach your functionToImportName
have an object this
with { twilio: TwilioClient }
.
async function functionThatUsesTwilio (prop) {
return this.twilio.sync.v1 // And the rest of your code.
}
The pipe method could receive as many parameters as you desire. They will be called one after another. For async methods use pipeAsync
.
Any sync function.
const sum1 = (x) => x + 1;
const sum2 = (x) => x + 2;
const sum3 = (x) => x + 3;
const sum = pipe(sum1, sum2, sum3);
const result = sum(1) // return 7
// For async methods:
const asyncPiped = pipeAsync(async1, async2, async3);
const result = await asyncPiped(1) // return Promise { YOUR-VALUE }
The transformListTo method takes two parameters. The first to apply as a handler and the last is a transformation function.
A Twilio Instance List method as twilio.calls.list
or twilio.records.list
.
A transformation function. You could use one of lib defaults as extract
or factory
.
const getCallSidList = transformListTo(twilio.calls.list, extract('sid'));
const callSidList = await getCallSidList(); // returns ['CA****', 'CA****', 'CA****', 'CA****']
The transformInstanceTo method takes two parameters. The first to apply as a handler and the last is a transformation function.
A Twilio Instance method as twilio.calls
or twilio.records
.
A transformation function. You could use one of lib defaults as extract
or factory
.
const getToNumber = transformInstanceTo(twilio.calls, extract('to'));
const toNumber = await getToNumber('CA****'); // returns "+956798915489"
The responses coming from the function destined to the handler must be returned as an instance of Response.
Response receives a string and a number (status code):
return new Response('Your pretty answer.', 200);
There are two failure response models, BadRequest and NotFound. Its use follows the same model.
const notFound = new NotFoundError('Your error message here.');
const badRequest = new BadRequestError('Your error message here.');
There is a proper response template to use with the TwiML format:
const twimlVoice = new Twilio.twiml
.VoiceResponse();
const enqueueVoice = twimlVoice
.enqueue({
action,
workflowSid,
})
.task('{}');
return new TwiMLResponse(twimlVoice, 201)
IMPORTANT TO USE REGULAR FUNCTIONS ➜ With arrow functions it doesn't work as expected as this
cannot be injected correctly.
function yourFunctionName() {
// ...
}
Get the context
, event
and request data
just by deconstructing the object this:
const { cookies, request, env, twilio, ...YOUR_BODY_VALUES } = this
Combine multiple functions to change the final result using one of the new
transformListTo
and transformInstanceTo
methods:
// File: functions/create-action.js
const { useInjection, Response, transformListTo, extract } = require('twilio-functions-utils');
async function createAction(event) {
const { cookies, request, env, twilio, ...attributes } = this
const findFromAttributes = transformListTo(twilio.calls.list, extract('sid'))
const calls = await findFromAttributes(attributes);
return new Response(calls, 200);
}
exports.handler = useInjection(createAction, {
validateToken: true, // When using Token Validator, the Request body must contain a valid Token from Twilio.
});
A simple method to discovery a value type. This is more specific then the original JavaScript typeof
.
It will return as Array
, Object
, String
, Number
, Symbol
.
Could be any JavaScript primitive value to be type checked.
const { typeOf } = require('twilio-functions-utils');
const type = typeOf('my name is Lorem');
const typeArray = typeOf(['one', 'two']);
const original = typeof ['one', 'two']
console.log(type) // String
console.log(typeArray) // Array
console.log(original) // object
A Factory method for your desired Class. It returns a function that works as the Class constructor and receive the Class constructor params.
Could be any JavaScript primitive value to be type checked.
class CustomCall {
constructor({ from, to, price }) {
this.from = from;
this.to = to;
this.price = price;
}
}
const customCallFactory = factory(CustomCall);
const call = customCallFactory({ from: '+987566498965', to: '+485797955646', price: 65 })
console.log(call.price) // return 65
The Twilio Serverless structure make it hard for testing sometimes. So this provides a method that works perfectly with useInjection ready functions. The useMock
act like useInjection but mocking some required fragments as getAssets
and getFunctions
.
The same function as used in useInjection
.
(Required) Set your jest
testing script with NODE_ENV=test
:
"scripts": {
"test": "NODE_ENV=test jest --collect-coverage --watchAll",
"start": "twilio-run",
"deploy": "twilio-run deploy"
}
Your files structures must be have assets
and functions
into first or second levels starting from src
(when in second level):
app/
├─ package.json
├─ node_modules/
├─ src/
│ ├─ functions/
│ ├─ assets/
or:
app/
├─ package.json
├─ functions/
├─ assets/
├─ node_modules/
Exports your function to be tested and your handler so it can be used by Twilio when in runtime:
async function functionToBeTested(event) {
const something = await someFunction(event)
return Response(something)
}
const handler = useInjection(functionToBeTested);
module.exports = { functionToBeTested, handler }; // <--
(Required) You always need to import the twilio.mock
for Response Twilio Global object on your testing files begining.
require('twilio-functions-utils/lib/twilio.mock');
Use Twilio Functions Utils useMock
to do the hard job and just write your tests with the generated function.
You can use Twilio.mockRequestResolvedValue
, Twilio.mockRequestImplementation
, Twilio.mockRequestRejectedValue
to Mock your Twilio API requests.
/* global describe, it, expect */
require('twilio-functions-utils/lib/twilio.mock');
const { useMock, Response } = require('twilio-functions-utils');
const { functionToBeTested } = require('../../functions/functionToBeTested'); // <-- Import here!
// Create the test function from the function to be tested
const fn = useMock(functionToBeTested, {
env: {
YOUR_ENV_VAR: 'value'
},
twilio: {
functionToMock: {}
}
});
describe('Function functionToBeTested', () => {
it('if {"someValue": true}', async () => {
const request = { TaskSid: '1234567', TaskAttributes: '{"someValue": true}' };
Twilio.mockRequestResolvedValue({
statusCode: 200,
body: {
sid: '1234567'
}
})
Twilio.mockRequestResolvedValue({
statusCode: 200,
body: {
key: "MP****",
data: { sid: '7654321' }
}
})
const res = await fn(request);
const customMap = await Runtime.getSync().maps("MP****").fetch();
expect(res).toBeInstanceOf(Response);
expect(res.body).not.toEqual(request);
expect(res.data).toEqual({ sid: '7654321' });
expect(res.body).toEqual({ sid: '1234567' });
});
});
FAQs
Twilio Functions utils library
The npm package twilio-functions-utils receives a total of 37 weekly downloads. As such, twilio-functions-utils popularity was classified as not popular.
We found that twilio-functions-utils demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.